summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2013-10-17 18:19:31 +0000
committerDeLesley Hutchins <delesley@google.com>2013-10-17 18:19:31 +0000
commit6501320e723a63bcbadf49c9e9dd4cfde904619e (patch)
tree53071dc37ac76561128d625a08f5b9c8561203fe
parent045a78fa7e21af1459b7eb5be2193a9789a80780 (diff)
downloadbcm5719-llvm-6501320e723a63bcbadf49c9e9dd4cfde904619e.tar.gz
bcm5719-llvm-6501320e723a63bcbadf49c9e9dd4cfde904619e.zip
Consumed analysis: fix ICE in handling of loop source locations.
llvm-svn: 192911
-rw-r--r--clang/lib/Analysis/Consumed.cpp37
-rw-r--r--clang/test/SemaCXX/warn-consumed-analysis.cpp28
2 files changed, 55 insertions, 10 deletions
diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp
index c51c02335c5..b06fb155d5b 100644
--- a/clang/lib/Analysis/Consumed.cpp
+++ b/clang/lib/Analysis/Consumed.cpp
@@ -51,6 +51,23 @@ using namespace consumed;
// Key method definition
ConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() {}
+static SourceLocation getFirstStmtLoc(const CFGBlock *Block) {
+ // Find the source location of the first statement in the block, if the block
+ // is not empty.
+ for (CFGBlock::const_iterator BI = Block->begin(), BE = Block->end();
+ BI != BE; ++BI) {
+ if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>())
+ return CS->getStmt()->getLocStart();
+ }
+
+ // Block is empty.
+ // If we have one successor, return the first statement in that block
+ if (Block->succ_size() == 1 && *Block->succ_begin())
+ return getFirstStmtLoc(*Block->succ_begin());
+
+ return SourceLocation();
+}
+
static SourceLocation getLastStmtLoc(const CFGBlock *Block) {
// Find the source location of the last statement in the block, if the block
// is not empty.
@@ -59,17 +76,23 @@ static SourceLocation getLastStmtLoc(const CFGBlock *Block) {
} else {
for (CFGBlock::const_reverse_iterator BI = Block->rbegin(),
BE = Block->rend(); BI != BE; ++BI) {
- // FIXME: Handle other CFGElement kinds.
if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>())
return CS->getStmt()->getLocStart();
}
}
+
+ // If we have one successor, return the first statement in that block
+ SourceLocation Loc;
+ if (Block->succ_size() == 1 && *Block->succ_begin())
+ Loc = getFirstStmtLoc(*Block->succ_begin());
+ if (Loc.isValid())
+ return Loc;
- // The block is empty, and has a single predecessor. Use its exit location.
- assert(Block->pred_size() == 1 && *Block->pred_begin() &&
- Block->succ_size() != 0);
-
- return getLastStmtLoc(*Block->pred_begin());
+ // If we have one predecessor, return the last statement in that block
+ if (Block->pred_size() == 1 && *Block->pred_begin())
+ return getLastStmtLoc(*Block->pred_begin());
+
+ return Loc;
}
static ConsumedState invertConsumedUnconsumed(ConsumedState State) {
@@ -1237,7 +1260,7 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
CFG *CFGraph = AC.getCFG();
if (!CFGraph)
return;
-
+
determineExpectedReturnState(AC, D);
PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
diff --git a/clang/test/SemaCXX/warn-consumed-analysis.cpp b/clang/test/SemaCXX/warn-consumed-analysis.cpp
index 8a55c8820a2..e7380b97feb 100644
--- a/clang/test/SemaCXX/warn-consumed-analysis.cpp
+++ b/clang/test/SemaCXX/warn-consumed-analysis.cpp
@@ -546,14 +546,36 @@ void testWhileLoop1() {
ConsumableClass<int> var0, var1(42);
- while (i-- > 0) {
+ while (i-- > 0) { // expected-warning {{state of variable 'var1' must match at the entry and exit of loop}}
*var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
*var1;
var1.consume();
- *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} \
- // expected-warning {{state of variable 'var1' must match at the entry and exit of loop}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
}
*var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
}
+
+
+namespace ContinueICETest {
+
+bool cond1();
+bool cond2();
+
+static void foo1() {
+ while (cond1()) {
+ if (cond2())
+ continue;
+ }
+}
+
+static void foo2() {
+ while (true) {
+ if (false)
+ continue;
+ }
+}
+
+} // end namespace ContinueICETest
+
OpenPOWER on IntegriCloud