Home | History | Annotate | Download | only in Analysis
      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 
      4 void clang_analyzer_eval(int);
      5 
      6 struct S {
      7   int field;
      8 
      9 #if __cplusplus
     10   const struct S *getThis() const { return this; }
     11 #endif
     12 };
     13 
     14 struct S getS();
     15 
     16 
     17 void testAssignment() {
     18   struct S s = getS();
     19 
     20   if (s.field != 42) return;
     21   clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
     22 
     23   s.field = 0;
     24   clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}}
     25 
     26 #if __cplusplus
     27   clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
     28 #endif
     29 }
     30 
     31 
     32 void testImmediateUse() {
     33   int x = getS().field;
     34 
     35   if (x != 42) return;
     36   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
     37 
     38 #if __cplusplus
     39   clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}
     40 #endif
     41 }
     42 
     43 int getConstrainedField(struct S s) {
     44   if (s.field != 42) return 42;
     45   return s.field;
     46 }
     47 
     48 int getAssignedField(struct S s) {
     49   s.field = 42;
     50   return s.field;
     51 }
     52 
     53 void testArgument() {
     54   clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
     55 #if __cplusplus
     56   // FIXME: Passing the struct by value seems to be confusing C++.
     57   // Possibly related to <rdar://problem/12137950>.
     58   // expected-warning@-4{{UNKNOWN}}
     59 #endif
     60 
     61   clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
     62 }
     63 
     64 
     65 //--------------------
     66 // C++-only tests
     67 //--------------------
     68 
     69 #if __cplusplus
     70 void testReferenceAssignment() {
     71   const S &s = getS();
     72 
     73   if (s.field != 42) return;
     74   clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
     75 
     76   clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
     77 }
     78 
     79 
     80 int getConstrainedFieldRef(const S &s) {
     81   if (s.field != 42) return 42;
     82   return s.field;
     83 }
     84 
     85 bool checkThis(const S &s) {
     86   return s.getThis() == &s;
     87 }
     88 
     89 void testReferenceArgument() {
     90   clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
     91   clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
     92 }
     93 #endif
     94