From: Ted Kremenek Date: Tue, 11 Sep 2007 22:08:24 +0000 (+0000) Subject: Added static method "CFG::hasImplicitControlFlow". X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=155383b0fcd0a12a103310010f8c0d084b90b090;p=clang 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 --- 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(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