From 52f717eba7eff69c97d64de5e3669f4a5ee57d5c Mon Sep 17 00:00:00 2001 From: DeLesley Hutchins Date: Thu, 17 Oct 2013 18:19:31 +0000 Subject: [PATCH] Consumed analysis: fix ICE in handling of loop source locations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192911 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/Consumed.cpp | 37 ++++++++++++++++++++----- test/SemaCXX/warn-consumed-analysis.cpp | 28 +++++++++++++++++-- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp index c51c02335c..b06fb155d5 100644 --- a/lib/Analysis/Consumed.cpp +++ b/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 CS = BI->getAs()) + 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 CS = BI->getAs()) 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(); diff --git a/test/SemaCXX/warn-consumed-analysis.cpp b/test/SemaCXX/warn-consumed-analysis.cpp index 8a55c8820a..e7380b97fe 100644 --- a/test/SemaCXX/warn-consumed-analysis.cpp +++ b/test/SemaCXX/warn-consumed-analysis.cpp @@ -546,14 +546,36 @@ void testWhileLoop1() { ConsumableClass 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 + -- 2.40.0