summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Core/MemRegion.cpp2
-rw-r--r--clang/test/Analysis/misc-ps.c18
-rw-r--r--clang/test/Analysis/out-of-bounds.c12
4 files changed, 33 insertions, 3 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index bfe4e15a715..627e0107b86 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1613,7 +1613,9 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
const LocationContext *LCtx = Pred->getLocationContext();
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- assert(Ex->isGLValue());
+ // C permits "extern void v", and if you cast the address to a valid type,
+ // you can even do things with it. We simply pretend
+ assert(Ex->isGLValue() || VD->getType()->isVoidType());
SVal V = state->getLValue(VD, Pred->getLocationContext());
// For references, the 'lvalue' is the pointer address stored in the
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 31ac86bea66..0102f9237c2 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -186,7 +186,7 @@ DefinedOrUnknownSVal TypedValueRegion::getExtent(SValBuilder &svalBuilder) const
if (isa<VariableArrayType>(T))
return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
- if (isa<IncompleteArrayType>(T))
+ if (T->isIncompleteType())
return UnknownVal();
CharUnits size = Ctx.getTypeSizeInChars(T);
diff --git a/clang/test/Analysis/misc-ps.c b/clang/test/Analysis/misc-ps.c
index b302860a2f9..01cad1549cd 100644
--- a/clang/test/Analysis/misc-ps.c
+++ b/clang/test/Analysis/misc-ps.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -disable-free -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=deadcode -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -disable-free -analyzer-eagerly-assume -analyzer-checker=core,deadcode,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
int size_rdar9373039 = 1;
int foo_rdar9373039(const char *);
@@ -175,3 +177,17 @@ void sinkAfterRegularNode(struct PR15684 *context) {
context->callback(uninitialized); // expected-warning {{uninitialized}}
}
+
+// PR16131: C permits variables to be declared extern void.
+static void PR16131(int x) {
+ extern void v;
+
+ int *ip = (int *)&v;
+ char *cp = (char *)&v;
+ clang_analyzer_eval(ip == cp); // expected-warning{{TRUE}}
+ // expected-warning@-1 {{comparison of distinct pointer types}}
+
+ *ip = 42;
+ clang_analyzer_eval(*ip == 42); // expected-warning{{TRUE}}
+ clang_analyzer_eval(*(int *)&v == 42); // expected-warning{{TRUE}}
+}
diff --git a/clang/test/Analysis/out-of-bounds.c b/clang/test/Analysis/out-of-bounds.c
index dd593c5f26c..d89a2396190 100644
--- a/clang/test/Analysis/out-of-bounds.c
+++ b/clang/test/Analysis/out-of-bounds.c
@@ -154,3 +154,15 @@ void test_index_below_symboloc() {
buf[-1] = 0; // no-warning;
}
+void test_incomplete_struct() {
+ extern struct incomplete incomplete;
+ int *p = (int *)&incomplete;
+ p[1] = 42; // no-warning
+}
+
+void test_extern_void() {
+ extern void v;
+ int *p = (int *)&v;
+ p[1] = 42; // no-warning
+}
+
OpenPOWER on IntegriCloud