aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/PseudoConstantAnalysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/PseudoConstantAnalysis.cpp')
-rw-r--r--lib/Analysis/PseudoConstantAnalysis.cpp226
1 files changed, 0 insertions, 226 deletions
diff --git a/lib/Analysis/PseudoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp
deleted file mode 100644
index 83b545a7be83..000000000000
--- a/lib/Analysis/PseudoConstantAnalysis.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-//== PseudoConstantAnalysis.cpp - Find Pseudoconstants in the AST-*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file tracks the usage of variables in a Decl body to see if they are
-// never written to, implying that they constant. This is useful in static
-// analysis to see if a developer might have intended a variable to be const.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Stmt.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include <deque>
-
-using namespace clang;
-
-typedef llvm::SmallPtrSet<const VarDecl*, 32> 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
-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;
- }
-
- VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl;
-
- 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);
-}
-
-// Returns a Decl from a (Block)DeclRefExpr (if any)
-const Decl *PseudoConstantAnalysis::getDecl(const Expr *E) {
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
- return DR->getDecl();
- else
- return nullptr;
-}
-
-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);
-
- while (!WorkList.empty()) {
- const Stmt *Head = WorkList.front();
- WorkList.pop_front();
-
- if (const Expr *Ex = dyn_cast<Expr>(Head))
- Head = Ex->IgnoreParenCasts();
-
- switch (Head->getStmtClass()) {
- // Case 1: Assignment operators modifying VarDecls
- case Stmt::BinaryOperatorClass: {
- const BinaryOperator *BO = cast<BinaryOperator>(Head);
- // Look for a Decl on the LHS
- const Decl *LHSDecl = getDecl(BO->getLHS()->IgnoreParenCasts());
- if (!LHSDecl)
- break;
-
- // We found a binary operator with a DeclRefExpr on the LHS. We now check
- // for any of the assignment operators, implying that this Decl is being
- // written to.
- switch (BO->getOpcode()) {
- // Self-assignments don't count as use of a variable
- case BO_Assign: {
- // Look for a DeclRef on the RHS
- const Decl *RHSDecl = getDecl(BO->getRHS()->IgnoreParenCasts());
-
- // If the Decls match, we have self-assignment
- if (LHSDecl == RHSDecl)
- // Do not visit the children
- continue;
-
- LLVM_FALLTHROUGH;
- }
- case BO_AddAssign:
- case BO_SubAssign:
- case BO_MulAssign:
- case BO_DivAssign:
- case BO_AndAssign:
- case BO_OrAssign:
- case BO_XorAssign:
- case BO_ShlAssign:
- case BO_ShrAssign: {
- const VarDecl *VD = dyn_cast<VarDecl>(LHSDecl);
- // The DeclRefExpr is being assigned to - mark it as non-constant
- if (VD)
- NonConstants->insert(VD);
- break;
- }
-
- default:
- break;
- }
- break;
- }
-
- // Case 2: Pre/post increment/decrement and address of
- case Stmt::UnaryOperatorClass: {
- const UnaryOperator *UO = cast<UnaryOperator>(Head);
-
- // Look for a DeclRef in the subexpression
- const Decl *D = getDecl(UO->getSubExpr()->IgnoreParenCasts());
- if (!D)
- break;
-
- // We found a unary operator with a DeclRef as a subexpression. We now
- // check for any of the increment/decrement operators, as well as
- // addressOf.
- switch (UO->getOpcode()) {
- case UO_PostDec:
- case UO_PostInc:
- case UO_PreDec:
- case UO_PreInc:
- // The DeclRef is being changed - mark it as non-constant
- case UO_AddrOf: {
- // If we are taking the address of the DeclRefExpr, assume it is
- // non-constant.
- const VarDecl *VD = dyn_cast<VarDecl>(D);
- if (VD)
- NonConstants->insert(VD);
- break;
- }
-
- default:
- break;
- }
- 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 (const auto *I : DS->decls()) {
- // 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;
-
- // Try to find a Decl in the initializer
- const Decl *D = getDecl(VD->getInit()->IgnoreParenCasts());
- if (!D)
- break;
-
- // If the reference is to another var, add the var to the non-constant
- // list
- if (const VarDecl *RefVD = dyn_cast<VarDecl>(D)) {
- NonConstants->insert(RefVD);
- continue;
- }
- }
- break;
- }
-
- // Case 4: Variable references
- case Stmt::DeclRefExprClass: {
- const DeclRefExpr *DR = cast<DeclRefExpr>(Head);
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
- // Add the Decl to the used list
- UsedVars->insert(VD);
- continue;
- }
- break;
- }
-
- // Case 5: Block expressions
- case Stmt::BlockExprClass: {
- const BlockExpr *B = cast<BlockExpr>(Head);
- // Add the body of the block to the list
- WorkList.push_back(B->getBody());
- continue;
- }
-
- default:
- break;
- } // switch (head->getStmtClass())
-
- // Add all substatements to the worklist
- for (const Stmt *SubStmt : Head->children())
- if (SubStmt)
- WorkList.push_back(SubStmt);
- } // while (!WorkList.empty())
-}