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 const struct S *operator +() const { return this; } 14 15 bool check() const { return this == this; } 16 bool operator !() const { return this != this; } 17 18 int operator *() const { return field; } 19 #endif 20 }; 21 22 #if __cplusplus 23 const struct S *operator -(const struct S &s) { return &s; } 24 bool operator ~(const struct S &s) { return &s != &s; } 25 #endif 26 27 28 #ifdef INLINE 29 struct S getS() { 30 struct S s = { 42 }; 31 return s; 32 } 33 #else 34 struct S getS(); 35 #endif 36 37 38 void testAssignment() { 39 struct S s = getS(); 40 41 if (s.field != 42) return; 42 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}} 43 44 s.field = 0; 45 clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}} 46 47 #if __cplusplus 48 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}} 49 clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}} 50 clang_analyzer_eval(-s == &s); // expected-warning{{TRUE}} 51 52 clang_analyzer_eval(s.check()); // expected-warning{{TRUE}} 53 clang_analyzer_eval(!s); // expected-warning{{FALSE}} 54 clang_analyzer_eval(~s); // expected-warning{{FALSE}} 55 56 clang_analyzer_eval(*s == 0); // expected-warning{{TRUE}} 57 #endif 58 } 59 60 61 void testImmediateUse() { 62 int x = getS().field; 63 64 if (x != 42) return; 65 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} 66 67 #if __cplusplus 68 clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}} 69 clang_analyzer_eval((void *)+getS() == (void *)&x); // expected-warning{{FALSE}} 70 clang_analyzer_eval((void *)-getS() == (void *)&x); // expected-warning{{FALSE}} 71 72 clang_analyzer_eval(getS().check()); // expected-warning{{TRUE}} 73 clang_analyzer_eval(!getS()); // expected-warning{{FALSE}} 74 clang_analyzer_eval(~getS()); // expected-warning{{FALSE}} 75 #endif 76 } 77 78 int getConstrainedField(struct S s) { 79 if (s.field != 42) return 42; 80 return s.field; 81 } 82 83 int getAssignedField(struct S s) { 84 s.field = 42; 85 return s.field; 86 } 87 88 void testArgument() { 89 clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}} 90 clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}} 91 } 92 93 94 //-------------------- 95 // C++-only tests 96 //-------------------- 97 98 #if __cplusplus 99 void testReferenceAssignment() { 100 const S &s = getS(); 101 102 if (s.field != 42) return; 103 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}} 104 105 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}} 106 clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}} 107 108 clang_analyzer_eval(s.check()); // expected-warning{{TRUE}} 109 clang_analyzer_eval(!s); // expected-warning{{FALSE}} 110 clang_analyzer_eval(~s); // expected-warning{{FALSE}} 111 112 clang_analyzer_eval(*s == 42); // expected-warning{{TRUE}} 113 } 114 115 116 int getConstrainedFieldRef(const S &s) { 117 if (s.field != 42) return 42; 118 return s.field; 119 } 120 121 bool checkThis(const S &s) { 122 return s.getThis() == &s; 123 } 124 125 bool checkThisOp(const S &s) { 126 return +s == &s; 127 } 128 129 bool checkThisStaticOp(const S &s) { 130 return -s == &s; 131 } 132 133 void testReferenceArgument() { 134 clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}} 135 clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}} 136 clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}} 137 clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}} 138 } 139 140 141 int getConstrainedFieldOp(S s) { 142 if (*s != 42) return 42; 143 return *s; 144 } 145 146 int getConstrainedFieldRefOp(const S &s) { 147 if (*s != 42) return 42; 148 return *s; 149 } 150 151 void testImmediateUseOp() { 152 int x = *getS(); 153 if (x != 42) return; 154 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} 155 156 clang_analyzer_eval(getConstrainedFieldOp(getS()) == 42); // expected-warning{{TRUE}} 157 clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}} 158 } 159 160 #endif 161