diff options
-rw-r--r-- | lib/Checker/IdempotentOperationChecker.cpp | 18 | ||||
-rw-r--r-- | test/Analysis/idempotent-operations.c | 6 |
2 files changed, 20 insertions, 4 deletions
diff --git a/lib/Checker/IdempotentOperationChecker.cpp b/lib/Checker/IdempotentOperationChecker.cpp index 74f4a62ccc..4f2810ea94 100644 --- a/lib/Checker/IdempotentOperationChecker.cpp +++ b/lib/Checker/IdempotentOperationChecker.cpp @@ -81,6 +81,7 @@ class IdempotentOperationChecker const CFGBlock *CB, const GRCoreEngine &CE); static bool CanVary(const Expr *Ex, ASTContext &Ctx); + static bool isPseudoConstant(const DeclRefExpr *D); // Hash table typedef llvm::DenseMap<const BinaryOperator *, @@ -530,8 +531,7 @@ bool IdempotentOperationChecker::CanVary(const Expr *Ex, ASTContext &Ctx) { return SE->getTypeOfArgument()->isVariableArrayType(); } case Stmt::DeclRefExprClass: - // return !IsPseudoConstant(cast<DeclRefExpr>(Ex)); - return true; + return !isPseudoConstant(cast<DeclRefExpr>(Ex)); // The next cases require recursion for subexpressions case Stmt::BinaryOperatorClass: { @@ -555,3 +555,17 @@ bool IdempotentOperationChecker::CanVary(const Expr *Ex, ASTContext &Ctx) { } } +// Returns true if a DeclRefExpr behaves like a constant. +bool IdempotentOperationChecker::isPseudoConstant(const DeclRefExpr *DR) { + // Check for an enum + if (isa<EnumConstantDecl>(DR->getDecl())) + return true; + + // Check for a static variable + // FIXME: Analysis should model static vars + if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) + if (VD->isStaticLocal()) + return true; + + return false; +} diff --git a/test/Analysis/idempotent-operations.c b/test/Analysis/idempotent-operations.c index 23401e8cdb..a54a3aae08 100644 --- a/test/Analysis/idempotent-operations.c +++ b/test/Analysis/idempotent-operations.c @@ -74,12 +74,14 @@ void bailout() { // False positive tests unsigned false1() { - return (5 - 2 - 3); // no-warning + int a = 10; + return a * (5 - 2 - 3); // no-warning } enum testenum { enum1 = 0, enum2 }; unsigned false2() { - return enum1; // no-warning + int a = 1234; + return enum1 + a; // no-warning } extern unsigned foo(); |