135dbd0b1SArtem Dergachev // RUN: %clang_analyze_cc1 -w -analyzer-checker=core -verify %s
235dbd0b1SArtem Dergachev 
335dbd0b1SArtem Dergachev // expected-no-diagnostics
435dbd0b1SArtem Dergachev 
5*fec4c1a1SArtem Dergachev typedef __typeof(sizeof(int)) size_t;
operator new(size_t,void * h)6*fec4c1a1SArtem Dergachev void *operator new(size_t, void *h) { return h; }
735dbd0b1SArtem Dergachev 
835dbd0b1SArtem Dergachev // I've no idea what this code does, but it used to crash, so let's keep it.
935dbd0b1SArtem Dergachev namespace pr37802_v1 {
1035dbd0b1SArtem Dergachev struct J {
1135dbd0b1SArtem Dergachev   int *p;
1235dbd0b1SArtem Dergachev };
1335dbd0b1SArtem Dergachev class X {
1435dbd0b1SArtem Dergachev   void *ar;
1535dbd0b1SArtem Dergachev 
1635dbd0b1SArtem Dergachev public:
X(void * t)1735dbd0b1SArtem Dergachev   X(void *t) : ar(t) {}
1835dbd0b1SArtem Dergachev   template <typename T>
f(const T & t)1935dbd0b1SArtem Dergachev   void f(const T &t) {
2035dbd0b1SArtem Dergachev     new (ar) T(t);
2135dbd0b1SArtem Dergachev   }
2235dbd0b1SArtem Dergachev };
2335dbd0b1SArtem Dergachev class Y {
2435dbd0b1SArtem Dergachev public:
2535dbd0b1SArtem Dergachev   template <typename T>
2635dbd0b1SArtem Dergachev   void f(T &&);
f(J t)2735dbd0b1SArtem Dergachev   void f(J t) {
2835dbd0b1SArtem Dergachev     f(*t.p);
2935dbd0b1SArtem Dergachev   }
3035dbd0b1SArtem Dergachev };
3135dbd0b1SArtem Dergachev class Z {
at() const3235dbd0b1SArtem Dergachev   int at() const {}
3335dbd0b1SArtem Dergachev 
3435dbd0b1SArtem Dergachev public:
Z(const Z & other)3535dbd0b1SArtem Dergachev   Z(const Z &other) {
3635dbd0b1SArtem Dergachev     other.au(X(this));
3735dbd0b1SArtem Dergachev   }
3835dbd0b1SArtem Dergachev   template <typename T>
au(T t) const3935dbd0b1SArtem Dergachev   void au(T t) const {
4035dbd0b1SArtem Dergachev     void *c = const_cast<Z *>(this);
4135dbd0b1SArtem Dergachev     if (at()) {
4235dbd0b1SArtem Dergachev       t.f(*static_cast<J *>(c));
4335dbd0b1SArtem Dergachev     } else {
4435dbd0b1SArtem Dergachev       t.f(*static_cast<bool *>(c));
4535dbd0b1SArtem Dergachev     }
4635dbd0b1SArtem Dergachev   }
4735dbd0b1SArtem Dergachev };
g()4835dbd0b1SArtem Dergachev Z g() {
4935dbd0b1SArtem Dergachev   Z az = g();
5035dbd0b1SArtem Dergachev   Z e = az;
5135dbd0b1SArtem Dergachev   Y d;
5235dbd0b1SArtem Dergachev   e.au(d);
5335dbd0b1SArtem Dergachev }
5435dbd0b1SArtem Dergachev } // namespace pr37802_v1
5535dbd0b1SArtem Dergachev 
5635dbd0b1SArtem Dergachev 
5735dbd0b1SArtem Dergachev // This slightly modified code crashed differently.
5835dbd0b1SArtem Dergachev namespace pr37802_v2 {
5935dbd0b1SArtem Dergachev struct J {
6035dbd0b1SArtem Dergachev   int *p;
6135dbd0b1SArtem Dergachev };
6235dbd0b1SArtem Dergachev 
6335dbd0b1SArtem Dergachev class X {
6435dbd0b1SArtem Dergachev   void *ar;
6535dbd0b1SArtem Dergachev 
6635dbd0b1SArtem Dergachev public:
X(void * t)6735dbd0b1SArtem Dergachev   X(void *t) : ar(t) {}
f(const J & t)6835dbd0b1SArtem Dergachev   void f(const J &t) { new (ar) J(t); }
f(const bool & t)6935dbd0b1SArtem Dergachev   void f(const bool &t) { new (ar) bool(t); }
7035dbd0b1SArtem Dergachev };
7135dbd0b1SArtem Dergachev 
7235dbd0b1SArtem Dergachev class Y {
7335dbd0b1SArtem Dergachev public:
7435dbd0b1SArtem Dergachev   void boolf(bool &&);
7535dbd0b1SArtem Dergachev   void f(J &&);
f(J t)7635dbd0b1SArtem Dergachev   void f(J t) { boolf(*t.p); }
7735dbd0b1SArtem Dergachev };
7835dbd0b1SArtem Dergachev 
7935dbd0b1SArtem Dergachev class Z {
at() const8035dbd0b1SArtem Dergachev   int at() const {}
8135dbd0b1SArtem Dergachev 
8235dbd0b1SArtem Dergachev public:
Z(const Z & other)8335dbd0b1SArtem Dergachev   Z(const Z &other) { other.au(X(this)); }
au(X t) const8435dbd0b1SArtem Dergachev   void au(X t) const {
8535dbd0b1SArtem Dergachev     void *c = const_cast<Z *>(this);
8635dbd0b1SArtem Dergachev     if (at()) {
8735dbd0b1SArtem Dergachev       t.f(*static_cast<J *>(c));
8835dbd0b1SArtem Dergachev     } else {
8935dbd0b1SArtem Dergachev       t.f(*static_cast<bool *>(c));
9035dbd0b1SArtem Dergachev     }
9135dbd0b1SArtem Dergachev   }
au(Y t) const9235dbd0b1SArtem Dergachev   void au(Y t) const {
9335dbd0b1SArtem Dergachev     void *c = const_cast<Z *>(this);
9435dbd0b1SArtem Dergachev     if (at()) {
9535dbd0b1SArtem Dergachev       t.f(*static_cast<J *>(c));
9635dbd0b1SArtem Dergachev     } else {
9735dbd0b1SArtem Dergachev     }
9835dbd0b1SArtem Dergachev   }
9935dbd0b1SArtem Dergachev };
10035dbd0b1SArtem Dergachev 
g()10135dbd0b1SArtem Dergachev Z g() {
10235dbd0b1SArtem Dergachev   Z az = g();
10335dbd0b1SArtem Dergachev   Z e = az;
10435dbd0b1SArtem Dergachev   Y d;
10535dbd0b1SArtem Dergachev   e.au(d);
10635dbd0b1SArtem Dergachev }
10735dbd0b1SArtem Dergachev } // namespace pr37802_v2
108