r181088 - [analyzer; alternate edges] start experimenting with control flow "barriers" to prevent an edge being optimized away.
Ted Kremenek
kremenek at apple.com
Fri May 3 18:13:22 PDT 2013
Author: kremenek
Date: Fri May 3 20:13:22 2013
New Revision: 181088
URL: http://llvm.org/viewvc/llvm-project?rev=181088&view=rev
Log:
[analyzer;alternate edges] start experimenting with control flow "barriers" to prevent an edge being optimized away.
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h?rev=181088&r1=181087&r2=181088&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h Fri May 3 20:13:22 2013
@@ -304,6 +304,7 @@ public:
const PathDiagnosticLocation &getStart() const { return Start; }
const PathDiagnosticLocation &getEnd() const { return End; }
+ void setStart(const PathDiagnosticLocation &L) { Start = L; }
void setEnd(const PathDiagnosticLocation &L) { End = L; }
void flatten() {
@@ -618,6 +619,10 @@ public:
return LPairs[0].getEnd();
}
+ void setStartLocation(const PathDiagnosticLocation &L) {
+ LPairs[0].setStart(L);
+ }
+
void setEndLocation(const PathDiagnosticLocation &L) {
LPairs[0].setEnd(L);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=181088&r1=181087&r2=181088&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Fri May 3 20:13:22 2013
@@ -1750,7 +1750,48 @@ const Stmt *getStmtParent(const Stmt *S,
return PM.getParentIgnoreParens(S);
}
-static bool optimizeEdges(PathPieces &path,
+#if 0
+static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
+ // Note that we intentionally to do not handle || and && here.
+ switch (S->getStmtClass()) {
+ case Stmt::ForStmtClass:
+ return cast<ForStmt>(S)->getCond() == Cond;
+ case Stmt::WhileStmtClass:
+ return cast<WhileStmt>(S)->getCond() == Cond;
+ case Stmt::DoStmtClass:
+ return cast<DoStmt>(S)->getCond() == Cond;
+ case Stmt::ChooseExprClass:
+ return cast<ChooseExpr>(S)->getCond() == Cond;
+ case Stmt::IndirectGotoStmtClass:
+ return cast<IndirectGotoStmt>(S)->getTarget() == Cond;
+ case Stmt::SwitchStmtClass:
+ return cast<SwitchStmt>(S)->getCond() == Cond;
+ case Stmt::BinaryConditionalOperatorClass:
+ return cast<BinaryConditionalOperator>(S)->getCond() == Cond;
+ case Stmt::ConditionalOperatorClass:
+ return cast<ConditionalOperator>(S)->getCond() == Cond;
+ case Stmt::ObjCForCollectionStmtClass:
+ return cast<ObjCForCollectionStmt>(S)->getElement() == Cond;
+ default:
+ return false;
+ }
+}
+#endif
+
+typedef llvm::DenseSet<const PathDiagnosticControlFlowPiece *>
+ ControlFlowBarrierSet;
+
+typedef llvm::DenseSet<const PathDiagnosticCallPiece *>
+ OptimizedCallsSet;
+
+static bool isBarrier(ControlFlowBarrierSet &CFBS,
+ const PathDiagnosticControlFlowPiece *P) {
+ return CFBS.count(P);
+}
+
+static bool optimizeEdges(PathPieces &path, SourceManager &SM,
+ ControlFlowBarrierSet &CFBS,
+ OptimizedCallsSet &OCS,
LocationContextMap &LCM) {
bool hasChanges = false;
const LocationContext *LC = LCM[&path];
@@ -1758,13 +1799,15 @@ static bool optimizeEdges(PathPieces &pa
bool isFirst = true;
for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) {
- PathPieces::iterator NextI = I; ++NextI;
- if (NextI == E)
- break;
+ bool wasFirst = isFirst;
+ isFirst = false;
// Optimize subpaths.
if (PathDiagnosticCallPiece *CallI = dyn_cast<PathDiagnosticCallPiece>(*I)){
- while (optimizeEdges(CallI->path, LCM)) {}
+ if (!OCS.count(CallI)) {
+ while (optimizeEdges(CallI->path, SM, CFBS, OCS, LCM)) {}
+ OCS.insert(CallI);
+ }
continue;
}
@@ -1781,10 +1824,19 @@ static bool optimizeEdges(PathPieces &pa
const Stmt *level1 = getStmtParent(s1Start, PM);
const Stmt *level2 = getStmtParent(s1End, PM);
- if (isFirst) {
- isFirst = false;
+ if (wasFirst) {
+#if 0
+ // Apply the "first edge" case for Rule V. here.
+ if (s1Start && level1 && isConditionForTerminator(level1, s1Start)) {
+ PathDiagnosticLocation NewLoc(level2, SM, LC);
+ PieceI->setStartLocation(NewLoc);
+ CFBS.insert(PieceI);
+ return true;
+ }
+#endif
// Apply the "first edge" case for Rule III. here.
- if (level1 && level2 && level2 == PM.getParent(level1)) {
+ if (!isBarrier(CFBS, PieceI) &&
+ level1 && level2 && level2 == PM.getParent(level1)) {
path.erase(I);
// Since we are erasing the current edge at the start of the
// path, just return now so we start analyzing the start of the path
@@ -1793,6 +1845,10 @@ static bool optimizeEdges(PathPieces &pa
}
}
+ PathPieces::iterator NextI = I; ++NextI;
+ if (NextI == E)
+ break;
+
PathDiagnosticControlFlowPiece *PieceNextI =
dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
@@ -1817,7 +1873,8 @@ static bool optimizeEdges(PathPieces &pa
// NOTE: this will be limited later in cases where we add barriers
// to prevent this optimization.
//
- if (level1 && level1 == level2 && level1 == level3 && level1 == level4) {
+ if (!isBarrier(CFBS, PieceNextI) &&
+ level1 && level1 == level2 && level1 == level3 && level1 == level4) {
PieceI->setEndLocation(PieceNextI->getEndLocation());
path.erase(NextI);
hasChanges = true;
@@ -1835,7 +1892,8 @@ static bool optimizeEdges(PathPieces &pa
// For example:
//
// (1.1 -> 1.1.1) -> (1.1.1 -> 1.2) becomes (1.1 -> 1.2).
- if (level1 && level2 &&
+ if (!isBarrier(CFBS, PieceNextI) &&
+ level1 && level2 &&
level1 == level4 &&
level2 == level3 && PM.getParentIgnoreParens(level2) == level1) {
PieceI->setEndLocation(PieceNextI->getEndLocation());
@@ -1856,7 +1914,8 @@ static bool optimizeEdges(PathPieces &pa
//
// (1.1 -> 1.1.1) -> (1.1.1 -> X) becomes (1.1 -> X).
//
- if (level1 && level2 && level1 == PM.getParentIgnoreParens(level2)) {
+ if (!isBarrier(CFBS, PieceNextI) &&
+ level1 && level2 && level1 == PM.getParentIgnoreParens(level2)) {
PieceI->setEndLocation(PieceNextI->getEndLocation());
path.erase(NextI);
hasChanges = true;
@@ -1876,12 +1935,38 @@ static bool optimizeEdges(PathPieces &pa
// (X -> 1.1.1) -> (1.1.1 -> 1.1) becomes (X -> 1.1).
// [first edge] (1.1.1 -> 1.1) -> eliminate
//
- if (level2 && level4 && level2 == level3 && level4 == PM.getParent(level2)){
+ if (!isBarrier(CFBS, PieceNextI) &&
+ level2 && level4 && level2 == level3 && level4 == PM.getParent(level2)){
PieceI->setEndLocation(PieceNextI->getEndLocation());
path.erase(NextI);
hasChanges = true;
continue;
}
+#if 0
+ // Rule V.
+ //
+ // Replace terminator conditions with terminators when the condition
+ // itself has no control-flow.
+ //
+ // For example:
+ //
+ // (X -> condition) -> (condition -> Y) becomes (X -> term) -> (term -> Y)
+ // [first edge] (condition -> Y) becomes (term -> Y)
+ //
+ // This applies to 'if', 'for', 'while', 'do .. while', 'switch'...
+ //
+ if (!isBarrier(CFBS, PieceNextI) &&
+ s1End && s1End == s2Start && level2) {
+ if (isConditionForTerminator(level2, s1End)) {
+ PathDiagnosticLocation NewLoc(level2, SM, LC);
+ PieceI->setEndLocation(NewLoc);
+ PieceNextI->setStartLocation(NewLoc);
+ CFBS.insert(PieceI);
+ hasChanges = true;
+ continue;
+ }
+ }
+#endif
}
// No changes.
@@ -2468,7 +2553,7 @@ bool GRBugReporter::generatePathDiagnost
if (ActiveScheme == PathDiagnosticConsumer::Extensive) {
AnalyzerOptions &options = getEngine().getAnalysisManager().options;
- if (options.getBooleanOption("path-diagnostics-alternate", true)) {
+ if (options.getBooleanOption("path-diagnostics-alternate", false)) {
ActiveScheme = PathDiagnosticConsumer::AlternateExtensive;
}
}
@@ -2573,7 +2658,10 @@ bool GRBugReporter::generatePathDiagnost
adjustCallLocations(PD.getMutablePieces());
if (ActiveScheme == PathDiagnosticConsumer::AlternateExtensive) {
- while (optimizeEdges(PD.getMutablePieces(), LCM)) {}
+ ControlFlowBarrierSet CFBS;
+ OptimizedCallsSet OCS;
+ while (optimizeEdges(PD.getMutablePieces(), getSourceManager(), CFBS,
+ OCS, LCM)) {}
}
}
More information about the cfe-commits
mailing list