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 ContributorFinder() {
38 ShouldVisitTemplateInstantiations = true;
39 ShouldVisitImplicitCode = false;
40 }
41
42 bool VisitFunctionDecl(FunctionDecl *D) override {
43 Contributors.insert(D);
44 return true;
45 }
46
47 bool VisitRecordDecl(RecordDecl *D) override {
48 Contributors.insert(D);
49 return true;
50 }
51
52 bool VisitVarDecl(VarDecl *D) override {
53 DeclContext *DC = D->getDeclContext();
54
55 // Collects Decl for global variables or static data members:
56 if (DC->isFileContext() || D->isStaticDataMember())
57 Contributors.insert(D);
58 return true;
59 }
60
61 bool VisitLambdaExpr(LambdaExpr *L) override {
62 // TraverseLambdaExpr directly visits the body stmt, skipping the
63 // CXXMethodDecl, which is a contributor that needs to be collected.
64 VisitFunctionDecl(L->getCallOperator());
65 return true;
66 }
67};
68
69/// An AST visitor that skips the root node's strict-descendants that are
70/// callable Decls and record Decls, because those are separate contributors.
71///
72/// Clients need to implement their own "MatchAction", which is a function that
73/// takes a `DynTypedNode`, decides if the node matches and performs any further
74/// callback actions.
75/// ContributorFactFinder takes a reference to a "MatchAction". It does not own
76/// the "MatchAction", which is usually stateful and may own containers.
77class ContributorFactFinder : public DynamicRecursiveASTVisitor {
78 llvm::function_ref<void(const DynTypedNode &)> MatchActionRef;
79 const NamedDecl *RootDecl = nullptr;
80
81 template <typename NodeTy> void match(const NodeTy &Node) {
82 MatchActionRef(DynTypedNode::create(Node));
83 }
84
85public:
86 ContributorFactFinder(
87 llvm::function_ref<void(const DynTypedNode &)> MatchActionRef)
88 : MatchActionRef(MatchActionRef) {
89 ShouldVisitTemplateInstantiations = true;
90 ShouldVisitImplicitCode = false;
91 }
92
93 // The entry point:
94 void findMatches(const NamedDecl *Contributor) {
95 RootDecl = Contributor;
96 TraverseDecl(const_cast<NamedDecl *>(Contributor));
97 }
98
99 bool TraverseDecl(Decl *Node) override {
100 if (!Node)
101 return true;
102 // To skip callables:
103 if (Node != RootDecl &&
105 return true;
106 match(*Node);
108 }
109
110 bool TraverseStmt(Stmt *Node) override {
111 if (!Node)
112 return true;
113 match(*Node);
115 }
116
117 bool TraverseLambdaExpr(LambdaExpr *L) override {
118 // TODO: lambda captures of pointer variables (by copy or by reference)
119 // are currently not tracked. Each capture initializes an implicit closure
120 // field from the captured variable, which constitutes a pointer assignment
121 // edge that should be recorded here.
122 return true; // Skip lambda as it is a callable.
123 }
124};
125} // namespace
126
128 std::vector<const NamedDecl *> &Contributors) {
129 ContributorFinder Finder;
130 Finder.TraverseAST(Ctx);
131 Contributors.insert(Contributors.end(), Finder.Contributors.begin(),
132 Finder.Contributors.end());
133}
134
136 const NamedDecl *Contributor,
137 llvm::function_ref<void(const DynTypedNode &)> MatchActionRef) {
138 ContributorFactFinder{MatchActionRef}.findMatches(Contributor);
139}
140
142 const clang::NamedDecl *D) {
143 return makeErrAtNode(Ctx, D, "failed to create entity name for %s",
144 D->getNameAsString().data());
145}
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:223
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:2026
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
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1304
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