aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Analysis/array-struct-region.cpp73
-rw-r--r--test/Analysis/fields.c12
-rw-r--r--test/Analysis/reference.cpp4
3 files changed, 85 insertions, 4 deletions
diff --git a/test/Analysis/array-struct-region.cpp b/test/Analysis/array-struct-region.cpp
index 3581566bdc..cffa64d21a 100644
--- a/test/Analysis/array-struct-region.cpp
+++ b/test/Analysis/array-struct-region.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c %s
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c++ -analyzer-config c++-inlining=constructors %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c++ -analyzer-config c++-inlining=constructors %s
void clang_analyzer_eval(int);
@@ -8,10 +10,29 @@ struct S {
#if __cplusplus
const struct S *getThis() const { return this; }
+ const struct S *operator +() const { return this; }
+
+ bool check() const { return this == this; }
+ bool operator !() const { return this != this; }
+
+ int operator *() const { return field; }
#endif
};
+#if __cplusplus
+const struct S *operator -(const struct S &s) { return &s; }
+bool operator ~(const struct S &s) { return &s != &s; }
+#endif
+
+
+#ifdef INLINE
+struct S getS() {
+ struct S s = { 42 };
+ return s;
+}
+#else
struct S getS();
+#endif
void testAssignment() {
@@ -25,6 +46,14 @@ void testAssignment() {
#if __cplusplus
clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
+ clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
+ clang_analyzer_eval(-s == &s); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
+ clang_analyzer_eval(!s); // expected-warning{{FALSE}}
+ clang_analyzer_eval(~s); // expected-warning{{FALSE}}
+
+ clang_analyzer_eval(*s == 0); // expected-warning{{TRUE}}
#endif
}
@@ -37,6 +66,12 @@ void testImmediateUse() {
#if __cplusplus
clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}
+ clang_analyzer_eval((void *)+getS() == (void *)&x); // expected-warning{{FALSE}}
+ clang_analyzer_eval((void *)-getS() == (void *)&x); // expected-warning{{FALSE}}
+
+ clang_analyzer_eval(getS().check()); // expected-warning{{TRUE}}
+ clang_analyzer_eval(!getS()); // expected-warning{{FALSE}}
+ clang_analyzer_eval(~getS()); // expected-warning{{FALSE}}
#endif
}
@@ -68,6 +103,13 @@ void testReferenceAssignment() {
clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
+ clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
+ clang_analyzer_eval(!s); // expected-warning{{FALSE}}
+ clang_analyzer_eval(~s); // expected-warning{{FALSE}}
+
+ clang_analyzer_eval(*s == 42); // expected-warning{{TRUE}}
}
@@ -80,8 +122,39 @@ bool checkThis(const S &s) {
return s.getThis() == &s;
}
+bool checkThisOp(const S &s) {
+ return +s == &s;
+}
+
+bool checkThisStaticOp(const S &s) {
+ return -s == &s;
+}
+
void testReferenceArgument() {
clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
+ clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}}
+ clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}}
+}
+
+
+int getConstrainedFieldOp(S s) {
+ if (*s != 42) return 42;
+ return *s;
+}
+
+int getConstrainedFieldRefOp(const S &s) {
+ if (*s != 42) return 42;
+ return *s;
}
+
+void testImmediateUseOp() {
+ int x = *getS();
+ if (x != 42) return;
+ clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(getConstrainedFieldOp(getS()) == 42); // expected-warning{{TRUE}}
+ clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}}
+}
+
#endif
diff --git a/test/Analysis/fields.c b/test/Analysis/fields.c
index da0847a560..12e8bbf367 100644
--- a/test/Analysis/fields.c
+++ b/test/Analysis/fields.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core %s -analyzer-store=region -verify
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection %s -analyzer-store=region -verify
+
+void clang_analyzer_eval(int);
unsigned foo();
typedef struct bf { unsigned x:2; } bf;
@@ -26,3 +28,11 @@ void test() {
Point p;
(void)(p = getit()).x;
}
+
+
+void testLazyCompoundVal() {
+ Point p = {42, 0};
+ Point q;
+ clang_analyzer_eval((q = p).x == 42); // expected-warning{{TRUE}}
+ clang_analyzer_eval(q.x == 42); // expected-warning{{TRUE}}
+}
diff --git a/test/Analysis/reference.cpp b/test/Analysis/reference.cpp
index 374f3f7261..ce0ee8ed57 100644
--- a/test/Analysis/reference.cpp
+++ b/test/Analysis/reference.cpp
@@ -116,10 +116,8 @@ void testReferenceAddress(int &x) {
struct S { int &x; };
- // FIXME: Should be TRUE. Fields of return-by-value structs are not yet
- // symbolicated. Tracked by <rdar://problem/12137950>.
extern S getS();
- clang_analyzer_eval(&getS().x != 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(&getS().x != 0); // expected-warning{{TRUE}}
extern S *getSP();
clang_analyzer_eval(&getSP()->x != 0); // expected-warning{{TRUE}}