Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -833,13 +833,20 @@ return; // First, find when we processed the statement. + // If we have one of the following cases that is going to be purged away + // before its call take place. We would catch that purge in the second + // condition as a 'StmtPoint' so we have to bypass it. + const bool IsBypass = + isa(S) || isa(S) || isa(S); do { - if (auto CEE = Node->getLocationAs()) + if (Optional CEE = Node->getLocationAs()) if (CEE->getCalleeContext()->getCallSite() == S) break; - if (auto SP = Node->getLocationAs()) - if (SP->getStmt() == S) - break; + + if (!IsBypass) + if (Optional SP = Node->getLocationAs()) + if (SP->getStmt() == S) + break; Node = Node->getFirstPred(); } while (Node); Index: clang/test/Analysis/new-ctor-null-throw.cpp =================================================================== --- clang/test/Analysis/new-ctor-null-throw.cpp +++ clang/test/Analysis/new-ctor-null-throw.cpp @@ -1,4 +1,9 @@ -// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core \ +// RUN: -analyzer-config suppress-null-return-paths=false \ +// RUN: -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core \ +// RUN: -DSUPPRESSED=1 \ +// RUN: -verify %s void clang_analyzer_eval(bool); @@ -9,18 +14,41 @@ // operator new. void *operator new(size_t size) { return nullptr; + // expected-warning@-1 {{'operator new' should not return a null pointer unless it is declared 'throw()' or 'noexcept'}} } void *operator new[](size_t size) { return nullptr; + // expected-warning@-1 {{'operator new[]' should not return a null pointer unless it is declared 'throw()' or 'noexcept'}} } struct S { int x; S() : x(1) {} ~S() {} + int getX() const { return x; } }; void testArrays() { S *s = new S[10]; // no-crash - s[0].x = 2; // expected-warning{{Dereference of null pointer}} + s[0].x = 2; +#ifndef SUPPRESSED + // expected-warning@-2 {{Dereference of null pointer}} +#endif } + +void testCtor() { + S *s = new S(); + s->x = 13; +#ifndef SUPPRESSED + // expected-warning@-2 {{Access to field 'x' results in a dereference of a null pointer (loaded from variable 's')}} +#endif +} + +void testMethod() { + S *s = new S(); + const int X = s->getX(); +#ifndef SUPPRESSED + // expected-warning@-2 {{Called C++ object pointer is null}} +#endif +} + Index: clang/test/Analysis/new-ctor-null.cpp =================================================================== --- clang/test/Analysis/new-ctor-null.cpp +++ clang/test/Analysis/new-ctor-null.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=core,debug.ExprInspection \ +// RUN: -std=c++11 -verify %s void clang_analyzer_eval(bool); void clang_analyzer_warnIfReached(); @@ -24,7 +26,8 @@ void testArrays() { S *s = new S[10]; // no-crash - s[0].x = 2; // expected-warning{{Dereference of null pointer}} + s[0].x = 2; + // no-warning: 'Dereference of null pointer' suppressed by ReturnVisitor. } int global;