aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/PseudoConstantAnalysis.cpp
diff options
context:
space:
mode:
authorTom Care <tom.care@uqconnect.edu.au>2010-08-24 21:09:07 +0000
committerTom Care <tom.care@uqconnect.edu.au>2010-08-24 21:09:07 +0000
commitef52bcb606c73950139a775af61495f63fbc3603 (patch)
treeaafe54f1a52e53ede92f8a8b945551bec366c92c /lib/Analysis/PseudoConstantAnalysis.cpp
parent120d63cd4465230c2cd56508c7cd8e0ad00848e7 (diff)
Improvements to IdempotentOperationChecker and its use of PseudoConstantAnalysis
- Added wasReferenced function to PseudoConstantAnalysis to determine if a variable was ever referenced in a function (outside of a self-assignment) - BlockDeclRefExpr referenced variables are now explicitly added to the non-constant list - Remove unnecessary ignore of implicit casts - Generalized parameter self-assign detection to detect deliberate self-assigns of variables to avoid unused variable warnings - Updated test cases with deliberate self-assignments - Fixed bug with C++ references and pseudoconstants - Added test case for C++ references and pseudoconstants git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111965 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/PseudoConstantAnalysis.cpp')
-rw-r--r--lib/Analysis/PseudoConstantAnalysis.cpp61
1 files changed, 53 insertions, 8 deletions
diff --git a/lib/Analysis/PseudoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp
index 7a2fa8a8bd..5deabacea4 100644
--- a/lib/Analysis/PseudoConstantAnalysis.cpp
+++ b/lib/Analysis/PseudoConstantAnalysis.cpp
@@ -28,10 +28,12 @@ typedef llvm::SmallPtrSet<const VarDecl*, VARDECL_SET_SIZE> VarDeclSet;
PseudoConstantAnalysis::PseudoConstantAnalysis(const Stmt *DeclBody) :
DeclBody(DeclBody), Analyzed(false) {
NonConstantsImpl = new VarDeclSet;
+ UsedVarsImpl = new VarDeclSet;
}
PseudoConstantAnalysis::~PseudoConstantAnalysis() {
delete (VarDeclSet*)NonConstantsImpl;
+ delete (VarDeclSet*)UsedVarsImpl;
}
// Returns true if the given ValueDecl is never written to in the given DeclBody
@@ -50,9 +52,22 @@ bool PseudoConstantAnalysis::isPseudoConstant(const VarDecl *VD) {
return !NonConstants->count(VD);
}
+// Returns true if the variable was used (self assignments don't count)
+bool PseudoConstantAnalysis::wasReferenced(const VarDecl *VD) {
+ if (!Analyzed) {
+ RunAnalysis();
+ Analyzed = true;
+ }
+
+ VarDeclSet *UsedVars = (VarDeclSet*)UsedVarsImpl;
+
+ return UsedVars->count(VD);
+}
+
void PseudoConstantAnalysis::RunAnalysis() {
std::deque<const Stmt *> WorkList;
VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl;
+ VarDeclSet *UsedVars = (VarDeclSet*)UsedVarsImpl;
// Start with the top level statement of the function
WorkList.push_back(DeclBody);
@@ -65,7 +80,7 @@ void PseudoConstantAnalysis::RunAnalysis() {
// Case 1: Assignment operators modifying ValueDecl
case Stmt::BinaryOperatorClass: {
const BinaryOperator *BO = cast<BinaryOperator>(Head);
- const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
+ const Expr *LHS = BO->getLHS()->IgnoreParenCasts();
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS);
// We only care about DeclRefExprs on the LHS
@@ -76,7 +91,16 @@ void PseudoConstantAnalysis::RunAnalysis() {
// for any of the assignment operators, implying that this Decl is being
// written to.
switch (BO->getOpcode()) {
- case BinaryOperator::Assign:
+ case BinaryOperator::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;
+ }
+
+ }
case BinaryOperator::AddAssign:
case BinaryOperator::SubAssign:
case BinaryOperator::MulAssign:
@@ -148,16 +172,37 @@ void PseudoConstantAnalysis::RunAnalysis() {
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()))
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(VD->getInit()))
+ if (const VarDecl *RefVD = dyn_cast<VarDecl>(DR->getDecl())) {
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);
+ UsedVars->insert(VD);
+ continue;
}
+ break;
+ }
+
+ // Case 5: Variable references
+ case Stmt::DeclRefExprClass: {
+ const DeclRefExpr *DR = cast<DeclRefExpr>(Head);
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ UsedVars->insert(VD);
+ continue;
+ }
+ break;
}
default: