]> granicus.if.org Git - clang/commitdiff
Added static method "CFG::hasImplicitControlFlow".
authorTed Kremenek <kremenek@apple.com>
Tue, 11 Sep 2007 22:08:24 +0000 (22:08 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 11 Sep 2007 22:08:24 +0000 (22:08 +0000)
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

AST/CFG.cpp
include/clang/AST/CFG.h

index c1f96ceed32afddb8b52acf6c0c2bfadeb33edef..268fc062e4b2d5164fdb00429b4ccf6d16e76ebc 100644 (file)
@@ -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
 //===----------------------------------------------------------------------===//
index 52cb54ddc536389a422b4693d3cb83e197074041..f940a534c80df58e6c8346af9bbe0f2893439766 100644 (file)
@@ -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