aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-09-13 09:53:55 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-09-13 09:53:55 +0000
commit83754162f698a5dafad93fb89be0953651a604d0 (patch)
treedfbf9ce92f2d9a4af9ce57814202b594e5b7523c
parentdba3fb5413437dc613734fa4ffac892b11a37d25 (diff)
Add a bit to the CFGBlock to track when it contains a no-return
CFGElement. This will allow greatly simplifying the logic in -Wreturn-type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139593 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Analysis/CFG.h16
-rw-r--r--lib/Analysis/CFG.cpp1
2 files changed, 16 insertions, 1 deletions
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index f380012080..f191c80281 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -333,10 +333,21 @@ class CFGBlock {
AdjacentBlocks Preds;
AdjacentBlocks Succs;
+ /// NoReturn - This bit is set when the basic block contains a function call
+ /// or implicit destructor that is attributed as 'noreturn'. In that case,
+ /// control cannot technically ever proceed past this block. All such blocks
+ /// will have a single immediate successor: the exit block. This allows them
+ /// to be easily reached from the exit block and using this bit quickly
+ /// recognized without scanning the contents of the block.
+ ///
+ /// Optimization Note: This bit could be profitably folded with Terminator's
+ /// storage if the memory usage of CFGBlock becomes an issue.
+ unsigned HasNoReturnElement : 1;
+
public:
explicit CFGBlock(unsigned blockid, BumpVectorContext &C)
: Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
- BlockID(blockid), Preds(C, 1), Succs(C, 1) {}
+ BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false) {}
~CFGBlock() {}
// Statement iterators
@@ -458,6 +469,7 @@ public:
void setTerminator(Stmt *Statement) { Terminator = Statement; }
void setLabel(Stmt *Statement) { Label = Statement; }
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
+ void setHasNoReturnElement() { HasNoReturnElement = true; }
CFGTerminator getTerminator() { return Terminator; }
const CFGTerminator getTerminator() const { return Terminator; }
@@ -473,6 +485,8 @@ public:
Stmt *getLabel() { return Label; }
const Stmt *getLabel() const { return Label; }
+ bool hasNoReturnElement() const { return HasNoReturnElement; }
+
unsigned getBlockID() const { return BlockID; }
void dump(const CFG *cfg, const LangOptions &LO) const;
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 12ff84417f..0775dcfb79 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -603,6 +603,7 @@ CFGBlock *CFGBuilder::createBlock(bool add_successor) {
/// directly tied to the exit block in order to be reachable.
CFGBlock *CFGBuilder::createNoReturnBlock() {
CFGBlock *B = createBlock(false);
+ B->setHasNoReturnElement();
addSuccessor(B, &cfg->getExit());
return B;
}