// 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>()) {
-// 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);
// 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;
}
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
}
}