diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 52fe156e3525..e1eb7281479f 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -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() && NextStmtIdx + 1 < B->size()) { + ++NextStmtIdx; + Next = (*B)[NextStmtIdx]; + } // Is this a constructor for a local variable? if (Optional StmtElem = Next.getAs()) { diff --git a/clang/test/Analysis/dtor.cpp b/clang/test/Analysis/dtor.cpp index dbb950eda0f7..e410fc9083a0 100644 --- a/clang/test/Analysis/dtor.cpp +++ b/clang/test/Analysis/dtor.cpp @@ -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); @@ -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; } @@ -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 } }