265 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\2// RUN: -analyzer-checker=debug.ExprInspection -verify\3// RUN: -Wno-tautological-compare\4// RUN: -x c %s5// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\6// RUN: -analyzer-checker=debug.ExprInspection -verify\7// RUN: -Wno-tautological-compare\8// RUN: -x c++ -std=c++14 %s9// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\10// RUN: -analyzer-checker=debug.ExprInspection -verify\11// RUN: -Wno-tautological-compare\12// RUN: -x c++ -std=c++17 %s13// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\14// RUN: -analyzer-checker=debug.ExprInspection -verify\15// RUN: -Wno-tautological-compare\16// RUN: -DINLINE -x c %s17// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\18// RUN: -analyzer-checker=debug.ExprInspection -verify\19// RUN: -Wno-tautological-compare\20// RUN: -DINLINE -x c++ -std=c++14 %s21// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\22// RUN: -analyzer-checker=debug.ExprInspection -verify\23// RUN: -Wno-tautological-compare\24// RUN: -DINLINE -x c++ -std=c++17 %s25 26void clang_analyzer_eval(int);27 28struct S {29 int field;30 31#if __cplusplus32 const struct S *getThis() const { return this; }33 const struct S *operator +() const { return this; }34 35 bool check() const { return this == this; }36 bool operator !() const { return this != this; }37 38 int operator *() const { return field; }39#endif40};41 42#if __cplusplus43const struct S *operator -(const struct S &s) { return &s; }44bool operator ~(const struct S &s) { return (&s) != &s; }45#endif46 47 48#ifdef INLINE49struct S getS(void) {50 struct S s = { 42 };51 return s;52}53#else54struct S getS(void);55#endif56 57 58void testAssignment(void) {59 struct S s = getS();60 61 if (s.field != 42) return;62 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}63 64 s.field = 0;65 clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}}66 67#if __cplusplus68 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}69 clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}70 clang_analyzer_eval(-s == &s); // expected-warning{{TRUE}}71 72 clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}73 clang_analyzer_eval(!s); // expected-warning{{FALSE}}74 clang_analyzer_eval(~s); // expected-warning{{FALSE}}75 76 clang_analyzer_eval(*s == 0); // expected-warning{{TRUE}}77#endif78}79 80 81void testImmediateUse(void) {82 int x = getS().field;83 84 if (x != 42) return;85 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}86 87#if __cplusplus88 clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}89 clang_analyzer_eval((void *)+getS() == (void *)&x); // expected-warning{{FALSE}}90 clang_analyzer_eval((void *)-getS() == (void *)&x); // expected-warning{{FALSE}}91 92 clang_analyzer_eval(getS().check()); // expected-warning{{TRUE}}93 clang_analyzer_eval(!getS()); // expected-warning{{FALSE}}94 clang_analyzer_eval(~getS()); // expected-warning{{FALSE}}95#endif96}97 98int getConstrainedField(struct S s) {99 if (s.field != 42) return 42;100 return s.field;101}102 103int getAssignedField(struct S s) {104 s.field = 42;105 return s.field;106}107 108void testArgument(void) {109 clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}110 clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}111}112 113void testImmediateUseParens(void) {114 int x = ((getS())).field;115 116 if (x != 42) return;117 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}118 119 clang_analyzer_eval(getConstrainedField(((getS()))) == 42); // expected-warning{{TRUE}}120 clang_analyzer_eval(getAssignedField(((getS()))) == 42); // expected-warning{{TRUE}}121 122#if __cplusplus123 clang_analyzer_eval(((getS())).check()); // expected-warning{{TRUE}}124 clang_analyzer_eval(!((getS()))); // expected-warning{{FALSE}}125 clang_analyzer_eval(~((getS()))); // expected-warning{{FALSE}}126#endif127}128 129 130//--------------------131// C++-only tests132//--------------------133 134#if __cplusplus135void testReferenceAssignment() {136 const S &s = getS();137 138 if (s.field != 42) return;139 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}140 141 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}142 clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}143 144 clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}145 clang_analyzer_eval(!s); // expected-warning{{FALSE}}146 clang_analyzer_eval(~s); // expected-warning{{FALSE}}147 148 clang_analyzer_eval(*s == 42); // expected-warning{{TRUE}}149}150 151 152int getConstrainedFieldRef(const S &s) {153 if (s.field != 42) return 42;154 return s.field;155}156 157bool checkThis(const S &s) {158 return s.getThis() == &s;159}160 161bool checkThisOp(const S &s) {162 return +s == &s;163}164 165bool checkThisStaticOp(const S &s) {166 return -s == &s;167}168 169void testReferenceArgument() {170 clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}171 clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}172 clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}}173 clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}}174}175 176 177int getConstrainedFieldOp(S s) {178 if (*s != 42) return 42;179 return *s;180}181 182int getConstrainedFieldRefOp(const S &s) {183 if (*s != 42) return 42;184 return *s;185}186 187void testImmediateUseOp() {188 int x = *getS();189 if (x != 42) return;190 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}191 192 clang_analyzer_eval(getConstrainedFieldOp(getS()) == 42); // expected-warning{{TRUE}}193 clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}}194}195 196namespace EmptyClass {197 struct Base {198 int& x;199 200 Base(int& x) : x(x) {}201 };202 203 struct Derived : public Base {204 Derived(int& x) : Base(x) {}205 206 void operator=(int a) { x = a; }207 };208 209 Derived ref(int& a) { return Derived(a); }210 211 // There used to be a warning here, because analyzer treated Derived as empty.212 int test() {213 int a;214 ref(a) = 42;215 return a; // no warning216 }217}218 219#if __cplusplus >= 201703L220namespace aggregate_inheritance_cxx17 {221struct A {222 int x;223};224 225struct B {226 int y;227};228 229struct C: B {230 int z;231};232 233struct D: A, C {234 int w;235};236 237void foo() {238 D d{1, 2, 3, 4};239 clang_analyzer_eval(d.x == 1); // expected-warning{{TRUE}}240 clang_analyzer_eval(d.y == 2); // expected-warning{{TRUE}}241 clang_analyzer_eval(d.z == 3); // expected-warning{{TRUE}}242 clang_analyzer_eval(d.w == 4); // expected-warning{{TRUE}}243}244} // namespace aggregate_inheritance_cxx17245#endif246 247namespace flex_array_inheritance_cxx17 {248struct A {249 int flexible_array[];250};251 252struct B {253 long cookie;254};255 256struct C : B {257 A a;258};259 260void foo() {261 C c{}; // no-crash262}263} // namespace flex_array_inheritance_cxx17264#endif265