Skip to content

Commit

Permalink
[analyzer] Look through temporary destructors when finding a region t…
Browse files Browse the repository at this point in the history
…o construct.

Fixes a false positive when temporary destructors are enabled where a temporary
is destroyed after a variable is constructed but before the VarDecl itself is
processed, which occurs when the variable is in the condition of an if or while.

Patch by Alex McCarthy, with an extra test from me.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205661 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
jrose-apple committed Apr 5, 2014
1 parent 1c3262a commit bb4f59b
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
12 changes: 10 additions & 2 deletions lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,16 @@ static const MemRegion *getRegionForConstructedObject(
// See if we're constructing an existing region by looking at the next
// element in the CFG.
const CFGBlock *B = CurrBldrCtx.getBlock();
if (CurrStmtIdx + 1 < B->size()) {
CFGElement Next = (*B)[CurrStmtIdx+1];
unsigned int NextStmtIdx = CurrStmtIdx + 1;
if (NextStmtIdx < B->size()) {
CFGElement Next = (*B)[NextStmtIdx];

// Is this a destructor? If so, we might be in the middle of an assignment
// to a local or member: look ahead one more element to see what we find.
while (Next.getAs<CFGImplicitDtor>() && NextStmtIdx + 1 < B->size()) {
++NextStmtIdx;
Next = (*B)[NextStmtIdx];
}

// Is this a constructor for a local variable?
if (Optional<CFGStmt> StmtElem = Next.getAs<CFGStmt>()) {
Expand Down
15 changes: 10 additions & 5 deletions test/Analysis/dtor.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -Wno-null-dereference -verify %s
// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors,cfg-temporary-dtors=true -Wno-null-dereference -verify %s

void clang_analyzer_eval(bool);
void clang_analyzer_checkInlined(bool);
Expand Down Expand Up @@ -426,8 +426,14 @@ namespace LifetimeExtension {

// This case used to cause an unexpected "Undefined or garbage value returned
// to caller" warning
bool testNamedCustomDestructor() {
if (CheckCustomDestructor c = CheckCustomDestructor())
// bool testNamedCustomDestructor() {
// if (CheckCustomDestructor c = CheckCustomDestructor())
// return true;
// return false;
// }

bool testMultipleTemporariesCustomDestructor() {
if (CheckCustomDestructor c = (CheckCustomDestructor(), CheckCustomDestructor()))
return true;
return false;
}
Expand Down Expand Up @@ -477,8 +483,7 @@ namespace NoReturn {

void g2(int *x) {
if (! x) NR();
// FIXME: this shouldn't cause a warning.
*x = 47; // expected-warning{{Dereference of null pointer}}
*x = 47; // no warning
}
}

Expand Down

0 comments on commit bb4f59b

Please sign in to comment.