1 // RUN: %clang_analyze_cc1 -Wno-unused-value -std=c++14 -analyzer-checker=core,debug.ExprInspection,alpha.core.PointerArithm -verify %s
2 
3 template <typename T> void clang_analyzer_dump(T);
4 
5 struct X {
6   int *p;
7   int zero;
fooX8   void foo () {
9     reset(p - 1);
10   }
resetX11   void reset(int *in) {
12     while (in != p) // Loop must be entered.
13       zero = 1;
14   }
15 };
16 
test(int * in)17 int test (int *in) {
18   X littleX;
19   littleX.zero = 0;
20   littleX.p = in;
21   littleX.foo();
22   return 5/littleX.zero; // no-warning
23 }
24 
25 
26 class Base {};
27 class Derived : public Base {};
28 
checkPolymorphicUse()29 void checkPolymorphicUse() {
30   Derived d[10];
31 
32   Base *p = d;
33   ++p; // expected-warning{{Pointer arithmetic on a pointer to base class is dangerous}}
34 }
35 
checkBitCasts()36 void checkBitCasts() {
37   long l;
38   char *p = (char*)&l;
39   p = p+2;
40 }
41 
checkBasicarithmetic(int i)42 void checkBasicarithmetic(int i) {
43   int t[10];
44   int *p = t;
45   ++p;
46   int a = 5;
47   p = &a;
48   ++p; // expected-warning{{Pointer arithmetic on non-array variables relies on memory layout, which is dangerous}}
49   p = p + 2; // expected-warning{{}}
50   p = 2 + p; // expected-warning{{}}
51   p += 2; // expected-warning{{}}
52   a += p[2]; // expected-warning{{}}
53   p = i*0 + p;
54   p = p + i*0;
55   p += i*0;
56 }
57 
checkArithOnSymbolic(int * p)58 void checkArithOnSymbolic(int*p) {
59   ++p;
60   p = p + 2;
61   p = 2 + p;
62   p += 2;
63   (void)p[2];
64 }
65 
66 struct S {
67   int t[10];
68 };
69 
arrayInStruct()70 void arrayInStruct() {
71   S s;
72   int * p = s.t;
73   ++p;
74   S *sp = new S;
75   p = sp->t;
76   ++p;
77   delete sp;
78 }
79 
checkNew()80 void checkNew() {
81   int *p = new int;
82   p[1] = 1; // expected-warning{{}}
83 }
84 
InitState(int * state)85 void InitState(int* state) {
86     state[1] = 1; // expected-warning{{}}
87 }
88 
getArray(int size)89 int* getArray(int size) {
90     if (size == 0)
91       return new int;
92     return new int[5];
93 }
94 
checkConditionalArray()95 void checkConditionalArray() {
96     int* maybeArray = getArray(0);
97     InitState(maybeArray);
98 }
99 
checkMultiDimansionalArray()100 void checkMultiDimansionalArray() {
101   int a[5][5];
102    *(*(a+1)+2) = 2;
103 }
104 
ptrSubtractionNoCrash(char * Begin,char * End)105 unsigned ptrSubtractionNoCrash(char *Begin, char *End) {
106   auto N = End - Begin;
107   if (Begin)
108     return 0;
109   return N;
110 }
111 
112 // Bug 34309
ptrAsIntegerSubtractionNoCrash(__UINTPTR_TYPE__ x,char * p)113 bool ptrAsIntegerSubtractionNoCrash(__UINTPTR_TYPE__ x, char *p) {
114   __UINTPTR_TYPE__ y = (__UINTPTR_TYPE__)p - 1;
115   return y == x;
116 }
117 
118 // Bug 34374
integerAsPtrSubtractionNoCrash(char * p,__UINTPTR_TYPE__ m)119 bool integerAsPtrSubtractionNoCrash(char *p, __UINTPTR_TYPE__ m) {
120   auto n = p - reinterpret_cast<char*>((__UINTPTR_TYPE__)1);
121   return n == m;
122 }
123 
124 namespace Bug_55934 {
125 struct header {
126   unsigned a : 1;
127   unsigned b : 1;
128 };
129 struct parse_t {
130   unsigned bits0 : 1;
131   unsigned bits2 : 2; // <-- header
132   unsigned bits4 : 4;
133 };
parse(parse_t * p)134 int parse(parse_t *p) {
135   unsigned copy = p->bits2;
136   clang_analyzer_dump(copy);
137   // expected-warning@-1 {{reg_$1<unsigned int SymRegion{reg_$0<struct Bug_55934::parse_t * p>}.bits2>}}
138   header *bits = (header *)&copy;
139   clang_analyzer_dump(bits->b);
140   // expected-warning@-1 {{derived_$2{reg_$1<unsigned int SymRegion{reg_$0<struct Bug_55934::parse_t * p>}.bits2>,Element{copy,0 S64b,struct Bug_55934::header}.b}}}
141   return bits->b; // no-warning
142 }
143 } // namespace Bug_55934
144