aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Analysis/AnalysisDeclContext.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp31
-rw-r--r--test/Analysis/ctor-inlining.mm11
-rw-r--r--test/Analysis/dtor.cpp21
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}}
+}