diff options
author | DeLesley Hutchins <delesley@google.com> | 2013-10-17 18:19:31 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2013-10-17 18:19:31 +0000 |
commit | 6501320e723a63bcbadf49c9e9dd4cfde904619e (patch) | |
tree | 53071dc37ac76561128d625a08f5b9c8561203fe | |
parent | 045a78fa7e21af1459b7eb5be2193a9789a80780 (diff) | |
download | bcm5719-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.cpp | 37 | ||||
-rw-r--r-- | clang/test/SemaCXX/warn-consumed-analysis.cpp | 28 |
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 + |