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 *)©
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