1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c %s 2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c++ -analyzer-config c++-inlining=constructors %s 3 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c %s 4 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c++ -analyzer-config c++-inlining=constructors %s 5 6 void clang_analyzer_eval(int); 7 8 struct S { 9 int field; 10 11 #if __cplusplus 12 const struct S *getThis() const { return this; } 13 #endif 14 }; 15 16 #ifdef INLINE 17 struct S getS() { 18 struct S s = { 42 }; 19 return s; 20 } 21 #else 22 struct S getS(); 23 #endif 24 25 26 void testAssignment() { 27 struct S s = getS(); 28 29 if (s.field != 42) return; 30 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}} 31 32 s.field = 0; 33 clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}} 34 35 #if __cplusplus 36 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}} 37 #endif 38 } 39 40 41 void testImmediateUse() { 42 int x = getS().field; 43 44 if (x != 42) return; 45 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} 46 47 #if __cplusplus 48 clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}} 49 #endif 50 } 51 52 int getConstrainedField(struct S s) { 53 if (s.field != 42) return 42; 54 return s.field; 55 } 56 57 int getAssignedField(struct S s) { 58 s.field = 42; 59 return s.field; 60 } 61 62 void testArgument() { 63 clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}} 64 #if __cplusplus 65 // FIXME: Passing the struct by value seems to be confusing C++. 66 // Possibly related to <rdar://problem/12137950>. 67 // expected-warning@-4{{UNKNOWN}} 68 #endif 69 70 clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}} 71 } 72 73 74 //-------------------- 75 // C++-only tests 76 //-------------------- 77 78 #if __cplusplus 79 void testReferenceAssignment() { 80 const S &s = getS(); 81 82 if (s.field != 42) return; 83 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}} 84 85 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}} 86 } 87 88 89 int getConstrainedFieldRef(const S &s) { 90 if (s.field != 42) return 42; 91 return s.field; 92 } 93 94 bool checkThis(const S &s) { 95 return s.getThis() == &s; 96 } 97 98 void testReferenceArgument() { 99 clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}} 100 clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}} 101 } 102 #endif 103