class VarUseAnalyze {
public:
VarUseAnalyze(ASTContext *TheContext) : Context(TheContext){};
void getDeclRefs(const Stmt *CodeContext, const Decl *Variable,
llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {
auto AddDeclRefs = [DeclRefs](const ArrayRef<BoundNodes> Matches) {
for (const auto &Match : Matches) {
const auto *DeclRef = Match.getNodeAs<DeclRefExpr>("declref");
if (DeclRef) {
// Ignore uses of a standard smart pointer that don't dereference
// the pointer.
DeclRefs->insert(DeclRef);
}
}
};
auto DeclRefMatcher =
declRefExpr(hasDeclaration(equalsNode(Variable))).bind("declref");
AddDeclRefs(match(traverse(TK_AsIs, findAll(DeclRefMatcher)), *CodeContext,
*Context));
}
void getReinits(const Stmt *Block, const Decl *Variable,
llvm::SmallPtrSetImpl<const Stmt *> *Stmts,
llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {
auto DeclRefMatcher =
declRefExpr(hasDeclaration(equalsNode(Variable))).bind("declref");
// Matches different types of reinitialization.
auto ReinitMatcher =
stmt(binaryOperation(hasOperatorName("="), hasLHS(DeclRefMatcher)))
.bind("reinit");
Stmts->clear();
DeclRefs->clear();
SmallVector<BoundNodes, 1> Matches =
match(findAll(ReinitMatcher), *Block, *Context);
for (const auto &Match : Matches) {
const auto *TheStmt = Match.getNodeAs<Stmt>("reinit");
const auto *TheDeclRef = Match.getNodeAs<DeclRefExpr>("declref");
Stmts->insert(TheStmt);
DeclRefs->insert(TheDeclRef);
}
}
void getUsesAndReinits(const Stmt *Block, const ValueDecl *Variable,
llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
llvm::SmallPtrSetImpl<const Stmt *> *Reinits) {
llvm::SmallPtrSet<const DeclRefExpr *, 1> DeclRefs;
llvm::SmallPtrSet<const DeclRefExpr *, 1> ReinitDeclRefs;
getDeclRefs(Block, Variable, &DeclRefs);
getReinits(Block, Variable, Reinits, &ReinitDeclRefs);
// All references to the variable that aren't reinitializations are uses.
Uses->clear();
for (const DeclRefExpr *DeclRef : DeclRefs) {
if (!ReinitDeclRefs.count(DeclRef))
Uses->push_back(DeclRef);
}
// Sort the uses by their occurrence in the source code.
llvm::sort(*Uses, [](const DeclRefExpr *D1, const DeclRefExpr *D2) {
return D1->getExprLoc() < D2->getExprLoc();
});
}
protected:
ASTContext *Context;
std::unique_ptr<ExprSequence> Sequence;
std::unique_ptr<StmtToBlockMap> BlockMap;
llvm::SmallPtrSet<const CFGBlock *, 8> Visited;
};
for (const DeclRefExpr *DeclRef : Uses) {
const CFGBlock *RefBlock = BlockMap->blockContainingStmt(DeclRef);
if (!RefBlock)
continue;
if (0 == Reinits.size()) {
continue;
}
bool HaveDom = false;
for (const Stmt *Assgin : Reinits) {
const CFGBlock *AssBlock = BlockMap->blockContainingStmt(Assgin);
if (!AssBlock)
continue;
if (AssBlock != RefBlock) {
if (Dom.dominates(AssBlock, RefBlock)) {
HaveDom = true;
}
} else {
if (!Sequence->potentiallyAfter(Assgin, DeclRef)) {
HaveDom = true;
}
}
}
if (!HaveDom) {
DeclRef->dump();
}
}
文档更新时间: 2024-03-11 02:46 作者:suglow