mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-15 12:39:19 +00:00
3d90e7e8db
This reverts commit r352473. The overall idea is great, but it seems to cause unintented consequences when not only Region Store invalidation but also pointer escape mechanism was accidentally affected. Based on discussions in https://reviews.llvm.org/D58121#1452483 and https://reviews.llvm.org/D57230#1434161 Differential Revision: https://reviews.llvm.org/D57230 llvm-svn: 357620
168 lines
4.4 KiB
C++
168 lines
4.4 KiB
C++
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
|
|
|
|
void clang_analyzer_eval(bool);
|
|
|
|
void usePointer(int * const *);
|
|
void useReference(int * const &);
|
|
|
|
void testPointer() {
|
|
int x;
|
|
int *p;
|
|
|
|
p = &x;
|
|
x = 42;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
usePointer(&p);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
|
|
|
|
p = &x;
|
|
x = 42;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
useReference(p);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
|
|
|
|
int * const cp1 = &x;
|
|
x = 42;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
usePointer(&cp1);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
|
|
|
|
int * const cp2 = &x;
|
|
x = 42;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
useReference(cp2);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
|
|
}
|
|
|
|
|
|
struct Wrapper {
|
|
int *ptr;
|
|
};
|
|
|
|
void useStruct(Wrapper &w);
|
|
void useConstStruct(const Wrapper &w);
|
|
|
|
void testPointerStruct() {
|
|
int x;
|
|
Wrapper w;
|
|
|
|
w.ptr = &x;
|
|
x = 42;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
useStruct(w);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
|
|
|
|
w.ptr = &x;
|
|
x = 42;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
useConstStruct(w);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
|
|
}
|
|
|
|
|
|
struct RefWrapper {
|
|
int &ref;
|
|
};
|
|
|
|
void useStruct(RefWrapper &w);
|
|
void useConstStruct(const RefWrapper &w);
|
|
|
|
void testReferenceStruct() {
|
|
int x;
|
|
RefWrapper w = { x };
|
|
|
|
x = 42;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
useStruct(w);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
|
|
}
|
|
|
|
// FIXME: This test is split into two functions because region invalidation
|
|
// does not preserve reference bindings. <rdar://problem/13320347>
|
|
void testConstReferenceStruct() {
|
|
int x;
|
|
RefWrapper w = { x };
|
|
|
|
x = 42;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
useConstStruct(w);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
|
|
}
|
|
|
|
|
|
void usePointerPure(int * const *) __attribute__((pure));
|
|
void usePointerConst(int * const *) __attribute__((const));
|
|
|
|
void testPureConst() {
|
|
extern int global;
|
|
int x;
|
|
int *p;
|
|
|
|
p = &x;
|
|
x = 42;
|
|
global = -5;
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
|
|
|
|
usePointerPure(&p);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
|
|
|
|
usePointerConst(&p);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
|
|
|
|
usePointer(&p);
|
|
clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
|
|
clang_analyzer_eval(global == -5); // expected-warning{{UNKNOWN}}
|
|
}
|
|
|
|
|
|
struct PlainStruct {
|
|
int x, y;
|
|
mutable int z;
|
|
};
|
|
|
|
PlainStruct glob;
|
|
|
|
void useAnything(void *);
|
|
void useAnythingConst(const void *);
|
|
|
|
void testInvalidationThroughBaseRegionPointer() {
|
|
PlainStruct s1;
|
|
s1.x = 1;
|
|
s1.z = 1;
|
|
clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
|
|
// Not only passing a structure pointer through const pointer parameter,
|
|
// but also passing a field pointer through const pointer parameter
|
|
// should preserve the contents of the structure.
|
|
useAnythingConst(&(s1.y));
|
|
clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
|
|
// FIXME: Should say "UNKNOWN", because it is not uncommon to
|
|
// modify a mutable member variable through const pointer.
|
|
clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
|
|
useAnything(&(s1.y));
|
|
clang_analyzer_eval(s1.x == 1); // expected-warning{{UNKNOWN}}
|
|
}
|
|
|
|
|
|
void useFirstConstSecondNonConst(const void *x, void *y);
|
|
void useFirstNonConstSecondConst(void *x, const void *y);
|
|
|
|
void testMixedConstNonConstCalls() {
|
|
PlainStruct s2;
|
|
s2.x = 1;
|
|
useFirstConstSecondNonConst(&(s2.x), &(s2.y));
|
|
clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}
|
|
s2.x = 1;
|
|
useFirstNonConstSecondConst(&(s2.x), &(s2.y));
|
|
clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}
|
|
s2.y = 1;
|
|
useFirstConstSecondNonConst(&(s2.x), &(s2.y));
|
|
clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}
|
|
s2.y = 1;
|
|
useFirstNonConstSecondConst(&(s2.x), &(s2.y));
|
|
clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}
|
|
}
|