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 | 155383b0fcd0a12a103310010f8c0d084b90b090 (patch) | |
| tree | 66a803cc6ba29741c2f394381985186ceca5871f | |
| parent | f50ec1026d23282d94699f079ffb5edb9dfd951f (diff) | |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41868 91177308-0d34-0410-b5e6-96231b3b80d8
| -rw-r--r-- | AST/CFG.cpp | 24 | ||||
| -rw-r--r-- | include/clang/AST/CFG.h | 40 |
2 files changed, 63 insertions, 1 deletions
diff --git a/AST/CFG.cpp b/AST/CFG.cpp index c1f96ceed3..268fc062e4 100644 --- a/AST/CFG.cpp +++ b/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/include/clang/AST/CFG.h b/include/clang/AST/CFG.h index 52cb54ddc5..f940a534c8 100644 --- a/include/clang/AST/CFG.h +++ b/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 |
