[cfe-commits] r76500 - in /cfe/trunk: include/clang/Analysis/CFG.h lib/Analysis/CFG.cpp lib/Frontend/AnalysisConsumer.cpp test/Analysis/dead-stores.c

Mike Stump mrs at apple.com
Mon Jul 20 16:24:15 PDT 2009


Author: mrs
Date: Mon Jul 20 18:24:15 2009
New Revision: 76500

URL: http://llvm.org/viewvc/llvm-project?rev=76500&view=rev
Log:
Add yet more analysis for CFGs involving conditionals that are actually constant.

Modified:
    cfe/trunk/include/clang/Analysis/CFG.h
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/lib/Frontend/AnalysisConsumer.cpp
    cfe/trunk/test/Analysis/dead-stores.c

Modified: cfe/trunk/include/clang/Analysis/CFG.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CFG.h?rev=76500&r1=76499&r2=76500&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/CFG.h (original)
+++ cfe/trunk/include/clang/Analysis/CFG.h Mon Jul 20 18:24:15 2009
@@ -30,7 +30,8 @@
   class CFG;
   class PrinterHelper;
   class LangOptions;
-  
+  class ASTContext;
+
 /// CFGBlock - Represents a single basic block in a source-level CFG.
 ///  It consists of:
 ///
@@ -177,7 +178,8 @@
   void reverseStmts();
   
   void addSuccessor(CFGBlock* Block) {
-    Block->Preds.push_back(this);
+    if (Block)
+      Block->Preds.push_back(this);
     Succs.push_back(Block);
   }
   
@@ -204,7 +206,7 @@
 
   /// buildCFG - Builds a CFG from an AST.  The responsibility to free the
   ///   constructed CFG belongs to the caller.  
-  static CFG* buildCFG(Stmt* AST);  
+  static CFG* buildCFG(Stmt* AST, ASTContext *C);  
   
   /// createBlock - Create a new block in the CFG.  The CFG owns the block;
   ///  the caller should not directly free it.

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=76500&r1=76499&r2=76500&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Mon Jul 20 18:24:15 2009
@@ -62,6 +62,7 @@
 ///  implicit fall-throughs without extra basic blocks.
 ///
 class VISIBILITY_HIDDEN CFGBuilder {
+  ASTContext *Context;
   CFG* cfg;
   CFGBlock* Block;
   CFGBlock* Succ;
@@ -94,7 +95,7 @@
   ~CFGBuilder() { delete cfg; }
 
   // buildCFG - Used by external clients to construct the CFG.
-  CFG* buildCFG(Stmt* Statement);
+  CFG* buildCFG(Stmt *Statement, ASTContext *C);
 
 private:
   // Visitors to walk an AST and construct the CFG.
@@ -166,7 +167,8 @@
 ///  body (compound statement).  The ownership of the returned CFG is
 ///  transferred to the caller.  If CFG construction fails, this method returns
 ///  NULL.
-CFG* CFGBuilder::buildCFG(Stmt* Statement) {
+CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
+  Context = C;
   assert(cfg);
   if (!Statement)
     return NULL;
@@ -397,6 +399,19 @@
 CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, bool alwaysAdd) {
   if (B->isLogicalOp()) { // && or ||
 
+    // See if this is a known constant.
+    bool KnownTrue = false;
+    bool KnownFalse = false;
+    Expr::EvalResult Result;
+    if (B->getLHS()->Evaluate(Result, *Context)
+        && Result.Val.isInt()) {
+      if ((B->getOpcode() == BinaryOperator::LAnd)
+          == Result.Val.getInt().getBoolValue())
+        KnownTrue = true;
+      else
+        KnownFalse = true;
+    }
+
     CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
     ConfluenceBlock->appendStmt(B);
     
@@ -416,12 +431,24 @@
     
     // Now link the LHSBlock with RHSBlock.
     if (B->getOpcode() == BinaryOperator::LOr) {
-      LHSBlock->addSuccessor(ConfluenceBlock);
-      LHSBlock->addSuccessor(RHSBlock);
+      if (KnownTrue)
+        LHSBlock->addSuccessor(0);
+      else
+        LHSBlock->addSuccessor(ConfluenceBlock);
+      if (KnownFalse)
+        LHSBlock->addSuccessor(0);
+      else
+        LHSBlock->addSuccessor(RHSBlock);
     } else {
       assert (B->getOpcode() == BinaryOperator::LAnd);
-      LHSBlock->addSuccessor(RHSBlock);
-      LHSBlock->addSuccessor(ConfluenceBlock);
+      if (KnownFalse)
+        LHSBlock->addSuccessor(0);
+      else
+        LHSBlock->addSuccessor(RHSBlock);
+      if (KnownTrue)
+        LHSBlock->addSuccessor(0);
+      else
+        LHSBlock->addSuccessor(ConfluenceBlock);
     }
     
     // Generate the blocks for evaluating the LHS.
@@ -530,6 +557,18 @@
 }
   
 CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C) {
+  // See if this is a known constant.
+  bool KnownTrue = false;
+  bool KnownFalse = false;
+  Expr::EvalResult Result;
+  if (C->getCond()->Evaluate(Result, *Context)
+      && Result.Val.isInt()) {
+    if (Result.Val.getInt().getBoolValue())
+      KnownTrue = true;
+    else
+      KnownFalse = true;
+  }
+
   // Create the confluence block that will "merge" the results of the ternary
   // expression.
   CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
@@ -560,22 +599,36 @@
   // Create the block that will contain the condition.
   Block = createBlock(false);
   
-  if (LHSBlock)
-    Block->addSuccessor(LHSBlock);
-  else {
-    // If we have no LHS expression, add the ConfluenceBlock as a direct
-    // successor for the block containing the condition.  Moreover, we need to
-    // reverse the order of the predecessors in the ConfluenceBlock because
-    // the RHSBlock will have been added to the succcessors already, and we
-    // want the first predecessor to the the block containing the expression
-    // for the case when the ternary expression evaluates to true.
-    Block->addSuccessor(ConfluenceBlock);
-    assert (ConfluenceBlock->pred_size() == 2);
-    std::reverse(ConfluenceBlock->pred_begin(),
-                 ConfluenceBlock->pred_end());
+  if (LHSBlock) {
+    if (KnownFalse)
+      Block->addSuccessor(0);
+    else
+      Block->addSuccessor(LHSBlock);
+  } else {
+    if (KnownFalse) {
+      // If we know the condition is false, add NULL as the successor for
+      // the block containing the condition.  In this case, the confluence
+      // block will have just one predecessor.
+      Block->addSuccessor(0);
+      assert (ConfluenceBlock->pred_size() == 1);
+    } else {
+      // If we have no LHS expression, add the ConfluenceBlock as a direct
+      // successor for the block containing the condition.  Moreover, we need to
+      // reverse the order of the predecessors in the ConfluenceBlock because
+      // the RHSBlock will have been added to the succcessors already, and we
+      // want the first predecessor to the the block containing the expression
+      // for the case when the ternary expression evaluates to true.
+      Block->addSuccessor(ConfluenceBlock);
+      assert (ConfluenceBlock->pred_size() == 2);
+      std::reverse(ConfluenceBlock->pred_begin(),
+                   ConfluenceBlock->pred_end());
+    }
   }
   
-  Block->addSuccessor(RHSBlock);
+  if (KnownTrue)
+    Block->addSuccessor(0);
+  else
+    Block->addSuccessor(RHSBlock);
   
   Block->setTerminator(C);
   return addStmt(C->getCond());
@@ -648,6 +701,18 @@
 }
 
 CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
+  // See if this is a known constant first.
+  bool KnownTrue = false;
+  bool KnownFalse = false;
+  Expr::EvalResult Result;
+  if (I->getCond()->Evaluate(Result, *Context)
+      && Result.Val.isInt()) {
+    if (Result.Val.getInt().getBoolValue())
+      KnownTrue = true;
+    else
+      KnownFalse = true;
+  }
+
   // We may see an if statement in the middle of a basic block, or it may be the
   // first statement we are processing.  In either case, we create a new basic
   // block.  First, we create the blocks for the then...else statements, and
@@ -711,8 +776,14 @@
   Block->setTerminator(I);
 
   // Now add the successors.
-  Block->addSuccessor(ThenBlock);
-  Block->addSuccessor(ElseBlock);
+  if (KnownFalse)
+    Block->addSuccessor(0);
+  else
+    Block->addSuccessor(ThenBlock);
+  if (KnownTrue)
+    Block->addSuccessor(0);
+  else
+    Block->addSuccessor(ElseBlock);
 
   // Add the condition as the last statement in the new block.  This may create
   // new blocks as the condition may contain control-flow.  Any newly created
@@ -1438,9 +1509,9 @@
 
 /// buildCFG - Constructs a CFG from an AST.  Ownership of the returned
 ///  CFG is returned to the caller.
-CFG* CFG::buildCFG(Stmt* Statement) {
+CFG* CFG::buildCFG(Stmt* Statement, ASTContext *C) {
   CFGBuilder Builder;
-  return Builder.buildCFG(Statement);
+  return Builder.buildCFG(Statement, C);
 }
 
 /// reverseStmts - Reverses the orders of statements within a CFGBlock.
@@ -1826,7 +1897,10 @@
       if (i == 8 || (i-8) % 10 == 0)
         OS << "\n    ";
 
-      OS << " B" << (*I)->getBlockID();
+      if (*I)
+        OS << " B" << (*I)->getBlockID();
+      else
+        OS  << " NULL";
     }
 
     OS << '\n';

Modified: cfe/trunk/lib/Frontend/AnalysisConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/AnalysisConsumer.cpp?rev=76500&r1=76499&r2=76500&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/AnalysisConsumer.cpp (original)
+++ cfe/trunk/lib/Frontend/AnalysisConsumer.cpp Mon Jul 20 18:24:15 2009
@@ -158,7 +158,7 @@
     }
     
     virtual CFG* getCFG() {
-      if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
+      if (!cfg) cfg.reset(CFG::buildCFG(getBody(), &getContext()));
       return cfg.get();
     }
     

Modified: cfe/trunk/test/Analysis/dead-stores.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dead-stores.c?rev=76500&r1=76499&r2=76500&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/dead-stores.c (original)
+++ cfe/trunk/test/Analysis/dead-stores.c Mon Jul 20 18:24:15 2009
@@ -185,3 +185,85 @@
   }
   return 1;
 }
+
+int j;
+void f22() {
+  int x = 4;
+  int y1 = 4;
+  int y2 = 4;
+  int y3 = 4;
+  int y4 = 4;
+  int y5 = 4;
+  int y6 = 4;
+  int y7 = 4;
+  int y8 = 4;
+  int y9 = 4;
+  int y10 = 4;
+
+  ++x; // expected-warning{{never read}}
+  ++y1;
+  ++y2;
+  ++y3;
+  ++y4;
+  ++y5;
+  ++y6;
+  ++y7;
+  ++y8;
+  ++y9;
+  ++y10;
+
+  switch (j) {
+  case 1:
+    if (0)
+      (void)x;
+    if (1) {
+      (void)y1;
+      return;
+    }
+    (void)x;
+    break;
+  case 2:
+    if (0)
+      (void)x;
+    else {
+      (void)y2;
+      return;
+    }
+    (void)x;
+    break;
+  case 3:
+    if (1) {
+      (void)y3;
+      return;
+    } else
+      (void)x;
+    (void)x;
+  break;
+  case 4:
+    0 ? : ((void)y4, ({ return; }));
+    (void)x;
+    break;
+  case 5:
+    1 ? : (void)x;
+    0 ? (void)x : ((void)y5, ({ return; }));
+    (void)x;
+    break;
+  case 6:
+    1 ? ((void)y6, ({ return; })) : (void)x;
+    (void)x;
+    break;
+  case 7:
+    (void)(0 && x);
+    (void)y7;
+    (void)(0 || (y8, ({ return; }), 1));
+    (void)x;
+    break;
+  case 8:
+    (void)(1 && (y9, ({ return; }), 1));
+    (void)x;
+    break;
+  case 9:
+    (void)(1 || x);
+    (void)y10;
+  }
+}





More information about the cfe-commits mailing list