diff options
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 2 | ||||
| -rw-r--r-- | clang/test/Analysis/misc-ps.c | 18 | ||||
| -rw-r--r-- | clang/test/Analysis/out-of-bounds.c | 12 |
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 +} + |

