1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c %s 2*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c++ -analyzer-config c++-inlining=constructors %s 3*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c %s 4*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c++ -analyzer-config c++-inlining=constructors %s 5*f4a2713aSLionel Sambuc 6*f4a2713aSLionel Sambuc void clang_analyzer_eval(int); 7*f4a2713aSLionel Sambuc 8*f4a2713aSLionel Sambuc struct S { 9*f4a2713aSLionel Sambuc int field; 10*f4a2713aSLionel Sambuc 11*f4a2713aSLionel Sambuc #if __cplusplus getThisS12*f4a2713aSLionel Sambuc const struct S *getThis() const { return this; } operator +S13*f4a2713aSLionel Sambuc const struct S *operator +() const { return this; } 14*f4a2713aSLionel Sambuc checkS15*f4a2713aSLionel Sambuc bool check() const { return this == this; } operator !S16*f4a2713aSLionel Sambuc bool operator !() const { return this != this; } 17*f4a2713aSLionel Sambuc operator *S18*f4a2713aSLionel Sambuc int operator *() const { return field; } 19*f4a2713aSLionel Sambuc #endif 20*f4a2713aSLionel Sambuc }; 21*f4a2713aSLionel Sambuc 22*f4a2713aSLionel Sambuc #if __cplusplus operator -(const struct S & s)23*f4a2713aSLionel Sambucconst struct S *operator -(const struct S &s) { return &s; } operator ~(const struct S & s)24*f4a2713aSLionel Sambucbool operator ~(const struct S &s) { return (&s) != &s; } 25*f4a2713aSLionel Sambuc #endif 26*f4a2713aSLionel Sambuc 27*f4a2713aSLionel Sambuc 28*f4a2713aSLionel Sambuc #ifdef INLINE getS()29*f4a2713aSLionel Sambucstruct S getS() { 30*f4a2713aSLionel Sambuc struct S s = { 42 }; 31*f4a2713aSLionel Sambuc return s; 32*f4a2713aSLionel Sambuc } 33*f4a2713aSLionel Sambuc #else 34*f4a2713aSLionel Sambuc struct S getS(); 35*f4a2713aSLionel Sambuc #endif 36*f4a2713aSLionel Sambuc 37*f4a2713aSLionel Sambuc testAssignment()38*f4a2713aSLionel Sambucvoid testAssignment() { 39*f4a2713aSLionel Sambuc struct S s = getS(); 40*f4a2713aSLionel Sambuc 41*f4a2713aSLionel Sambuc if (s.field != 42) return; 42*f4a2713aSLionel Sambuc clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}} 43*f4a2713aSLionel Sambuc 44*f4a2713aSLionel Sambuc s.field = 0; 45*f4a2713aSLionel Sambuc clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}} 46*f4a2713aSLionel Sambuc 47*f4a2713aSLionel Sambuc #if __cplusplus 48*f4a2713aSLionel Sambuc clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}} 49*f4a2713aSLionel Sambuc clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}} 50*f4a2713aSLionel Sambuc clang_analyzer_eval(-s == &s); // expected-warning{{TRUE}} 51*f4a2713aSLionel Sambuc 52*f4a2713aSLionel Sambuc clang_analyzer_eval(s.check()); // expected-warning{{TRUE}} 53*f4a2713aSLionel Sambuc clang_analyzer_eval(!s); // expected-warning{{FALSE}} 54*f4a2713aSLionel Sambuc clang_analyzer_eval(~s); // expected-warning{{FALSE}} 55*f4a2713aSLionel Sambuc 56*f4a2713aSLionel Sambuc clang_analyzer_eval(*s == 0); // expected-warning{{TRUE}} 57*f4a2713aSLionel Sambuc #endif 58*f4a2713aSLionel Sambuc } 59*f4a2713aSLionel Sambuc 60*f4a2713aSLionel Sambuc testImmediateUse()61*f4a2713aSLionel Sambucvoid testImmediateUse() { 62*f4a2713aSLionel Sambuc int x = getS().field; 63*f4a2713aSLionel Sambuc 64*f4a2713aSLionel Sambuc if (x != 42) return; 65*f4a2713aSLionel Sambuc clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} 66*f4a2713aSLionel Sambuc 67*f4a2713aSLionel Sambuc #if __cplusplus 68*f4a2713aSLionel Sambuc clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}} 69*f4a2713aSLionel Sambuc clang_analyzer_eval((void *)+getS() == (void *)&x); // expected-warning{{FALSE}} 70*f4a2713aSLionel Sambuc clang_analyzer_eval((void *)-getS() == (void *)&x); // expected-warning{{FALSE}} 71*f4a2713aSLionel Sambuc 72*f4a2713aSLionel Sambuc clang_analyzer_eval(getS().check()); // expected-warning{{TRUE}} 73*f4a2713aSLionel Sambuc clang_analyzer_eval(!getS()); // expected-warning{{FALSE}} 74*f4a2713aSLionel Sambuc clang_analyzer_eval(~getS()); // expected-warning{{FALSE}} 75*f4a2713aSLionel Sambuc #endif 76*f4a2713aSLionel Sambuc } 77*f4a2713aSLionel Sambuc getConstrainedField(struct S s)78*f4a2713aSLionel Sambucint getConstrainedField(struct S s) { 79*f4a2713aSLionel Sambuc if (s.field != 42) return 42; 80*f4a2713aSLionel Sambuc return s.field; 81*f4a2713aSLionel Sambuc } 82*f4a2713aSLionel Sambuc getAssignedField(struct S s)83*f4a2713aSLionel Sambucint getAssignedField(struct S s) { 84*f4a2713aSLionel Sambuc s.field = 42; 85*f4a2713aSLionel Sambuc return s.field; 86*f4a2713aSLionel Sambuc } 87*f4a2713aSLionel Sambuc testArgument()88*f4a2713aSLionel Sambucvoid testArgument() { 89*f4a2713aSLionel Sambuc clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}} 90*f4a2713aSLionel Sambuc clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}} 91*f4a2713aSLionel Sambuc } 92*f4a2713aSLionel Sambuc testImmediateUseParens()93*f4a2713aSLionel Sambucvoid testImmediateUseParens() { 94*f4a2713aSLionel Sambuc int x = ((getS())).field; 95*f4a2713aSLionel Sambuc 96*f4a2713aSLionel Sambuc if (x != 42) return; 97*f4a2713aSLionel Sambuc clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} 98*f4a2713aSLionel Sambuc 99*f4a2713aSLionel Sambuc clang_analyzer_eval(getConstrainedField(((getS()))) == 42); // expected-warning{{TRUE}} 100*f4a2713aSLionel Sambuc clang_analyzer_eval(getAssignedField(((getS()))) == 42); // expected-warning{{TRUE}} 101*f4a2713aSLionel Sambuc 102*f4a2713aSLionel Sambuc #if __cplusplus 103*f4a2713aSLionel Sambuc clang_analyzer_eval(((getS())).check()); // expected-warning{{TRUE}} 104*f4a2713aSLionel Sambuc clang_analyzer_eval(!((getS()))); // expected-warning{{FALSE}} 105*f4a2713aSLionel Sambuc clang_analyzer_eval(~((getS()))); // expected-warning{{FALSE}} 106*f4a2713aSLionel Sambuc #endif 107*f4a2713aSLionel Sambuc } 108*f4a2713aSLionel Sambuc 109*f4a2713aSLionel Sambuc 110*f4a2713aSLionel Sambuc //-------------------- 111*f4a2713aSLionel Sambuc // C++-only tests 112*f4a2713aSLionel Sambuc //-------------------- 113*f4a2713aSLionel Sambuc 114*f4a2713aSLionel Sambuc #if __cplusplus testReferenceAssignment()115*f4a2713aSLionel Sambucvoid testReferenceAssignment() { 116*f4a2713aSLionel Sambuc const S &s = getS(); 117*f4a2713aSLionel Sambuc 118*f4a2713aSLionel Sambuc if (s.field != 42) return; 119*f4a2713aSLionel Sambuc clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}} 120*f4a2713aSLionel Sambuc 121*f4a2713aSLionel Sambuc clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}} 122*f4a2713aSLionel Sambuc clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}} 123*f4a2713aSLionel Sambuc 124*f4a2713aSLionel Sambuc clang_analyzer_eval(s.check()); // expected-warning{{TRUE}} 125*f4a2713aSLionel Sambuc clang_analyzer_eval(!s); // expected-warning{{FALSE}} 126*f4a2713aSLionel Sambuc clang_analyzer_eval(~s); // expected-warning{{FALSE}} 127*f4a2713aSLionel Sambuc 128*f4a2713aSLionel Sambuc clang_analyzer_eval(*s == 42); // expected-warning{{TRUE}} 129*f4a2713aSLionel Sambuc } 130*f4a2713aSLionel Sambuc 131*f4a2713aSLionel Sambuc getConstrainedFieldRef(const S & s)132*f4a2713aSLionel Sambucint getConstrainedFieldRef(const S &s) { 133*f4a2713aSLionel Sambuc if (s.field != 42) return 42; 134*f4a2713aSLionel Sambuc return s.field; 135*f4a2713aSLionel Sambuc } 136*f4a2713aSLionel Sambuc checkThis(const S & s)137*f4a2713aSLionel Sambucbool checkThis(const S &s) { 138*f4a2713aSLionel Sambuc return s.getThis() == &s; 139*f4a2713aSLionel Sambuc } 140*f4a2713aSLionel Sambuc checkThisOp(const S & s)141*f4a2713aSLionel Sambucbool checkThisOp(const S &s) { 142*f4a2713aSLionel Sambuc return +s == &s; 143*f4a2713aSLionel Sambuc } 144*f4a2713aSLionel Sambuc checkThisStaticOp(const S & s)145*f4a2713aSLionel Sambucbool checkThisStaticOp(const S &s) { 146*f4a2713aSLionel Sambuc return -s == &s; 147*f4a2713aSLionel Sambuc } 148*f4a2713aSLionel Sambuc testReferenceArgument()149*f4a2713aSLionel Sambucvoid testReferenceArgument() { 150*f4a2713aSLionel Sambuc clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}} 151*f4a2713aSLionel Sambuc clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}} 152*f4a2713aSLionel Sambuc clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}} 153*f4a2713aSLionel Sambuc clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}} 154*f4a2713aSLionel Sambuc } 155*f4a2713aSLionel Sambuc 156*f4a2713aSLionel Sambuc getConstrainedFieldOp(S s)157*f4a2713aSLionel Sambucint getConstrainedFieldOp(S s) { 158*f4a2713aSLionel Sambuc if (*s != 42) return 42; 159*f4a2713aSLionel Sambuc return *s; 160*f4a2713aSLionel Sambuc } 161*f4a2713aSLionel Sambuc getConstrainedFieldRefOp(const S & s)162*f4a2713aSLionel Sambucint getConstrainedFieldRefOp(const S &s) { 163*f4a2713aSLionel Sambuc if (*s != 42) return 42; 164*f4a2713aSLionel Sambuc return *s; 165*f4a2713aSLionel Sambuc } 166*f4a2713aSLionel Sambuc testImmediateUseOp()167*f4a2713aSLionel Sambucvoid testImmediateUseOp() { 168*f4a2713aSLionel Sambuc int x = *getS(); 169*f4a2713aSLionel Sambuc if (x != 42) return; 170*f4a2713aSLionel Sambuc clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} 171*f4a2713aSLionel Sambuc 172*f4a2713aSLionel Sambuc clang_analyzer_eval(getConstrainedFieldOp(getS()) == 42); // expected-warning{{TRUE}} 173*f4a2713aSLionel Sambuc clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}} 174*f4a2713aSLionel Sambuc } 175*f4a2713aSLionel Sambuc 176*f4a2713aSLionel Sambuc namespace EmptyClass { 177*f4a2713aSLionel Sambuc struct Base { 178*f4a2713aSLionel Sambuc int& x; 179*f4a2713aSLionel Sambuc BaseEmptyClass::Base180*f4a2713aSLionel Sambuc Base(int& x) : x(x) {} 181*f4a2713aSLionel Sambuc }; 182*f4a2713aSLionel Sambuc 183*f4a2713aSLionel Sambuc struct Derived : public Base { DerivedEmptyClass::Derived184*f4a2713aSLionel Sambuc Derived(int& x) : Base(x) {} 185*f4a2713aSLionel Sambuc operator =EmptyClass::Derived186*f4a2713aSLionel Sambuc void operator=(int a) { x = a; } 187*f4a2713aSLionel Sambuc }; 188*f4a2713aSLionel Sambuc ref(int & a)189*f4a2713aSLionel Sambuc Derived ref(int& a) { return Derived(a); } 190*f4a2713aSLionel Sambuc 191*f4a2713aSLionel Sambuc // There used to be a warning here, because analyzer treated Derived as empty. test()192*f4a2713aSLionel Sambuc int test() { 193*f4a2713aSLionel Sambuc int a; 194*f4a2713aSLionel Sambuc ref(a) = 42; 195*f4a2713aSLionel Sambuc return a; // no warning 196*f4a2713aSLionel Sambuc } 197*f4a2713aSLionel Sambuc } 198*f4a2713aSLionel Sambuc 199*f4a2713aSLionel Sambuc #endif 200