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 <set>
15
16using namespace clang;
17
18namespace {
19// Traverses the AST and finds contributors.
20class ContributorFinder : public DynamicRecursiveASTVisitor {
21public:
22 std::set<const NamedDecl *> Contributors;
23
24 bool VisitFunctionDecl(FunctionDecl *D) override {
25 Contributors.insert(D);
26 return true;
27 }
28
29 bool VisitRecordDecl(RecordDecl *D) override {
30 Contributors.insert(D);
31 return true;
32 }
33
34 bool VisitVarDecl(VarDecl *D) override {
35 DeclContext *DC = D->getDeclContext();
36
37 if (DC->isFileContext() || DC->isNamespace())
38 Contributors.insert(D);
39 return true;
40 }
41};
42
43/// An AST visitor that skips the root node's strict-descendants that are
44/// callable Decls and record Decls, because those are separate contributors.
45///
46/// Clients need to implement their own "MatchAction", which is a function that
47/// takes a `DynTypedNode`, decides if the node matches and performs any further
48/// callback actions.
49/// ContributorFactFinder takes a reference to a "MatchAction". It does not own
50/// the "MatchAction", which is usually stateful and may own containers.
51class ContributorFactFinder : public DynamicRecursiveASTVisitor {
52 llvm::function_ref<void(const DynTypedNode &)> MatchActionRef;
53 const NamedDecl *RootDecl = nullptr;
54
55 template <typename NodeTy> void match(const NodeTy &Node) {
56 MatchActionRef(DynTypedNode::create(Node));
57 }
58
59public:
60 ContributorFactFinder(
61 llvm::function_ref<void(const DynTypedNode &)> MatchActionRef)
62 : MatchActionRef(MatchActionRef) {
63 ShouldVisitTemplateInstantiations = true;
64 ShouldVisitImplicitCode = false;
65 }
66
67 // The entry point:
68 void findMatches(const NamedDecl *Contributor) {
69 RootDecl = Contributor;
70 TraverseDecl(const_cast<NamedDecl *>(Contributor));
71 }
72
73 bool TraverseDecl(Decl *Node) override {
74 if (!Node)
75 return true;
76 // To skip callables:
77 if (Node != RootDecl &&
79 return true;
80 match(*Node);
82 }
83
84 bool TraverseStmt(Stmt *Node) override {
85 if (!Node)
86 return true;
87 match(*Node);
89 }
90
91 bool TraverseLambdaExpr(LambdaExpr *L) override {
92 // TODO: lambda captures of pointer variables (by copy or by reference)
93 // are currently not tracked. Each capture initializes an implicit closure
94 // field from the captured variable, which constitutes a pointer assignment
95 // edge that should be recorded here.
96 return true; // Skip lambda as it is a callable.
97 }
98};
99} // namespace
100
102 ASTContext &Ctx, std::vector<const NamedDecl *> &Contributors) {
103 ContributorFinder Finder;
104 Finder.TraverseAST(Ctx);
105 Contributors.insert(Contributors.end(), Finder.Contributors.begin(),
106 Finder.Contributors.end());
107}
108
110 const NamedDecl *Contributor,
111 llvm::function_ref<void(const DynTypedNode &)> MatchActionRef) {
112 ContributorFactFinder{MatchActionRef}.findMatches(Contributor);
113}
114
116 const clang::NamedDecl *D) {
117 return makeErrAtNode(Ctx, D, "failed to create entity name for %s",
118 D->getNameAsString().data());
119}
Defines the clang::ASTContext interface.
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
bool isNamespace() const
Definition DeclBase.h:2211
DeclContext * getDeclContext()
Definition DeclBase.h:456
A dynamically typed AST node container.
virtual bool TraverseDecl(MaybeConst< Decl > *D)
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
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
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.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor