================
@@ -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;
+}
+
+// "Variable usage graph":
+// Stores dependencies of variables from other variables or function calls,
+// and dependencies of function results from variables or functions.
+// Only static variables (static member, static local variable, or global
+// variable) and global or static functions are stored.
+// Stored are the canonical declarations of variables and definitions of
+// functions.
+class VarUseGraph {
+ using UseMapTy = llvm::DenseMap<const Decl *, std::unique_ptr<VarUseNode>>;
+
+ UseMapTy UseMap;
+ // Root contains edges to all other nodes, without a "Ref" expression.
+ VarUseNode *Root;
+
+public:
+ VarUseGraph() {
+ UseMap[nullptr] = std::make_unique<VarUseNode>(nullptr);
+ Root = UseMap[nullptr].get();
----------------
NagyDonat wrote:
Why do you store `Root` as a separate data member of `VarUseGraph` instead of
just defining `getRoot()` as e.g.
```c++
VarUseNode *getRoot() const { return UseMap[nullptr].get(); }
```
I think it is better to have one canonical location for the storage of each
piece of data -- unless there is any concrete reason that overrides this?
(Alternatively, storing the `Root` in a separate data member and not placing it
in the `UseMap` would also be a reasonable setup. I don't know which would be
more intuitive/natural here.)
https://github.com/llvm/llvm-project/pull/175342
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits