[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