Skip to content

Commit

Permalink
[analyzer] Canonicalize declarations within variable regions.
Browse files Browse the repository at this point in the history
Memory region that correspond to a variable is identified by the variable's
declaration and, in case of local variables, the stack frame it belongs to.

The declaration needs to be canonical, otherwise we'd have two different
memory regions that correspond to the same variable.

Fix such bug for global variables with forward declarations and assert
that no other problems of this kind happen.

Differential Revision: https://reviews.llvm.org/D57619

llvm-svn: 353353
  • Loading branch information
haoNoQ committed Feb 7, 2019
1 parent 1e71b04 commit 161e475
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 1 deletion.
Expand Up @@ -908,7 +908,7 @@ class DeclRegion : public TypedValueRegion {
DeclRegion(const ValueDecl *d, const MemRegion *sReg, Kind k)
: TypedValueRegion(sReg, k), D(d) {
assert(classof(this));
assert(d);
assert(d && d->isCanonicalDecl());
}

static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/StaticAnalyzer/Core/MemRegion.cpp
Expand Up @@ -844,6 +844,7 @@ getStackOrCaptureRegionForDeclContext(const LocationContext *LC,

const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
const LocationContext *LC) {
D = D->getCanonicalDecl();
const MemRegion *sReg = nullptr;

if (D->hasGlobalStorage() && !D->isStaticLocal()) {
Expand Down Expand Up @@ -930,6 +931,7 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,

const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
const MemRegion *superR) {
D = D->getCanonicalDecl();
return getSubRegion<VarRegion>(D, superR);
}

Expand Down
15 changes: 15 additions & 0 deletions clang/test/Analysis/globals.cpp
Expand Up @@ -109,3 +109,18 @@ void recordinit()
S3 s3;
*(s3.p - 1) = 0; // expected-warning{{Dereference of null pointer}}
}

extern int ext_int;

void update_original_declaration() {
ext_int = 2;
}

extern int ext_int;

int test_redeclaration() {
ext_int = 1;
update_original_declaration();
int int_int = 3 / (ext_int - 1); // no-warning
return int_int / (ext_int - 2); // expected-warning{{Division by zero}}
}

0 comments on commit 161e475

Please sign in to comment.