diff options
author | Tom Care <tom.care@uqconnect.edu.au> | 2010-08-18 21:17:24 +0000 |
---|---|---|
committer | Tom Care <tom.care@uqconnect.edu.au> | 2010-08-18 21:17:24 +0000 |
commit | 245adabd97c8c770c13935a9075f2243cc6f1d57 (patch) | |
tree | abd01e8a0c55aba1aada82bd5925104b060f6472 /lib/Checker/IdempotentOperationChecker.cpp | |
parent | 5e1e89b8af283af34943a477dc6378f1a641df26 (diff) |
Added psuedo-constant analysis and integrated it into the false positive reduction stage in IdempotentOperationChecker.
- Renamed IdempotentOperationChecker::isConstant to isConstantOrPseudoConstant to better reflect the function
- Changed IdempotentOperationChecker::PreVisitBinaryOperator to only run 'CanVary' once on undefined assumptions
- Created new PsuedoConstantAnalysis class and added it to AnalysisContext
- Changed IdempotentOperationChecker to exploit the new analysis
- Updated tests with psuedo-constants
- Added check to IdempotentOperationChecker to see if a Decl is const qualified
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111426 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Checker/IdempotentOperationChecker.cpp')
-rw-r--r-- | lib/Checker/IdempotentOperationChecker.cpp | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/lib/Checker/IdempotentOperationChecker.cpp b/lib/Checker/IdempotentOperationChecker.cpp index 4f2810ea94..885123ae24 100644 --- a/lib/Checker/IdempotentOperationChecker.cpp +++ b/lib/Checker/IdempotentOperationChecker.cpp @@ -44,6 +44,7 @@ #include "GRExprEngineExperimentalChecks.h" #include "clang/Analysis/CFGStmtMap.h" +#include "clang/Analysis/Analyses/PsuedoConstantAnalysis.h" #include "clang/Checker/BugReporter/BugType.h" #include "clang/Checker/PathSensitive/CheckerHelpers.h" #include "clang/Checker/PathSensitive/CheckerVisitor.h" @@ -72,16 +73,16 @@ class IdempotentOperationChecker void UpdateAssumption(Assumption &A, const Assumption &New); - /// contains* - Useful recursive methods to see if a statement contains an - /// element somewhere. Used in static analysis to reduce false positives. + // False positive reduction methods static bool isParameterSelfAssign(const Expr *LHS, const Expr *RHS); static bool isTruncationExtensionAssignment(const Expr *LHS, const Expr *RHS); static bool PathWasCompletelyAnalyzed(const CFG *C, const CFGBlock *CB, const GRCoreEngine &CE); - static bool CanVary(const Expr *Ex, ASTContext &Ctx); - static bool isPseudoConstant(const DeclRefExpr *D); + static bool CanVary(const Expr *Ex, AnalysisContext *AC); + static bool isConstantOrPseudoConstant(const DeclRefExpr *DR, + AnalysisContext *AC); // Hash table typedef llvm::DenseMap<const BinaryOperator *, @@ -108,7 +109,8 @@ void IdempotentOperationChecker::PreVisitBinaryOperator( // 'Possible'. std::pair<Assumption, AnalysisContext *> &Data = hash[B]; Assumption &A = Data.first; - Data.second = C.getCurrentAnalysisContext(); + AnalysisContext *AC = C.getCurrentAnalysisContext(); + Data.second = AC; // If we already have visited this node on a path that does not contain an // idempotent operation, return immediately. @@ -119,8 +121,14 @@ void IdempotentOperationChecker::PreVisitBinaryOperator( // may mean this is a false positive. const Expr *LHS = B->getLHS(); const Expr *RHS = B->getRHS(); - bool LHSCanVary = CanVary(LHS, C.getASTContext()); - bool RHSCanVary = CanVary(RHS, C.getASTContext()); + + // Check if either side can vary. We only need to calculate this when we have + // no assumption. + bool LHSCanVary = true, RHSCanVary = true; + if (A == Possible) { + LHSCanVary = CanVary(LHS, AC); + RHSCanVary = CanVary(RHS, AC); + } const GRState *state = C.getState(); @@ -486,7 +494,8 @@ bool IdempotentOperationChecker::PathWasCompletelyAnalyzed( // that varies. This could be due to a compile-time constant like sizeof. An // expression may also involve a variable that behaves like a constant. The // function returns true if the expression varies, and false otherwise. -bool IdempotentOperationChecker::CanVary(const Expr *Ex, ASTContext &Ctx) { +bool IdempotentOperationChecker::CanVary(const Expr *Ex, + AnalysisContext *AC) { // Parentheses and casts are irrelevant here Ex = Ex->IgnoreParenCasts(); @@ -531,12 +540,13 @@ bool IdempotentOperationChecker::CanVary(const Expr *Ex, ASTContext &Ctx) { return SE->getTypeOfArgument()->isVariableArrayType(); } case Stmt::DeclRefExprClass: - return !isPseudoConstant(cast<DeclRefExpr>(Ex)); + return !isConstantOrPseudoConstant(cast<DeclRefExpr>(Ex), AC); // The next cases require recursion for subexpressions case Stmt::BinaryOperatorClass: { const BinaryOperator *B = cast<const BinaryOperator>(Ex); - return CanVary(B->getRHS(), Ctx) || CanVary(B->getLHS(), Ctx); + return CanVary(B->getRHS(), AC) + || CanVary(B->getLHS(), AC); } case Stmt::UnaryOperatorClass: { const UnaryOperator *U = cast<const UnaryOperator>(Ex); @@ -545,18 +555,25 @@ bool IdempotentOperationChecker::CanVary(const Expr *Ex, ASTContext &Ctx) { case UnaryOperator::Extension: return false; default: - return CanVary(U->getSubExpr(), Ctx); + return CanVary(U->getSubExpr(), AC); } } case Stmt::ChooseExprClass: - return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr(Ctx), Ctx); + return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr( + AC->getASTContext()), AC); case Stmt::ConditionalOperatorClass: - return CanVary(cast<const ConditionalOperator>(Ex)->getCond(), Ctx); + return CanVary(cast<const ConditionalOperator>(Ex)->getCond(), AC); } } -// Returns true if a DeclRefExpr behaves like a constant. -bool IdempotentOperationChecker::isPseudoConstant(const DeclRefExpr *DR) { +// Returns true if a DeclRefExpr is or behaves like a constant. +bool IdempotentOperationChecker::isConstantOrPseudoConstant( + const DeclRefExpr *DR, + AnalysisContext *AC) { + // Check if the type of the Decl is const-qualified + if (DR->getType().isConstQualified()) + return true; + // Check for an enum if (isa<EnumConstantDecl>(DR->getDecl())) return true; @@ -567,5 +584,10 @@ bool IdempotentOperationChecker::isPseudoConstant(const DeclRefExpr *DR) { if (VD->isStaticLocal()) return true; + // Check if the Decl behaves like a constant + PsuedoConstantAnalysis *PCA = AC->getPsuedoConstantAnalysis(); + if (PCA->isPsuedoConstant(DR->getDecl())) + return true; + return false; } |