summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-07-26 20:04:30 +0000
committerJordan Rose <jordan_rose@apple.com>2012-07-26 20:04:30 +0000
commit25bc20f846d4268bbd0dac0ecfee019d59f0bfae (patch)
treec270593100fefd0197d7e13f46a2b9998e4ddc11 /clang/lib
parent20edae8749c7967718d2f2bfca76b1a6d39eca8f (diff)
downloadbcm5719-llvm-25bc20f846d4268bbd0dac0ecfee019d59f0bfae.tar.gz
bcm5719-llvm-25bc20f846d4268bbd0dac0ecfee019d59f0bfae.zip
[analyzer] Don't crash on implicit statements inside initializers.
Our BugReporter knows how to deal with implicit statements: it looks in the ParentMap until it finds a parent with a valid location. However, since initializers are not in the body of a constructor, their sub-expressions are not in the ParentMap. That was easy enough to fix in AnalysisDeclContext. ...and then even once THAT was fixed, there's still an extra funny case of Objective-C object pointer fields under ARC, which are initialized with a top-level ImplicitValueInitExpr. To catch these cases, PathDiagnosticLocation will now fall back to the start of the current function if it can't find any other valid SourceLocations. This isn't great, but it's miles better than a crash. (All of this is only relevant when constructors and destructors are being inlined, i.e. under -cfg-add-initializers and -cfg-add-implicit-dtors.) llvm-svn: 160810
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Analysis/AnalysisDeclContext.cpp10
-rw-r--r--clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp31
2 files changed, 33 insertions, 8 deletions
diff --git a/clang/lib/Analysis/AnalysisDeclContext.cpp b/clang/lib/Analysis/AnalysisDeclContext.cpp
index 32b1fcfe7c8..7de7f395e8a 100644
--- a/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/clang/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/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 3306eaa7f88..394e975d4e7 100644
--- a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/clang/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;
OpenPOWER on IntegriCloud