clang 23.0.0git
SSAFAnalysesCommon.cpp
Go to the documentation of this file.
1//===- SSAFAnalysesCommon.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "clang/AST/Decl.h"
12#include "clang/AST/DeclObjC.h"
14#include "clang/AST/ExprCXX.h"
15#include <set>
16
17using namespace clang;
18
19std::string ssaf::describeJSONValue(const llvm::json::Value &V) {
20 return llvm::formatv("{0:2}", V).str();
21}
22
23std::string ssaf::describeJSONValue(const llvm::json::Array &A) {
24 return llvm::formatv("array of size {0}", A.size()).str();
25}
26
27std::string ssaf::describeJSONValue(const llvm::json::Object &O) {
28 return llvm::formatv("an object of {0} key(s)", O.size()).str();
29}
30
31namespace {
32// Traverses the AST and finds contributors.
33class ContributorFinder : public DynamicRecursiveASTVisitor {
34public:
35 std::set<const NamedDecl *> Contributors;
36
37 bool VisitFunctionDecl(FunctionDecl *D) override {
38 Contributors.insert(D);
39 return true;
40 }
41
42 bool VisitRecordDecl(RecordDecl *D) override {
43 Contributors.insert(D);
44 return true;
45 }
46
47 bool VisitVarDecl(VarDecl *D) override {
48 DeclContext *DC = D->getDeclContext();
49
50 // Collects Decl for global variables or static data members:
51 if (DC->isFileContext() || D->isStaticDataMember())
52 Contributors.insert(D);
53 return true;
54 }
55
56 bool VisitLambdaExpr(LambdaExpr *L) override {
57 // TraverseLambdaExpr directly visits the body stmt, skipping the
58 // CXXMethodDecl, which is a contributor that needs to be collected.
59 VisitFunctionDecl(L->getCallOperator());
60 return true;
61 }
62};
63
64/// An AST visitor that skips the root node's strict-descendants that are
65/// callable Decls and record Decls, because those are separate contributors.
66///
67/// Clients need to implement their own "MatchAction", which is a function that
68/// takes a `DynTypedNode`, decides if the node matches and performs any further
69/// callback actions.
70/// ContributorFactFinder takes a reference to a "MatchAction". It does not own
71/// the "MatchAction", which is usually stateful and may own containers.
72class ContributorFactFinder : public DynamicRecursiveASTVisitor {
73 llvm::function_ref<void(const DynTypedNode &)> MatchActionRef;
74 const NamedDecl *RootDecl = nullptr;
75
76 template <typename NodeTy> void match(const NodeTy &Node) {
77 MatchActionRef(DynTypedNode::create(Node));
78 }
79
80public:
81 ContributorFactFinder(
82 llvm::function_ref<void(const DynTypedNode &)> MatchActionRef)
83 : MatchActionRef(MatchActionRef) {
84 ShouldVisitTemplateInstantiations = true;
85 ShouldVisitImplicitCode = false;
86 }
87
88 // The entry point:
89 void findMatches(const NamedDecl *Contributor) {
90 RootDecl = Contributor;
91 TraverseDecl(const_cast<NamedDecl *>(Contributor));
92 }
93
94 bool TraverseDecl(Decl *Node) override {
95 if (!Node)
96 return true;
97 // To skip callables:
98 if (Node != RootDecl &&
100 return true;
101 match(*Node);
103 }
104
105 bool TraverseStmt(Stmt *Node) override {
106 if (!Node)
107 return true;
108 match(*Node);
110 }
111
112 bool TraverseLambdaExpr(LambdaExpr *L) override {
113 // TODO: lambda captures of pointer variables (by copy or by reference)
114 // are currently not tracked. Each capture initializes an implicit closure
115 // field from the captured variable, which constitutes a pointer assignment
116 // edge that should be recorded here.
117 return true; // Skip lambda as it is a callable.
118 }
119};
120} // namespace
121
123 std::vector<const NamedDecl *> &Contributors) {
124 ContributorFinder Finder;
125 Finder.TraverseAST(Ctx);
126 Contributors.insert(Contributors.end(), Finder.Contributors.begin(),
127 Finder.Contributors.end());
128}
129
131 const NamedDecl *Contributor,
132 llvm::function_ref<void(const DynTypedNode &)> MatchActionRef) {
133 ContributorFactFinder{MatchActionRef}.findMatches(Contributor);
134}
135
137 const clang::NamedDecl *D) {
138 return makeErrAtNode(Ctx, D, "failed to create entity name for %s",
139 D->getNameAsString().data());
140}
Defines the clang::ASTContext interface.
#define V(N, I)
Defines the clang::Expr interface and subclasses for C++ expressions.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:227
bool isFileContext() const
Definition DeclBase.h:2193
DeclContext * getDeclContext()
Definition DeclBase.h:456
A dynamically typed AST node container.
virtual bool TraverseDecl(MaybeConst< Decl > *D)
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
Represents a function declaration or definition.
Definition Decl.h:2018
CXXMethodDecl * getCallOperator() const
Retrieve the function call operator associated with this lambda expression.
Definition ExprCXX.cpp:1411
This represents a decl that may have a name.
Definition Decl.h:274
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition Decl.h:317
Represents a struct/union/class.
Definition Decl.h:4343
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1296
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
llvm::Error makeErrAtNode(clang::ASTContext &Ctx, const NodeTy *N, llvm::StringRef Fmt, const Ts &...Args)
void findContributors(ASTContext &Ctx, std::vector< const NamedDecl * > &Contributors)
Find all contributors in an AST.
llvm::Error makeEntityNameErr(clang::ASTContext &Ctx, const clang::NamedDecl *D)
void findMatchesIn(const NamedDecl *Contributor, llvm::function_ref< void(const DynTypedNode &)> MatchActionRef)
Perform "MatchAction" on each Stmt and Decl belonging to the Contributor.
std::string describeJSONValue(const llvm::json::Value &V)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor