================
@@ -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

Reply via email to