derived-to-base.cpp revision b11a3ada9a22e146c6edd33bcc6301e221fedd7a
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify %s
2
3void clang_analyzer_eval(bool);
4
5class A {
6protected:
7  int x;
8};
9
10class B : public A {
11public:
12  void f();
13};
14
15void B::f() {
16  x = 3;
17}
18
19
20class C : public B {
21public:
22  void g() {
23    // This used to crash because we are upcasting through two bases.
24    x = 5;
25  }
26};
27
28
29namespace VirtualBaseClasses {
30  class A {
31  protected:
32    int x;
33  };
34
35  class B : public virtual A {
36  public:
37    int getX() { return x; }
38  };
39
40  class C : public virtual A {
41  public:
42    void setX() { x = 42; }
43  };
44
45  class D : public B, public C {};
46  class DV : virtual public B, public C {};
47  class DV2 : public B, virtual public C {};
48
49  void test() {
50    D d;
51    d.setX();
52    clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
53
54    DV dv;
55    dv.setX();
56    clang_analyzer_eval(dv.getX() == 42); // expected-warning{{TRUE}}
57
58    DV2 dv2;
59    dv2.setX();
60    clang_analyzer_eval(dv2.getX() == 42); // expected-warning{{TRUE}}
61  }
62
63
64  // Make sure we're consistent about the offset of the A subobject within an
65  // Intermediate virtual base class.
66  class Padding1 { int unused; };
67  class Padding2 { int unused; };
68  class Intermediate : public Padding1, public A, public Padding2 {};
69
70  class BI : public virtual Intermediate {
71  public:
72    int getX() { return x; }
73  };
74
75  class CI : public virtual Intermediate {
76  public:
77    void setX() { x = 42; }
78  };
79
80  class DI : public BI, public CI {};
81
82  void testIntermediate() {
83    DI d;
84    d.setX();
85    clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
86  }
87}
88