forked from OSchip/llvm-project
[analyzer] Accept references to variables declared "extern void" (C only).
In C, 'void' is treated like any other incomplete type, and though it is never completed, you can cast the address of a void-typed variable to do something useful. (In C++ it's illegal to declare a variable with void type.) Previously we asserted on this code; now we just treat it like any other incomplete type. And speaking of incomplete types, we don't know their extent. Actually check that in TypedValueRegion::getExtent, though that's not being used by any checkers that are on by default. llvm-svn: 182880
This commit is contained in:
parent
33b736626e
commit
1bd1927a14
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue