diff options
author | Ted Kremenek <kremenek@apple.com> | 2007-09-11 22:08:24 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2007-09-11 22:08:24 +0000 |
commit | 3a5aa768c6b5bf0fb2bf9dbe52d288c721d88d68 (patch) | |
tree | 1fcd9f2732ca853739723a93d7f87e2f700195d6 | |
parent | 3dd952ba7230409b189937575a9c0912de3cbb87 (diff) | |
download | bcm5719-llvm-3a5aa768c6b5bf0fb2bf9dbe52d288c721d88d68.tar.gz bcm5719-llvm-3a5aa768c6b5bf0fb2bf9dbe52d288c721d88d68.zip |
Added static method "CFG::hasImplicitControlFlow".
This method is used to determine if an expression contains implicit
control-flow, and thus appears in a distinct statement slot in the CFG.
For example:
(1) x = ... ? ... ? ...
logically becomes:
(1) ... ? ... : ... (a unique statement slot for the ternary ?)
(2) x = [E1] (where E1 is actually the ConditionalOperator*)
A client of the CFG, when walking the statement at (2), will encounter
E1. In this case, hasImplicitControlFlow(E1) == true, and the client
will know that the expression E1 is explicitly placed into its own statement
slot to capture the implicit control-flow it has.
llvm-svn: 41868
-rw-r--r-- | clang/AST/CFG.cpp | 24 | ||||
-rw-r--r-- | clang/include/clang/AST/CFG.h | 40 |
2 files changed, 63 insertions, 1 deletions
diff --git a/clang/AST/CFG.cpp b/clang/AST/CFG.cpp index c1f96ceed32..268fc062e4b 100644 --- a/clang/AST/CFG.cpp +++ b/clang/AST/CFG.cpp @@ -1240,6 +1240,30 @@ void CFGBlock::print(std::ostream& OS, const CFG* cfg) const { print_block(OS, cfg, *this, &Helper, true); } +/// hasImplicitControlFlow - Returns true if a given expression is +/// is represented within a CFG as having a designated "statement slot" +bool CFG::hasImplicitControlFlow(const Stmt* S) { + switch (S->getStmtClass()) { + default: + return false; + + case Stmt::CallExprClass: + case Stmt::ConditionalOperatorClass: + case Stmt::ChooseExprClass: + case Stmt::StmtExprClass: + case Stmt::DeclStmtClass: + return true; + + case Stmt::BinaryOperatorClass: { + const BinaryOperator* B = cast<BinaryOperator>(S); + if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma) + return true; + else + return false; + } + } +} + //===----------------------------------------------------------------------===// // CFG Graphviz Visualization //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/AST/CFG.h b/clang/include/clang/AST/CFG.h index 52cb54ddc53..f940a534c80 100644 --- a/clang/include/clang/AST/CFG.h +++ b/clang/include/clang/AST/CFG.h @@ -222,7 +222,45 @@ public: void print(std::ostream& OS) const; void dump() const; void setEntry(CFGBlock *B) { Entry = B; } - void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; } + void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; } + + // Useful Predicates + + /// hasImplicitControlFlow - Returns true if a given expression is + /// is represented within a CFG as having a designated "statement slot" + /// within a CFGBlock to represent the execution of that expression. This + /// is usefull for expressions that contain implicit control flow, such + /// as &&, ||, and ? operators, as well as commas and statement expressions. + /// + /// For example, considering a CFGBlock with the following statement: + /// + /// (1) x = ... ? ... ? ... + /// + /// When the CFG is built, this logically becomes: + /// + /// (1) ... ? ... : ... (a unique statement slot for the ternary ?) + /// (2) x = [E1] (where E1 is actually the ConditionalOperator*) + /// + /// A client of the CFG, when walking the statement at (2), will encounter + /// E1. In this case, hasImplicitControlFlow(E1) == true, and the client + /// will know that the expression E1 is explicitly placed into its own + /// statement slot to capture the implicit control-flow it has. + /// + /// Special cases: + /// + /// (1) Function calls. + /// Function calls are placed in their own statement slot so that + /// that we have a clear identification of "call-return" sites. If + /// you see a CallExpr nested as a subexpression of E, the CallExpr appears + /// in a statement slot in the CFG that dominates the location of E. + /// + /// (2) DeclStmts + /// We include DeclStmts because the initializer expressions for Decls + /// will be separated out into distinct statements in the CFG. These + /// statements will dominate the Decl. + /// + static bool hasImplicitControlFlow(const Stmt* S); + }; } // end namespace clang |