summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ParentMap.cpp7
-rw-r--r--clang/lib/Analysis/AnalysisDeclContext.cpp23
-rw-r--r--clang/lib/Analysis/CFG.cpp5
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporter.cpp57
4 files changed, 76 insertions, 16 deletions
diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp
index dbe0b98e186..ff44d938d3a 100644
--- a/clang/lib/AST/ParentMap.cpp
+++ b/clang/lib/AST/ParentMap.cpp
@@ -110,6 +110,13 @@ void ParentMap::addStmt(Stmt* S) {
}
}
+void ParentMap::setParent(const Stmt *S, const Stmt *Parent) {
+ assert(S);
+ assert(Parent);
+ MapTy *M = reinterpret_cast<MapTy *>(Impl);
+ M->insert(std::make_pair(const_cast<Stmt *>(S), const_cast<Stmt *>(Parent)));
+}
+
Stmt* ParentMap::getParent(Stmt* S) const {
MapTy* M = (MapTy*) Impl;
MapTy::iterator I = M->find(S);
diff --git a/clang/lib/Analysis/AnalysisDeclContext.cpp b/clang/lib/Analysis/AnalysisDeclContext.cpp
index 5ff7842407a..66dbd3e7856 100644
--- a/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -157,6 +157,19 @@ AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
return itr->second;
}
+/// Add each synthetic statement in the CFG to the parent map, using the
+/// source statement's parent.
+static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) {
+ if (!TheCFG)
+ return;
+
+ for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(),
+ E = TheCFG->synthetic_stmt_end();
+ I != E; ++I) {
+ PM.setParent(I->first, PM.getParent(I->second));
+ }
+}
+
CFG *AnalysisDeclContext::getCFG() {
if (!cfgBuildOptions.PruneTriviallyFalseEdges)
return getUnoptimizedCFG();
@@ -167,6 +180,9 @@ CFG *AnalysisDeclContext::getCFG() {
// Even when the cfg is not successfully built, we don't
// want to try building it again.
builtCFG = true;
+
+ if (PM)
+ addParentsForSyntheticStmts(cfg.get(), *PM);
}
return cfg.get();
}
@@ -180,6 +196,9 @@ CFG *AnalysisDeclContext::getUnoptimizedCFG() {
// Even when the cfg is not successfully built, we don't
// want to try building it again.
builtCompleteCFG = true;
+
+ if (PM)
+ addParentsForSyntheticStmts(completeCFG.get(), *PM);
}
return completeCFG.get();
}
@@ -222,6 +241,10 @@ ParentMap &AnalysisDeclContext::getParentMap() {
PM->addStmt((*I)->getInit());
}
}
+ if (builtCFG)
+ addParentsForSyntheticStmts(getCFG(), *PM);
+ if (builtCompleteCFG)
+ addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM);
}
return *PM;
}
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 9945dcb36ce..f4858951854 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -1627,6 +1627,7 @@ CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
Decl *D = *I;
void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A);
DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
+ cfg->addSyntheticDeclStmt(DSNew, DS);
// Append the fake DeclStmt to block.
B = VisitDeclSubExpr(DSNew);
@@ -3953,6 +3954,10 @@ Stmt *CFGBlock::getTerminatorCondition() {
default:
break;
+ case Stmt::CXXForRangeStmtClass:
+ E = cast<CXXForRangeStmt>(Terminator)->getCond();
+ break;
+
case Stmt::ForStmtClass:
E = cast<ForStmt>(Terminator)->getCond();
break;
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 829e7482ebe..96aa4886186 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -363,6 +363,7 @@ static const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) {
case Stmt::DoStmtClass:
case Stmt::WhileStmtClass:
case Stmt::ObjCForCollectionStmtClass:
+ case Stmt::CXXForRangeStmtClass:
return Parent;
default:
break;
@@ -404,6 +405,10 @@ getEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P,
return PathDiagnosticLocation(Parent, SMgr, LC);
else
return PathDiagnosticLocation(S, SMgr, LC);
+ case Stmt::CXXForRangeStmtClass:
+ if (cast<CXXForRangeStmt>(Parent)->getBody() == S)
+ return PathDiagnosticLocation(S, SMgr, LC);
+ break;
case Stmt::DoStmtClass:
return PathDiagnosticLocation(S, SMgr, LC);
case Stmt::ForStmtClass:
@@ -1253,6 +1258,7 @@ static bool isLoop(const Stmt *Term) {
case Stmt::ForStmtClass:
case Stmt::WhileStmtClass:
case Stmt::ObjCForCollectionStmtClass:
+ case Stmt::CXXForRangeStmtClass:
return true;
default:
// Note that we intentionally do not include do..while here.
@@ -1302,6 +1308,15 @@ static const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term,
static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
const Stmt *LoopBody = 0;
switch (Term->getStmtClass()) {
+ case Stmt::CXXForRangeStmtClass: {
+ const CXXForRangeStmt *FR = cast<CXXForRangeStmt>(Term);
+ if (isContainedByStmt(PM, FR->getInc(), S))
+ return true;
+ if (isContainedByStmt(PM, FR->getLoopVarStmt(), S))
+ return true;
+ LoopBody = FR->getBody();
+ break;
+ }
case Stmt::ForStmtClass: {
const ForStmt *FS = cast<ForStmt>(Term);
if (isContainedByStmt(PM, FS->getInc(), S))
@@ -1718,16 +1733,20 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
// Are we jumping to the head of a loop? Add a special diagnostic.
if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
PathDiagnosticLocation L(Loop, SM, PDB.LC);
- const CompoundStmt *CS = NULL;
+ const Stmt *Body = NULL;
if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
- CS = dyn_cast<CompoundStmt>(FS->getBody());
+ Body = FS->getBody();
else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
- CS = dyn_cast<CompoundStmt>(WS->getBody());
+ Body = WS->getBody();
else if (const ObjCForCollectionStmt *OFS =
- dyn_cast<ObjCForCollectionStmt>(Loop)) {
- CS = dyn_cast<CompoundStmt>(OFS->getBody());
+ dyn_cast<ObjCForCollectionStmt>(Loop)) {
+ Body = OFS->getBody();
+ } else if (const CXXForRangeStmt *FRS =
+ dyn_cast<CXXForRangeStmt>(Loop)) {
+ Body = FRS->getBody();
}
+ // do-while statements are explicitly excluded here
PathDiagnosticEventPiece *p =
new PathDiagnosticEventPiece(L, "Looping back to the head "
@@ -1737,7 +1756,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
PD.getActivePath().push_front(p);
- if (CS) {
+ if (const CompoundStmt *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
addEdgeToPath(PD.getActivePath(), PrevLoc,
PathDiagnosticLocation::createEndBrace(CS, SM),
PDB.LC);
@@ -1871,16 +1890,22 @@ static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
}
case Stmt::ObjCForCollectionStmtClass:
return cast<ObjCForCollectionStmt>(S)->getElement() == Cond;
+ case Stmt::CXXForRangeStmtClass: {
+ const CXXForRangeStmt *FRS = cast<CXXForRangeStmt>(S);
+ return FRS->getCond() == Cond || FRS->getRangeInit() == Cond;
+ }
default:
return false;
}
}
static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) {
- const ForStmt *FS = dyn_cast<ForStmt>(FL);
- if (!FS)
- return false;
- return FS->getInc() == S || FS->getInit() == S;
+ if (const ForStmt *FS = dyn_cast<ForStmt>(FL))
+ return FS->getInc() == S || FS->getInit() == S;
+ if (const CXXForRangeStmt *FRS = dyn_cast<CXXForRangeStmt>(FL))
+ return FRS->getInc() == S || FRS->getRangeStmt() == S ||
+ FRS->getLoopVarStmt() || FRS->getRangeInit() == S;
+ return false;
}
typedef llvm::DenseSet<const PathDiagnosticCallPiece *>
@@ -1903,16 +1928,15 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM,
continue;
PathDiagnosticLocation SrcLoc = Piece->getStartLocation();
- const Stmt *Src = getLocStmt(SrcLoc);
SmallVector<PathDiagnosticLocation, 4> SrcContexts;
- PathDiagnosticLocation NextSrcContext =
- getEnclosingStmtLocation(Src, SM, PM, LCtx, /*allowNested=*/true);
- const Stmt *InnerStmt = Src;
+ PathDiagnosticLocation NextSrcContext = SrcLoc;
+ const Stmt *InnerStmt = 0;
while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) {
SrcContexts.push_back(NextSrcContext);
InnerStmt = NextSrcContext.asStmt();
- NextSrcContext = getEnclosingStmtLocation(InnerStmt, SM, PM, LCtx, true);
+ NextSrcContext = getEnclosingStmtLocation(InnerStmt, SM, PM, LCtx,
+ /*allowNested=*/true);
}
// Repeatedly split the edge as necessary.
@@ -2024,7 +2048,8 @@ static void simplifySimpleBranches(PathPieces &pieces) {
// We only perform this transformation for specific branch kinds.
// We don't want to do this for do..while, for example.
if (!(isa<ForStmt>(s1Start) || isa<WhileStmt>(s1Start) ||
- isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start)))
+ isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start) ||
+ isa<CXXForRangeStmt>(s1Start)))
continue;
// Is s1End the branch condition?
OpenPOWER on IntegriCloud