diff options
author | Tom Care <tom.care@uqconnect.edu.au> | 2010-08-23 19:51:57 +0000 |
---|---|---|
committer | Tom Care <tom.care@uqconnect.edu.au> | 2010-08-23 19:51:57 +0000 |
commit | db34ab70961ca4b24b600eb47053d7af304659f5 (patch) | |
tree | 5ba1642fe5209ca1eb78e85a856cd87dd0bc61d9 /lib/Analysis | |
parent | 6d72cbedbab7eea947f34ddc6a44c3b308530034 (diff) |
Several small changes to PseudoConstantAnalysis and the way IdempotentOperationChecker uses it.
- Psuedo -> Pseudo (doh...)
- C++ reference support
- Added pseudoconstant test case for __block vars
- Separated out static local checking from pseudoconstant analysis and generalized to non-local checking
- Added missing test cases for storage false positives
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111832 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/AnalysisContext.cpp | 6 | ||||
-rw-r--r-- | lib/Analysis/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/Analysis/PseudoConstantAnalysis.cpp (renamed from lib/Analysis/PsuedoConstantAnalysis.cpp) | 74 |
3 files changed, 68 insertions, 14 deletions
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index 934a031b3a..2c337f07c3 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -18,7 +18,7 @@ #include "clang/AST/ParentMap.h" #include "clang/AST/StmtVisitor.h" #include "clang/Analysis/Analyses/LiveVariables.h" -#include "clang/Analysis/Analyses/PsuedoConstantAnalysis.h" +#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/Support/BumpVector.h" @@ -84,9 +84,9 @@ ParentMap &AnalysisContext::getParentMap() { return *PM; } -PsuedoConstantAnalysis *AnalysisContext::getPsuedoConstantAnalysis() { +PseudoConstantAnalysis *AnalysisContext::getPseudoConstantAnalysis() { if (!PCA) - PCA = new PsuedoConstantAnalysis(getBody()); + PCA = new PseudoConstantAnalysis(getBody()); return PCA; } diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index 514042bf9a..850e9b4681 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -7,7 +7,7 @@ add_clang_library(clangAnalysis FormatString.cpp LiveVariables.cpp PrintfFormatString.cpp - PsuedoConstantAnalysis.cpp + PseudoConstantAnalysis.cpp ReachableCode.cpp ScanfFormatString.cpp UninitializedValues.cpp diff --git a/lib/Analysis/PsuedoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp index a169f89fe1..7a2fa8a8bd 100644 --- a/lib/Analysis/PsuedoConstantAnalysis.cpp +++ b/lib/Analysis/PseudoConstantAnalysis.cpp @@ -1,4 +1,4 @@ -//== PsuedoConstantAnalysis.cpp - Find Psuedoconstants in the AST-*- C++ -*-==// +//== PseudoConstantAnalysis.cpp - Find Pseudoconstants in the AST-*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -13,7 +13,7 @@ // //===----------------------------------------------------------------------===// -#include "clang/Analysis/Analyses/PsuedoConstantAnalysis.h" +#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/Stmt.h" @@ -21,18 +21,38 @@ using namespace clang; +// The number of ValueDecls we want to keep track of by default (per-function) +#define VARDECL_SET_SIZE 256 +typedef llvm::SmallPtrSet<const VarDecl*, VARDECL_SET_SIZE> VarDeclSet; + +PseudoConstantAnalysis::PseudoConstantAnalysis(const Stmt *DeclBody) : + DeclBody(DeclBody), Analyzed(false) { + NonConstantsImpl = new VarDeclSet; +} + +PseudoConstantAnalysis::~PseudoConstantAnalysis() { + delete (VarDeclSet*)NonConstantsImpl; +} + // Returns true if the given ValueDecl is never written to in the given DeclBody -bool PsuedoConstantAnalysis::isPsuedoConstant(const ValueDecl *VD) { +bool PseudoConstantAnalysis::isPseudoConstant(const VarDecl *VD) { + // Only local and static variables can be pseudoconstants + if (!VD->hasLocalStorage() && !VD->isStaticLocal()) + return false; + if (!Analyzed) { RunAnalysis(); Analyzed = true; } - return !NonConstants.count(VD); + VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl; + + return !NonConstants->count(VD); } -void PsuedoConstantAnalysis::RunAnalysis() { +void PseudoConstantAnalysis::RunAnalysis() { std::deque<const Stmt *> WorkList; + VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl; // Start with the top level statement of the function WorkList.push_back(DeclBody); @@ -65,10 +85,13 @@ void PsuedoConstantAnalysis::RunAnalysis() { case BinaryOperator::OrAssign: case BinaryOperator::XorAssign: case BinaryOperator::ShlAssign: - case BinaryOperator::ShrAssign: + case BinaryOperator::ShrAssign: { // The DeclRefExpr is being assigned to - mark it as non-constant - NonConstants.insert(DR->getDecl()); - continue; // Continue without looking at children + const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); + if (VD) + NonConstants->insert(VD); + break; + } default: break; @@ -95,10 +118,14 @@ void PsuedoConstantAnalysis::RunAnalysis() { case UnaryOperator::PreDec: case UnaryOperator::PreInc: // The DeclRefExpr is being changed - mark it as non-constant - case UnaryOperator::AddrOf: + case UnaryOperator::AddrOf: { // If we are taking the address of the DeclRefExpr, assume it is // non-constant. - NonConstants.insert(DR->getDecl()); + const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); + if (VD) + NonConstants->insert(VD); + break; + } default: break; @@ -106,6 +133,33 @@ void PsuedoConstantAnalysis::RunAnalysis() { break; } + // Case 3: Reference Declarations + 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) { + // We only care about VarDecls + const VarDecl *VD = dyn_cast<VarDecl>(*I); + if (!VD) + continue; + + // We found a VarDecl; make sure it is a reference type + if (!VD->getType().getTypePtr()->isReferenceType()) + continue; + + // Ignore VarDecls without a body + if (!VD->getBody()) + continue; + + // If the reference is to another var, add the var to the non-constant + // list + if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(VD->getBody())) + if (const VarDecl *RefVD = dyn_cast<VarDecl>(DR->getDecl())) + NonConstants->insert(RefVD); + } + } + default: break; } // switch (head->getStmtClass()) |