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
//===----------------------------------------------------------------------===//
return SourceRange(RetLoc);
}
+bool Stmt::hasImplicitControlFlow() const {
+ switch (sClass) {
+ default:
+ return false;
+
+ case CallExprClass:
+ case ConditionalOperatorClass:
+ case ChooseExprClass:
+ case StmtExprClass:
+ case DeclStmtClass:
+ return true;
+
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator* B = cast<BinaryOperator>(this);
+ if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma)
+ return true;
+ else
+ return false;
+ }
+ }
+}
+
//===----------------------------------------------------------------------===//
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
void print(std::ostream& OS) const;
void dump() const;
- //===--------------------------------------------------------------------===//
- // Static Predicates pertaining to CFG-related properties.
- //===--------------------------------------------------------------------===//
-
- /// 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);
-
//===--------------------------------------------------------------------===//
// Internal: constructors and data.
//===--------------------------------------------------------------------===//
// Implement isa<T> support.
static bool classof(const Stmt *) { return true; }
+ /// hasImplicitControlFlow - Some statements (e.g. short circuited operations)
+ /// contain implicit control-flow in the order their subexpressions
+ /// are evaluated. This predicate returns true if this statement has
+ /// such implicit control-flow. Such statements are also specially handled
+ /// within CFGs.
+ bool hasImplicitControlFlow() const;
+
/// Child Iterators: All subclasses must implement child_begin and child_end
/// to permit easy iteration over the substatements/subexpessions of an
/// AST node. This permits easy iteration over all nodes in the AST.