diff options
-rw-r--r-- | lib/Analysis/AnalysisDeclContext.cpp | 10 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 31 | ||||
-rw-r--r-- | test/Analysis/ctor-inlining.mm | 11 | ||||
-rw-r--r-- | test/Analysis/dtor.cpp | 21 |
4 files changed, 64 insertions, 9 deletions
diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp index 32b1fcfe7c..7de7f395e8 100644 --- a/lib/Analysis/AnalysisDeclContext.cpp +++ b/lib/Analysis/AnalysisDeclContext.cpp @@ -181,8 +181,16 @@ void AnalysisDeclContext::dumpCFG(bool ShowColors) { } ParentMap &AnalysisDeclContext::getParentMap() { - if (!PM) + if (!PM) { PM.reset(new ParentMap(getBody())); + if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(getDecl())) { + for (CXXConstructorDecl::init_const_iterator I = C->init_begin(), + E = C->init_end(); + I != E; ++I) { + PM->addStmt((*I)->getInit()); + } + } + } return *PM; } diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index 3306eaa7f8..394e975d4e 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -253,16 +253,33 @@ static SourceLocation getValidSourceLocation(const Stmt* S, // source code, so find an enclosing statement and use its location. if (!L.isValid()) { - ParentMap *PM = 0; + AnalysisDeclContext *ADC; if (LAC.is<const LocationContext*>()) - PM = &LAC.get<const LocationContext*>()->getParentMap(); + ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext(); else - PM = &LAC.get<AnalysisDeclContext*>()->getParentMap(); + ADC = LAC.get<AnalysisDeclContext*>(); + + ParentMap &PM = ADC->getParentMap(); + + const Stmt *Parent = S; + do { + Parent = PM.getParent(Parent); + + // In rare cases, we have implicit top-level expressions, + // such as arguments for implicit member initializers. + // In this case, fall back to the start of the body (even if we were + // asked for the statement end location). + if (!Parent) { + const Stmt *Body = ADC->getBody(); + if (Body) + L = Body->getLocStart(); + else + L = ADC->getDecl()->getLocEnd(); + break; + } - while (!L.isValid()) { - S = PM->getParent(S); - L = UseEnd ? S->getLocEnd() : S->getLocStart(); - } + L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart(); + } while (!L.isValid()); } return L; diff --git a/test/Analysis/ctor-inlining.mm b/test/Analysis/ctor-inlining.mm new file mode 100644 index 0000000000..000e865751 --- /dev/null +++ b/test/Analysis/ctor-inlining.mm @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -fobjc-arc -cfg-add-initializers -cfg-add-implicit-dtors -Wno-null-dereference -verify %s + +struct Wrapper { + __strong id obj; +}; + +void test() { + Wrapper w; + // force a diagnostic + *(char *)0 = 1; // expected-warning{{Dereference of null pointer}} +} diff --git a/test/Analysis/dtor.cpp b/test/Analysis/dtor.cpp index 4e3c0017f4..18884c5f91 100644 --- a/test/Analysis/dtor.cpp +++ b/test/Analysis/dtor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -analyzer-ipa=inlining -cfg-add-implicit-dtors -cfg-add-initializers -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -analyzer-ipa=inlining -cfg-add-implicit-dtors -cfg-add-initializers -Wno-null-dereference -verify %s void clang_analyzer_eval(bool); @@ -154,3 +154,22 @@ void testArrayInvalidation() { clang_analyzer_eval(i == 42); // expected-warning{{UNKNOWN}} clang_analyzer_eval(j == 42); // expected-warning{{UNKNOWN}} } + + + +// Don't crash on a default argument inside an initializer. +struct DefaultArg { + DefaultArg(int x = 0) {} + ~DefaultArg(); +}; + +struct InheritsDefaultArg : DefaultArg { + InheritsDefaultArg() {} + virtual ~InheritsDefaultArg(); +}; + +void testDefaultArg() { + InheritsDefaultArg a; + // Force a bug to be emitted. + *(char *)0 = 1; // expected-warning{{Dereference of null pointer}} +} |