From: Tom Care Date: Mon, 16 Aug 2010 21:43:52 +0000 (+0000) Subject: Added basic psuedoconstant checking in IdempotentOperationChecker and fixed some... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=50e8ac2369951d200e0d3849465d481f20fbdb62;p=clang Added basic psuedoconstant checking in IdempotentOperationChecker and fixed some test cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111190 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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::DenseMapgetTypeOfArgument()->isVariableArrayType(); } case Stmt::DeclRefExprClass: - // return !IsPseudoConstant(cast(Ex)); - return true; + return !isPseudoConstant(cast(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(DR->getDecl())) + return true; + + // Check for a static variable + // FIXME: Analysis should model static vars + if (const VarDecl *VD = dyn_cast(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();