================ @@ -0,0 +1,352 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "StaticInitializationCycleCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Analysis/CallGraph.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SCCIterator.h" + +using namespace clang; +using namespace clang::ast_matchers; + +namespace { + +// Compute (for the purpose of this check) if the value of a DeclRefExpr is used +// (at runtime). +// The value is not used if it appears at LHS of an assignment or it appears +// inside a compile-time constant expression (like 'sizeof'). +bool isUnusedValue(const DeclRefExpr *DRE, ASTContext &ACtx) { + ParentMapContext &PMC = ACtx.getParentMapContext(); + DynTypedNodeList Parents = PMC.getParents(*DRE); + const BinaryOperator *ParentBO = nullptr; + while (!Parents.empty()) { + if (const Expr *E = Parents[0].get<Expr>()) { + if (E->isIntegerConstantExpr(ACtx)) + return true; + if ((ParentBO = dyn_cast<BinaryOperator>(E))) + break; + } + Parents = PMC.getParents(Parents[0]); + } + if (!ParentBO) + return false; + return ParentBO->isAssignmentOp() && + ParentBO->getLHS()->IgnoreParenCasts() == DRE; +} + +class VarUseNode; + +// Store the reference to a variable or the call location of a function. +// 'Ref' is a DeclRefExpr or a CallExpr. +// 'Node' contains information about corresponding VarDecl or FunctionDecl. +struct VarUseRecord { + const Expr *Ref; + VarUseNode *Node; + + VarUseRecord() = default; + VarUseRecord(const Expr *Ref, VarUseNode *N) : Ref(Ref), Node(N) {} + operator VarUseNode *() const { return Node; } +}; + +// One node in the variable usage graph. +// If 'D' is a VarDecl: +// 'Uses' contains all static variables and global function calls in the +// initializer expression. +// If 'D' is a FunctionDecl: +// 'Uses' contains all static variable references and global function calls in +// the function body. +class VarUseNode { + const NamedDecl *D; + llvm::SmallVector<VarUseRecord, 2> Uses; + +public: + VarUseNode(const NamedDecl *D) : D(D) {} + + const NamedDecl *getDecl() const { return D; } + bool isVar() const { return isa<VarDecl>(D); } + bool isFunction() const { return isa<FunctionDecl>(D); } + const VarDecl *getVar() const { return cast<VarDecl>(D); } + const FunctionDecl *getFunction() const { return cast<FunctionDecl>(D); } + + using const_iterator = llvm::SmallVectorImpl<VarUseRecord>::const_iterator; + + const_iterator begin() const { return Uses.begin(); } + const_iterator end() const { return Uses.end(); } + + llvm::iterator_range<const_iterator> uses() const { + return llvm::make_range(begin(), end()); + } + + bool empty() const { return Uses.empty(); } + unsigned size() const { return Uses.size(); } + + friend class VarUseCollector; + friend class VarUseGraphBuilder; + friend class VarUseGraph; +}; + +inline bool operator==(const VarUseRecord &LHS, const VarUseNode *RHS) { + return LHS.Node == RHS; +} ---------------- NagyDonat wrote:
Why do you introduce an equality operator where the LHS and RHS have different types? (There might be a good reason but at first glance this seems to be just asking for trouble...) As the definition is very short, perhaps you could just inline it where it would be used -- that would be more explicit and less surprising/confusing/sneaky. https://github.com/llvm/llvm-project/pull/175342 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
