clang 23.0.0git
OperatorNewDeletePointers.cpp
Go to the documentation of this file.
1//===- OperatorNewDeletePointers.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//
9// Implementation of the OperatorNewDeletePointers analysis, including
10//
11// a) the Extractor implementation for extracting from user-provided operator
12// new/delete overloadings:
13// 1 return entities of operator new overloads;
14// 2 the parameter (optionally the 2nd) of operator new overloads
15// representing the pointer to a memory area to initialize the object at;
16// 3 the first parameter of operator delete overloads representing the
17// pointer to a memory block to deallocate or a null pointer;
18// 4 the parameter (optionally the 2nd) of operator delete overloads
19// representing the pointer used as the placement parameter in the matching
20// placement new.
21//
22// b) the WPA implementation that simply groups extracted summaries into a
23// OperatorNewDeletePointersAnalysisResult that other analysis can use.
24//
25// c) serialization implementations
26//
27//===----------------------------------------------------------------------===//
28
32#include "clang/AST/Decl.h"
33#include "clang/AST/DeclCXX.h"
34#include "clang/AST/Type.h"
43#include "llvm/ADT/StringRef.h"
44#include "llvm/Support/Error.h"
45#include "llvm/Support/JSON.h"
46#include <memory>
47#include <optional>
48#include <utility>
49#include <vector>
50
51using namespace clang;
52using namespace ssaf;
53
54namespace {
55
56class OperatorNewDeletePointersExtractor final : public TUSummaryExtractor {
57public:
59
60private:
61 void HandleTranslationUnit(ASTContext &Ctx) override;
62
63 std::unique_ptr<OperatorNewDeletePointersEntitySummary>
64 extractEntitySummary(const std::vector<const NamedDecl *> &Decls);
65};
66
67void OperatorNewDeletePointersExtractor::HandleTranslationUnit(
68 ASTContext &Ctx) {
70 *this, SummaryBuilder, Ctx,
71 [&](const std::vector<const NamedDecl *> &Decls) {
72 return extractEntitySummary(Decls);
73 },
75}
76
77std::unique_ptr<OperatorNewDeletePointersEntitySummary>
78OperatorNewDeletePointersExtractor::extractEntitySummary(
79 const std::vector<const NamedDecl *> &ContributorDecls) {
80 auto Summary = std::make_unique<OperatorNewDeletePointersEntitySummary>();
81 auto Matcher = [&Summary, this](const DynTypedNode &Node) {
82 const auto *FD = Node.get<FunctionDecl>();
83
84 if (!FD)
85 return;
86
87 OverloadedOperatorKind OO = FD->getOverloadedOperator();
88
89 switch (OO) {
90 case OO_New:
91 case OO_Array_New:
92 // Extract case 1:
93 if (auto Id = addEntityForReturn(FD))
94 Summary->Entities.insert(*Id);
95 break;
96 case OO_Delete:
97 case OO_Array_Delete:
98 // Extract case 3; ignore ill-formed ones (first param not a pointer).
99 if (!FD->getNumParams() || !hasPtrOrArrType(FD->getParamDecl(0)))
100 return;
101 if (auto Id = addEntity(FD->getParamDecl(0)))
102 Summary->Entities.insert(*Id);
103 break;
104 default:
105 return;
106 };
107 // Extract case 2 & 4: only `operator new(size_t, void*)` and
108 // `operator delete(void*, void*)` are standard-defined with a void* 2nd
109 // param; for user-defined 3+ param overloads the 2nd param type is
110 // unconstrained, so we conservatively skip them.
111 if (FD->getNumParams() == 2 && hasPtrOrArrType(FD->getParamDecl(1))) {
112 if (auto Id = addEntity(FD->getParamDecl(1)))
113 Summary->Entities.insert(*Id);
114 }
115 };
116
117 for (const NamedDecl *Decl : ContributorDecls)
118 findMatchesIn(Decl, Matcher);
119 return Summary;
120}
121
122//===----------------------------------------------------------------------===//
123// WPA implementation
124//===----------------------------------------------------------------------===//
125class OperatorNewDeletePointersAnalysis final
126 : public SummaryAnalysis<OperatorNewDeletePointersAnalysisResult,
127 OperatorNewDeletePointersEntitySummary> {
128public:
129 llvm::Error
130 add(EntityId,
131 const OperatorNewDeletePointersEntitySummary &Summary) override {
132 getResult().Entities.insert(Summary.Entities.begin(),
133 Summary.Entities.end());
134 return llvm::Error::success();
135 }
136};
137
138AnalysisRegistry::Add<OperatorNewDeletePointersAnalysis>
139 RegisterOperatorNewDeletePointersAnalysis(
140 "Whole-program set of pointer entities in operator new/delete "
141 "overloads that must retain their 'void*' type");
142
143//===----------------------------------------------------------------------===//
144// serialization implementation
145//===----------------------------------------------------------------------===//
146
147llvm::json::Object serializeImpl(const std::set<EntityId> &Set,
149 llvm::json::Object Result;
150 llvm::json::Array DataArray;
151
152 DataArray.reserve(Set.size());
153 for (const auto &Ent : Set)
154 DataArray.push_back(Fn(Ent));
156 return Result;
157}
158
159llvm::Expected<std::set<EntityId>>
160deserializeImpl(const llvm::json::Object &Data,
162 const auto *DataArray =
164 std::set<EntityId> EntitySet;
165
166 if (!DataArray) {
168 Data, "An object with a key %s",
170 }
171 for (const auto &Elt : *DataArray) {
172 const auto *EltAsObj = Elt.getAsObject();
173
174 if (!EltAsObj)
175 return makeSawButExpectedError(Elt, "an object representing EntityId");
176
177 Expected<EntityId> EntityId = Fn(*EltAsObj);
178
179 if (!EntityId)
180 return EntityId.takeError();
181
182 EntitySet.insert(*EntityId);
183 }
184 return EntitySet;
185}
186
187llvm::json::Object serializeSummary(const EntitySummary &S,
189 const auto &SS =
190 static_cast<const OperatorNewDeletePointersEntitySummary &>(S);
191 return serializeImpl(SS.Entities, Fn);
192}
193
194llvm::Expected<std::unique_ptr<EntitySummary>>
195deserializeSummary(const llvm::json::Object &Data, EntityIdTable &,
197 llvm::Expected<std::set<EntityId>> EntityIDSet = deserializeImpl(Data, Fn);
198
199 if (!EntityIDSet)
200 return EntityIDSet.takeError();
201
202 std::unique_ptr<OperatorNewDeletePointersEntitySummary> Sum =
203 std::make_unique<OperatorNewDeletePointersEntitySummary>();
204
205 Sum->Entities = std::move(*EntityIDSet);
206 return Sum;
207}
208
209struct OperatorNewDeletePointersJSONFormatInfo final : JSONFormat::FormatInfo {
210 OperatorNewDeletePointersJSONFormatInfo()
211 : JSONFormat::FormatInfo(
212 OperatorNewDeletePointersEntitySummary::summaryName(),
213 serializeSummary, deserializeSummary) {}
214};
215
216static llvm::Registry<JSONFormat::FormatInfo>::Add<
217 OperatorNewDeletePointersJSONFormatInfo>
218 RegisterOperatorNewDeletePointersJSONFormatInfo(
220 "JSON Format info for OperatorNewDeletePointersEntitySummary");
221
222llvm::json::Object
223serializeAnalysisResult(const OperatorNewDeletePointersAnalysisResult &R,
225 return serializeImpl(R.Entities, Fn);
226}
227
228llvm::Expected<std::unique_ptr<AnalysisResult>>
229deserializeAnalysisResult(const llvm::json::Object &Data,
231 llvm::Expected<std::set<EntityId>> EntityIDSet = deserializeImpl(Data, Fn);
232
233 if (!EntityIDSet)
234 return EntityIDSet.takeError();
235
236 std::unique_ptr<OperatorNewDeletePointersAnalysisResult> AR =
237 std::make_unique<OperatorNewDeletePointersAnalysisResult>();
238
239 AR->Entities = std::move(*EntityIDSet);
240 return AR;
241}
242
243JSONFormat::AnalysisResultRegistry::Add<OperatorNewDeletePointersAnalysisResult>
244 RegisterNewDeletePointersAnalysisResultForJSON(serializeAnalysisResult,
245 deserializeAnalysisResult);
246
247} // namespace
248
249namespace clang::ssaf {
250// NOLINTNEXTLINE(misc-use-internal-linkage)
252} // namespace clang::ssaf
253
254static TUSummaryExtractorRegistry::Add<OperatorNewDeletePointersExtractor>
257 "Extract pointer entities in operator new/delete overloads that must "
258 "have a 'void*' type");
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Result
Implement __builtin_bit_cast and related operations.
Defines an enumeration for C++ overloaded operators.
static TUSummaryExtractorRegistry::Add< OperatorNewDeletePointersExtractor > RegisterOperatorNewDeletePointersExtractor(OperatorNewDeletePointersEntitySummary::Name, "Extract pointer entities in operator new/delete overloads that must " "have a 'void*' type")
C Language Family Type Representation.
static llvm::Expected< std::unique_ptr< EntitySummary > > deserializeImpl(const Object &Data, JSONFormat::EntityIdFromJSONFn Fn)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
llvm::function_ref< llvm::Expected< EntityId >(const Object &)> EntityIdFromJSONFn
Definition JSONFormat.h:99
FormatInfoEntry< SerializerFn, DeserializerFn > FormatInfo
Definition JSONFormat.h:108
llvm::function_ref< Object(EntityId)> EntityIdToJSONFn
Definition JSONFormat.h:98
TUSummaryExtractor(TUSummaryBuilder &Builder)
DynTypedNode DynTypedNode
void extractAndAddSummaries(TUSummaryExtractor &Extractor, TUSummaryBuilder &Builder, ASTContext &Ctx, ExtractorFnT ExtractFn, llvm::StringRef ExtractorName="")
The standard contributor-summary extraction procedure:
bool hasPtrOrArrType(const Expr *E)
volatile int OperatorNewDeletePointersAnchorSource
void findMatchesIn(const NamedDecl *Contributor, llvm::function_ref< void(const DynTypedNode &)> MatchActionRef)
Perform "MatchAction" on each Stmt and Decl belonging to the Contributor.
llvm::Error makeSawButExpectedError(const JSONTy &Saw, llvm::StringRef Expected, const Ts &...ExpectedArgs)
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.