summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2007-09-11 22:08:24 +0000
committerTed Kremenek <kremenek@apple.com>2007-09-11 22:08:24 +0000
commit3a5aa768c6b5bf0fb2bf9dbe52d288c721d88d68 (patch)
tree1fcd9f2732ca853739723a93d7f87e2f700195d6
parent3dd952ba7230409b189937575a9c0912de3cbb87 (diff)
downloadbcm5719-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.cpp24
-rw-r--r--clang/include/clang/AST/CFG.h40
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
OpenPOWER on IntegriCloud