mirror of https://github.com/microsoft/clang.git
Remove PseudoConstantAnalysis
Summary: It's not used anywhere for years. The last usage is removed in https://reviews.llvm.org/rL198476 in 2014. Subscribers: mgorny, cfe-commits Differential Revision: https://reviews.llvm.org/D51946 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342246 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2f62ceaf73
commit
ccd349c348
|
@ -1,45 +0,0 @@
|
||||||
//== PseudoConstantAnalysis.h - Find Pseudo-constants 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.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H
|
|
||||||
#define LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H
|
|
||||||
|
|
||||||
#include "clang/AST/Stmt.h"
|
|
||||||
|
|
||||||
namespace clang {
|
|
||||||
|
|
||||||
class PseudoConstantAnalysis {
|
|
||||||
public:
|
|
||||||
PseudoConstantAnalysis(const Stmt *DeclBody);
|
|
||||||
~PseudoConstantAnalysis();
|
|
||||||
|
|
||||||
bool isPseudoConstant(const VarDecl *VD);
|
|
||||||
bool wasReferenced(const VarDecl *VD);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void RunAnalysis();
|
|
||||||
inline static const Decl *getDecl(const Expr *E);
|
|
||||||
|
|
||||||
// for storing the result of analyzed ValueDecls
|
|
||||||
void *NonConstantsImpl;
|
|
||||||
void *UsedVarsImpl;
|
|
||||||
|
|
||||||
const Stmt *DeclBody;
|
|
||||||
bool Analyzed;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -40,7 +40,6 @@ class ImplicitParamDecl;
|
||||||
class LocationContext;
|
class LocationContext;
|
||||||
class LocationContextManager;
|
class LocationContextManager;
|
||||||
class ParentMap;
|
class ParentMap;
|
||||||
class PseudoConstantAnalysis;
|
|
||||||
class StackFrameContext;
|
class StackFrameContext;
|
||||||
class Stmt;
|
class Stmt;
|
||||||
class VarDecl;
|
class VarDecl;
|
||||||
|
@ -84,7 +83,6 @@ class AnalysisDeclContext {
|
||||||
bool builtCFG = false;
|
bool builtCFG = false;
|
||||||
bool builtCompleteCFG = false;
|
bool builtCompleteCFG = false;
|
||||||
std::unique_ptr<ParentMap> PM;
|
std::unique_ptr<ParentMap> PM;
|
||||||
std::unique_ptr<PseudoConstantAnalysis> PCA;
|
|
||||||
std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
|
std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
|
||||||
|
|
||||||
llvm::BumpPtrAllocator A;
|
llvm::BumpPtrAllocator A;
|
||||||
|
@ -175,7 +173,6 @@ public:
|
||||||
bool isCFGBuilt() const { return builtCFG; }
|
bool isCFGBuilt() const { return builtCFG; }
|
||||||
|
|
||||||
ParentMap &getParentMap();
|
ParentMap &getParentMap();
|
||||||
PseudoConstantAnalysis *getPseudoConstantAnalysis();
|
|
||||||
|
|
||||||
using referenced_decls_iterator = const VarDecl * const *;
|
using referenced_decls_iterator = const VarDecl * const *;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "clang/AST/StmtCXX.h"
|
#include "clang/AST/StmtCXX.h"
|
||||||
#include "clang/AST/StmtVisitor.h"
|
#include "clang/AST/StmtVisitor.h"
|
||||||
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
|
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
|
||||||
#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
|
|
||||||
#include "clang/Analysis/BodyFarm.h"
|
#include "clang/Analysis/BodyFarm.h"
|
||||||
#include "clang/Analysis/CFG.h"
|
#include "clang/Analysis/CFG.h"
|
||||||
#include "clang/Analysis/CFGStmtMap.h"
|
#include "clang/Analysis/CFGStmtMap.h"
|
||||||
|
@ -292,12 +291,6 @@ ParentMap &AnalysisDeclContext::getParentMap() {
|
||||||
return *PM;
|
return *PM;
|
||||||
}
|
}
|
||||||
|
|
||||||
PseudoConstantAnalysis *AnalysisDeclContext::getPseudoConstantAnalysis() {
|
|
||||||
if (!PCA)
|
|
||||||
PCA.reset(new PseudoConstantAnalysis(getBody()));
|
|
||||||
return PCA.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
|
AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
|
||||||
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||||
// Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
|
// Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
|
||||||
|
|
|
@ -23,7 +23,6 @@ add_clang_library(clangAnalysis
|
||||||
PostOrderCFGView.cpp
|
PostOrderCFGView.cpp
|
||||||
PrintfFormatString.cpp
|
PrintfFormatString.cpp
|
||||||
ProgramPoint.cpp
|
ProgramPoint.cpp
|
||||||
PseudoConstantAnalysis.cpp
|
|
||||||
ReachableCode.cpp
|
ReachableCode.cpp
|
||||||
ScanfFormatString.cpp
|
ScanfFormatString.cpp
|
||||||
ThreadSafety.cpp
|
ThreadSafety.cpp
|
||||||
|
|
|
@ -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())
|
|
||||||
}
|
|
Loading…
Reference in New Issue