summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-10-23 20:08:55 +0000
committerJordan Rose <jordan_rose@apple.com>2013-10-23 20:08:55 +0000
commitbb61c8cc739bc29ea9d15a1b486273eb98023321 (patch)
tree77e1e59e0b36e0d0599f161c6d892cbcc90126fe /clang
parent48342ee908aababa7ffda5a9e82b73fa96d965ee (diff)
downloadbcm5719-llvm-bb61c8cc739bc29ea9d15a1b486273eb98023321.tar.gz
bcm5719-llvm-bb61c8cc739bc29ea9d15a1b486273eb98023321.zip
[analyzer] Generate a LazyCompoundVal when loading from a union-typed region.
This ensures that variables accessible through a union are invalidated when the union value is passed to a function. We still don't fully handle union values, but this should at least quiet some false positives. PR16596 llvm-svn: 193265
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/StaticAnalyzer/Core/RegionStore.cpp4
-rw-r--r--clang/test/Analysis/unions.cpp61
2 files changed, 62 insertions, 3 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 3cf1e5acde9..0b519768aa0 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1312,7 +1312,7 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
// FIXME: Handle unions.
if (RTy->isUnionType())
- return UnknownVal();
+ return createLazyBinding(B, R);
if (RTy->isArrayType()) {
if (RTy->isConstantArrayType())
@@ -1906,6 +1906,8 @@ RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
return bindStruct(B, TR, V);
if (Ty->isVectorType())
return bindVector(B, TR, V);
+ if (Ty->isUnionType())
+ return bindAggregate(B, TR, V);
}
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
diff --git a/clang/test/Analysis/unions.cpp b/clang/test/Analysis/unions.cpp
index 2bffe78b41c..f363ab81ae7 100644
--- a/clang/test/Analysis/unions.cpp
+++ b/clang/test/Analysis/unions.cpp
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core %s -verify
-// expected-no-diagnostics
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -verify
+
+extern void clang_analyzer_eval(bool);
+extern "C" char *strdup(const char *s);
namespace PR14054_reduced {
struct Definition;
@@ -49,3 +51,58 @@ namespace PR14054_original {
x = pn->pn_u.name.lexdef->pn_u.name.lexdef;
}
}
+
+namespace PR17596 {
+ union IntOrString {
+ int i;
+ char *s;
+ };
+
+ extern void process(IntOrString);
+
+ void test() {
+ IntOrString uu;
+ uu.s = strdup("");
+ process(uu);
+ }
+
+ void testPositive() {
+ IntOrString uu;
+ uu.s = strdup("");
+ } // expected-warning{{leak}}
+
+ void testCopy() {
+ IntOrString uu;
+ uu.i = 4;
+ clang_analyzer_eval(uu.i == 4); // expected-warning{{TRUE}}
+
+ IntOrString vv;
+ vv.i = 5;
+ uu = vv;
+ // FIXME: Should be true.
+ clang_analyzer_eval(uu.i == 5); // expected-warning{{UNKNOWN}}
+ }
+
+ void testInvalidation() {
+ IntOrString uu;
+ uu.s = strdup("");
+
+ IntOrString vv;
+ char str[] = "abc";
+ vv.s = str;
+
+ // FIXME: This is a leak of uu.s.
+ uu = vv;
+ }
+
+ void testIndirectInvalidation() {
+ IntOrString uu;
+ char str[] = "abc";
+ uu.s = str;
+
+ clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{TRUE}}
+
+ process(uu);
+ clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{UNKNOWN}}
+ }
+}
OpenPOWER on IntegriCloud