[cfe-commits] r112098 - in /cfe/trunk: include/clang/Analysis/Analyses/PseudoConstantAnalysis.h lib/Analysis/PseudoConstantAnalysis.cpp test/Analysis/idempotent-operations.c
Tom Care
tcare at apple.com
Wed Aug 25 15:37:26 PDT 2010
Author: tcare
Date: Wed Aug 25 17:37:26 2010
New Revision: 112098
URL: http://llvm.org/viewvc/llvm-project?rev=112098&view=rev
Log:
Improved the handling of blocks and block variables in PseudoConstantAnalysis
- Removed the assumption that __block vars are all non-constant
- Simplified some repetitive code in RunAnalysis
- Added block walking support
- Code/comments cleanup
- Separated out test for block pseudoconstants
Modified:
cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp
cfe/trunk/test/Analysis/idempotent-operations.c
Modified: cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h?rev=112098&r1=112097&r2=112098&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h Wed Aug 25 17:37:26 2010
@@ -30,6 +30,7 @@
private:
void RunAnalysis();
+ inline static const Decl *getDecl(const Expr *E);
// for storing the result of analyzed ValueDecls
void *NonConstantsImpl;
Modified: cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp?rev=112098&r1=112097&r2=112098&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp (original)
+++ cfe/trunk/lib/Analysis/PseudoConstantAnalysis.cpp Wed Aug 25 17:37:26 2010
@@ -64,6 +64,16 @@
return UsedVars->count(VD);
}
+// Returns a Decl from a (Block)DeclRefExpr (if any)
+const Decl *PseudoConstantAnalysis::getDecl(const Expr *E) {
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
+ return DR->getDecl();
+ else if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(E))
+ return BDR->getDecl();
+ else
+ return 0;
+}
+
void PseudoConstantAnalysis::RunAnalysis() {
std::deque<const Stmt *> WorkList;
VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl;
@@ -77,28 +87,28 @@
WorkList.pop_front();
switch (Head->getStmtClass()) {
- // Case 1: Assignment operators modifying ValueDecl
+ // Case 1: Assignment operators modifying VarDecls
case Stmt::BinaryOperatorClass: {
const BinaryOperator *BO = cast<BinaryOperator>(Head);
- const Expr *LHS = BO->getLHS()->IgnoreParenCasts();
- const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS);
+ // Look for a Decl on the LHS
+ const Decl *LHSDecl = getDecl(BO->getLHS()->IgnoreParenCasts());
- // We only care about DeclRefExprs on the LHS
- if (!DR)
+ if (!LHSDecl)
break;
// We found a binary operator with a DeclRefExpr on the LHS. We now check
// for any of the assignment operators, implying that this Decl is being
// written to.
switch (BO->getOpcode()) {
+ // Self-assignments don't count as use of a variable
case BO_Assign: {
- const Expr *RHS = BO->getRHS()->IgnoreParenCasts();
- if (const DeclRefExpr *RHSDecl = dyn_cast<DeclRefExpr>(RHS)) {
- // Self-assignments don't count as use of a variable
- if (DR->getDecl() == RHSDecl->getDecl())
- // Do not visit the children
- continue;
- }
+ // Look for a DeclRef on the RHS
+ const Decl *RHSDecl = getDecl(BO->getRHS()->IgnoreParenCasts());
+
+ // If the Decls match, we have self-assignment
+ if (LHSDecl == RHSDecl)
+ // Do not visit the children
+ continue;
}
case BO_AddAssign:
@@ -110,8 +120,8 @@
case BO_XorAssign:
case BO_ShlAssign:
case BO_ShrAssign: {
+ const VarDecl *VD = dyn_cast<VarDecl>(LHSDecl);
// The DeclRefExpr is being assigned to - mark it as non-constant
- const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
if (VD)
NonConstants->insert(VD);
break;
@@ -126,14 +136,11 @@
// Case 2: Pre/post increment/decrement and address of
case Stmt::UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(Head);
- const Expr *SubExpr = UO->getSubExpr()->IgnoreParenImpCasts();
- const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(SubExpr);
- // We only care about DeclRefExprs in the subexpression
- if (!DR)
- break;
+ // Look for a DeclRef in the subexpression
+ const Decl *D = getDecl(UO->getSubExpr()->IgnoreParenCasts());
- // We found a unary operator with a DeclRefExpr as a subexpression. We now
+ // We found a unary operator with a DeclRef as a subexpression. We now
// check for any of the increment/decrement operators, as well as
// addressOf.
switch (UO->getOpcode()) {
@@ -141,11 +148,11 @@
case UO_PostInc:
case UO_PreDec:
case UO_PreInc:
- // The DeclRefExpr is being changed - mark it as non-constant
+ // The DeclRef is being changed - mark it as non-constant
case UO_AddrOf: {
// If we are taking the address of the DeclRefExpr, assume it is
// non-constant.
- const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ const VarDecl *VD = dyn_cast<VarDecl>(D);
if (VD)
NonConstants->insert(VD);
break;
@@ -161,8 +168,8 @@
case Stmt::DeclStmtClass: {
const DeclStmt *DS = cast<DeclStmt>(Head);
// Iterate over each decl and see if any of them contain reference decls
- for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
- I != E; ++I) {
+ for (DeclStmt::const_decl_iterator I = DS->decl_begin(),
+ E = DS->decl_end(); I != E; ++I) {
// We only care about VarDecls
const VarDecl *VD = dyn_cast<VarDecl>(*I);
if (!VD)
@@ -172,23 +179,24 @@
if (!VD->getType().getTypePtr()->isReferenceType())
continue;
+ // Try to find a Decl in the initializer
+ const Decl *D = getDecl(VD->getInit()->IgnoreParenCasts());
+
// If the reference is to another var, add the var to the non-constant
// list
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(VD->getInit()))
- if (const VarDecl *RefVD = dyn_cast<VarDecl>(DR->getDecl())) {
- NonConstants->insert(RefVD);
- continue;
- }
+ if (const VarDecl *RefVD = dyn_cast<VarDecl>(D)) {
+ NonConstants->insert(RefVD);
+ continue;
+ }
}
break;
}
// Case 4: Block variable references
case Stmt::BlockDeclRefExprClass: {
- // Any block variables are assumed to be non-constant
const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(Head);
if (const VarDecl *VD = dyn_cast<VarDecl>(BDR->getDecl())) {
- NonConstants->insert(VD);
+ // Add the Decl to the used list
UsedVars->insert(VD);
continue;
}
@@ -199,12 +207,21 @@
case Stmt::DeclRefExprClass: {
const DeclRefExpr *DR = cast<DeclRefExpr>(Head);
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ // Add the Decl to the used list
UsedVars->insert(VD);
continue;
}
break;
}
+ // Case 6: Block expressions
+ case Stmt::BlockExprClass: {
+ const BlockExpr *B = cast<BlockExpr>(Head);
+ // Add the body of the block to the list
+ WorkList.push_back(B->getBody());
+ continue;
+ }
+
default:
break;
} // switch (head->getStmtClass())
Modified: cfe/trunk/test/Analysis/idempotent-operations.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/idempotent-operations.c?rev=112098&r1=112097&r2=112098&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/idempotent-operations.c (original)
+++ cfe/trunk/test/Analysis/idempotent-operations.c Wed Aug 25 17:37:26 2010
@@ -112,18 +112,34 @@
int c = 42;
test(height * c); // no-warning
- // Pseudo-constant (blockvar)
- __block int a = 0;
- int b = 10;
- a *= b; // no-warning
- test(a);
-
// Pseudo-constant (never changes after decl)
int width = height;
return width * 10; // no-warning
}
+// Block pseudoconstants
+void false4a() {
+ // Pseudo-constant
+ __block int a = 1;
+ int b = 10;
+ __block int c = 0;
+ b *= a; // no-warning
+
+ ^{
+ // Psuedoconstant block var
+ test(b * c); // no-warning
+
+ // Non-pseudoconstant block var
+ int d = 0;
+ test(b * d); // expected-warning{{The right operand to '*' is always 0}}
+ d = 5;
+ test(d);
+ }();
+
+ test(a + b);
+}
+
// Static vars are common false positives
int false5() {
static int test = 0;
More information about the cfe-commits
mailing list