summaryrefslogtreecommitdiffstats
path: root/test/Analysis/derived-to-base.cpp
blob: f8336785de8facf9df6e2941255bc370f0964359 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify %s

void clang_analyzer_eval(bool);

class A {
protected:
  int x;
};

class B : public A {
public:
  void f();
};

void B::f() {
  x = 3;
}


class C : public B {
public:
  void g() {
    // This used to crash because we are upcasting through two bases.
    x = 5;
  }
};


namespace VirtualBaseClasses {
  class A {
  protected:
    int x;
  };

  class B : public virtual A {
  public:
    int getX() { return x; }
  };

  class C : public virtual A {
  public:
    void setX() { x = 42; }
  };

  class D : public B, public C {};
  class DV : virtual public B, public C {};
  class DV2 : public B, virtual public C {};

  void test() {
    D d;
    d.setX();
    clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}

    DV dv;
    dv.setX();
    clang_analyzer_eval(dv.getX() == 42); // expected-warning{{TRUE}}

    DV2 dv2;
    dv2.setX();
    clang_analyzer_eval(dv2.getX() == 42); // expected-warning{{TRUE}}
  }


  // Make sure we're consistent about the offset of the A subobject within an
  // Intermediate virtual base class.
  class Padding1 { int unused; };
  class Padding2 { int unused; };
  class Intermediate : public Padding1, public A, public Padding2 {};

  class BI : public virtual Intermediate {
  public:
    int getX() { return x; }
  };

  class CI : public virtual Intermediate {
  public:
    void setX() { x = 42; }
  };

  class DI : public BI, public CI {};

  void testIntermediate() {
    DI d;
    d.setX();
    clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
  }
}


namespace DynamicVirtualUpcast {
  class A {
  public:
    virtual ~A();
  };

  class B : virtual public A {};
  class C : virtual public B {};
  class D : virtual public C {};

  bool testCast(A *a) {
    return dynamic_cast<B*>(a) && dynamic_cast<C*>(a);
  }

  void test() {
    D d;
    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
  }
}

namespace DynamicMultipleInheritanceUpcast {
  class B {
  public:
    virtual ~B();
  };
  class C {
  public:
    virtual ~C();
  };
  class D : public B, public C {};

  bool testCast(B *a) {
    return dynamic_cast<C*>(a);
  }

  void test() {
    D d;
    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
  }


  class DV : virtual public B, virtual public C {};

  void testVirtual() {
    DV d;
    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
  }
}
OpenPOWER on IntegriCloud