clang 24.0.0git
CppBoundedBuffers.cpp
Go to the documentation of this file.
1//===- CppBoundedBuffers.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/DeclBase.h"
13#include "clang/AST/DeclCXX.h"
15#include "clang/AST/Type.h"
16#include "clang/AST/TypeLoc.h"
20#include "clang/Lex/Lexer.h"
29#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/SmallVector.h"
31#include <cassert>
32#include <map>
33#include <optional>
34#include <string>
35
36using namespace clang;
37using namespace clang::ssaf;
38
39static constexpr llvm::StringLiteral SkippedRuleId =
40 "cpp-bounded-buffers-skipped";
41
42namespace {
43
44/// A declarator whose type can carry pointer levels.
45bool isCandidateType(QualType T) {
46 QualType U = T.getNonReferenceType();
47 return U->isPointerType() || U->isArrayType();
48}
49
50std::string spell(QualType T, const ASTContext &Ctx) {
51 return T.getAsString(Ctx.getPrintingPolicy());
52}
53
54/// Whether \p T is a type with a name that can be used in template arguments.
55bool isNamable(QualType T) {
56 if (!T->isTypedefNameType())
57 if (const auto *RT = T->getAs<RecordType>()) {
58 const RecordDecl *RD = RT->getDecl();
59 return RD->getIdentifier() || RD->getTypedefNameForAnonDecl();
60 }
61 return true;
62}
63
64std::string renderNewType(const ClassifyResult &R, QualType T,
65 const ASTContext &Ctx) {
66 assert(!R.Skip);
67 if (R.NewType == BoundedType::Ptr)
68 return "bounded_ptr<" + R.InnerSpelling + "> ";
69 const auto *CAT = Ctx.getAsConstantArrayType(T);
70 std::string N = std::to_string(CAT->getSize().getZExtValue());
71 return "bounded_array<" + R.InnerSpelling + ", " + N + ">";
72}
73
74/// Whether another declarator in \p D's lexical context shares its type
75/// specifier, i.e. \p D is one declarator of a multi-declarator group.
76bool sharesTypeSpecifier(const DeclaratorDecl *D) {
77 const TypeSourceInfo *TSI = D->getTypeSourceInfo();
78 const DeclContext *DC = D->getLexicalDeclContext();
79 if (!TSI || !DC)
80 return false;
81 SourceLocation Begin = TSI->getTypeLoc().getBeginLoc();
82 for (const Decl *Sibling : DC->decls()) {
83 if (Sibling == D)
84 continue;
85 const auto *Other = dyn_cast<DeclaratorDecl>(Sibling);
86 if (Other && Other->getTypeSourceInfo() &&
87 Other->getTypeSourceInfo()->getTypeLoc().getBeginLoc() == Begin)
88 return true;
89 }
90 return false;
91}
92
93bool hasTrailingReturnType(const FunctionDecl *FD) {
94 const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
95 return FPT && FPT->hasTrailingReturn();
96}
97
98CharSourceRange declTypeRange(const DeclaratorDecl *D) {
99 if (const TypeSourceInfo *TSI = D->getTypeSourceInfo())
100 return CharSourceRange::getTokenRange(TSI->getTypeLoc().getSourceRange());
102}
103
104/// \return the pointee or element types TypeLoc if TL is a (qualified) pointer
105/// or array type.
106TypeLoc getInnerTypeLoc(TypeLoc TL) {
107 TL = TL.getUnqualifiedLoc();
108 if (auto PTL = TL.getAs<PointerTypeLoc>())
109 return PTL.getPointeeLoc();
110 if (auto ATL = TL.getAs<ArrayTypeLoc>())
111 return ATL.getElementLoc();
112 return {};
113}
114
115/// Whether \p T spells a cv-qualifier keyword.
116bool isCVQualifier(const Token &T) {
117 return T.is(tok::raw_identifier) && (T.getRawIdentifier() == "const" ||
118 T.getRawIdentifier() == "volatile");
119}
120
121/// Probe leading qualifiers for a type 'T'. The probe is bounded in the range
122/// [ \p DeclBegin, \p TypeBegin ), where the lower bound is the begin location
123/// of the declaration where 'T' is spelled and the upper bound is the begin of
124/// the spell of 'T'.
125///
126/// The function updates \p TypeBegin if it finds cv-qualifiers preceding the
127/// original \p TypeBegin without any other token intervening in between. \p
128/// TypeBegin is not updated if there is no leading cv-qualifier. Otherwise,
129/// returns the probe failed reason.
130///
131/// \p TypeBegin is always token location.
132std::optional<ReportReason> extendLeadingQualifiers(SourceLocation DeclBegin,
133 SourceLocation &TypeBegin,
134 const ASTContext &Ctx) {
135 const SourceManager &SM = Ctx.getSourceManager();
136 const LangOptions &LangOpts = Ctx.getLangOpts();
137
138 std::optional<SourceLocation> FirstCVBegin;
139 std::optional<Token> Tok = Token();
140
141 if (Lexer::getRawToken(DeclBegin, *Tok, SM, LangOpts,
142 /*IgnoreWhiteSpace=*/true))
144 while (SM.isBeforeInTranslationUnit(Tok->getLocation(), TypeBegin)) {
145 if (isCVQualifier(*Tok)) {
146 if (!FirstCVBegin) {
147 // Found first cv-qualifier, set `FirstCVBegin`.
148 FirstCVBegin = Tok->getLocation();
149 }
150 } else if (FirstCVBegin)
151 // Bail when there is unexpected token between cv-qualifiers and the
152 // original TypeBegin:
154 Tok = Lexer::findNextToken(Tok->getEndLoc(), SM, LangOpts,
155 /*IncludeComments=*/true);
156 if (!Tok)
158 }
159 if (FirstCVBegin)
160 TypeBegin = *FirstCVBegin; // set the real TypeBegin after propagation
161 return std::nullopt;
162}
163
164/// Probe trailing qualifiers for a type 'T'. The probe is bounded in the range
165/// ( \p TypeEnd, \p UpperBound ), where the lower bound is the end location
166/// of 'T' and the upper bound should be a location within the declaration where
167/// 'T' is spelled.
168///
169/// The function updates \p TypeEnd if it finds cv-qualifiers following the
170/// original \p TypeEnd without any other token intervening in between.
171/// \p TypeEnd is not updated if there is no following cv-qualifier. Otherwise,
172/// returns the probe failed reason.
173///
174/// \p TypeBegin is always token location.
175std::optional<ReportReason> extendTrailingQualifiers(SourceLocation &TypeEnd,
176 SourceLocation UpperBound,
177 const ASTContext &Ctx) {
178 const SourceManager &SM = Ctx.getSourceManager();
179 const LangOptions &LangOpts = Ctx.getLangOpts();
180
181 std::optional<SourceLocation> LastCVBegin;
182 bool RunEnded = false;
183
184 std::optional<Token> Tok = Lexer::findNextToken(TypeEnd, SM, LangOpts,
185 /*IncludeComments=*/true);
186 if (!Tok)
188 while (SM.isBeforeInTranslationUnit(Tok->getLocation(), UpperBound)) {
189 if (isCVQualifier(*Tok)) {
190 // Bail if there is anything unexpected between TypeEnd and a
191 // cv-qualifier.
192 if (RunEnded)
194 LastCVBegin = Tok->getLocation();
195 } else
196 RunEnded = true;
197 Tok = Lexer::findNextToken(Tok->getEndLoc(), SM, LangOpts,
198 /*IncludeComments=*/true);
199 if (!Tok)
201 }
202 if (LastCVBegin)
203 TypeEnd = *LastCVBegin; // set the real TypeEnd after propagation
204 return std::nullopt;
205}
206
207using Levels = llvm::SmallSet<unsigned, 4>;
208using DeclLevels = std::map<const Decl *, Levels>;
209using ReturnLevels = std::map<const FunctionDecl *, Levels>;
210
211/// Reverse index from the whole-program reachability result onto entity names,
212/// so a declaration in this TU can look up its reachable pointer levels.
213class ReachabilityMap {
214 const std::map<EntityId, EntityPointerLevelSet> &Reachables;
215 std::map<EntityName, EntityId> NameToId;
216
217public:
218 ReachabilityMap(const WPASuite &Suite,
219 const std::map<EntityId, EntityPointerLevelSet> &Reachables)
220 : Reachables(Reachables) {
221 Suite.getIdTable().forEach([this](const EntityName &Name, EntityId Id) {
222 NameToId.emplace(Name, Id);
223 });
224 }
225
226 llvm::SmallSet<unsigned, 4> levelsFor(std::optional<EntityName> Name) const {
227 llvm::SmallSet<unsigned, 4> Levels;
228 if (!Name)
229 return Levels;
230 auto NameIt = NameToId.find(*Name);
231 if (NameIt == NameToId.end())
232 return Levels;
233 auto ReachIt = Reachables.find(NameIt->second);
234 if (ReachIt == Reachables.end())
235 return Levels;
236 for (const EntityPointerLevel &EPL : ReachIt->second)
237 Levels.insert(EPL.getPointerLevel());
238 return Levels;
239 }
240};
241
242/// Collects the reachable pointer/array declarators and function returns
243/// declared in this TU.
244class CollectVisitor : public DynamicRecursiveASTVisitor {
245public:
246 CollectVisitor(const ReachabilityMap &Reach, DeclLevels &Decls,
247 ReturnLevels &Returns)
248 : Reach(Reach), Decls(Decls), Returns(Returns) {}
249
250 bool VisitVarDecl(VarDecl *D) override {
251 collect(D, D->getType(), getEntityName(D));
252 return true;
253 }
254
255 bool VisitFieldDecl(FieldDecl *D) override {
256 collect(D, D->getType(), getEntityName(D));
257 return true;
258 }
259
260 bool VisitFunctionDecl(FunctionDecl *FD) override {
261 if (!FD->isTemplated() && isCandidateType(FD->getReturnType())) {
262 llvm::SmallSet<unsigned, 4> Levels =
263 Reach.levelsFor(getEntityNameForReturn(FD));
264 if (!Levels.empty())
265 Returns[FD] = std::move(Levels);
266 }
267 return true;
268 }
269
270private:
271 void collect(const Decl *D, QualType T, std::optional<EntityName> Name) {
272 if (D->isTemplated() || !isCandidateType(T))
273 return;
274 llvm::SmallSet<unsigned, 4> Levels = Reach.levelsFor(Name);
275 if (!Levels.empty())
276 Decls[D] = std::move(Levels);
277 }
278
279 const ReachabilityMap &Reach;
280 DeclLevels &Decls;
281 ReturnLevels &Returns;
282};
283
284/// Rewrites or reports every collected declarator and function return.
285class RewriteVisitor : public DynamicRecursiveASTVisitor {
286public:
287 RewriteVisitor(ASTContext &Ctx, DeclLevels &Decls, ReturnLevels &Returns,
289 : Ctx(Ctx), Decls(Decls), Returns(Returns), Edits(Edits), Report(Report) {
290 }
291
292 bool VisitVarDecl(VarDecl *D) override {
293 processDecl(D, D->getType());
294 return true;
295 }
296
297 bool VisitFieldDecl(FieldDecl *D) override {
298 processDecl(D, D->getType());
299 return true;
300 }
301
302 bool VisitFunctionDecl(FunctionDecl *FD) override {
303 auto It = Returns.find(FD);
304 if (It == Returns.end())
305 return true;
306 const Levels &ReachableLevels = It->second;
307 if (hasTrailingReturnType(FD))
308 return report(FD, ReportReason::TrailingReturnType);
309
310 SourceLocation NameLoc = FD->getLocation();
311
313 classifyDeclType(FD->getReturnType(), ReachableLevels, Ctx);
314 if (R.Skip)
315 return report(FD, *R.Skip);
316
317 FunctionTypeLoc FunTypeLoc = FD->getFunctionTypeLoc();
318
319 if (!FunTypeLoc)
320 return report(FD, ReportReason::EmissionFailed);
321 return report(FD, emit(FD->getBeginLoc(), NameLoc,
322 FunTypeLoc.getReturnLoc(), FD->getReturnType(), R));
323 }
324
325private:
326 void processDecl(DeclaratorDecl *D, QualType T) {
327 auto It = Decls.find(D);
328 if (It == Decls.end())
329 return;
330 const Levels &ReachableLevels = It->second;
331 if (sharesTypeSpecifier(D))
332 return (void)report(D, ReportReason::DeclarationGroup);
333
334 const TypeSourceInfo *TSI = D->getTypeSourceInfo();
335
336 if (!TSI)
337 return (void)report(D, ReportReason::EmissionFailed);
338
339 SourceLocation NameLoc = D->getLocation();
340 ClassifyResult R = classifyDeclType(T, ReachableLevels, Ctx);
341
342 if (R.Skip)
343 return (void)report(D, *R.Skip);
344 report(D, emit(D->getBeginLoc(), NameLoc, TSI->getTypeLoc(), T, R));
345 }
346
347 /// Compute the precise source range for rewriting. The produced range is
348 /// token range.
349 ///
350 /// For pointer types, the rewrite range is from the leading cv-qualifier of
351 /// the pointee type to the '*' token of the pointer type.
352 ///
353 /// For array types, the rewrite range is from the leading cv-qualifier to the
354 /// trailing cv-qualifier around the element type. It stops short of the
355 /// declarator name, leaving the name and the extent that follows it to be
356 /// handled separately.
357 ///
358 /// \param DeclBegin the begin location of the declaration, the lower bound of
359 /// the source range before narrowing down to the precise one.
360 /// \param NameLoc the location of the name of the declaration, the upper
361 /// bound of the source range before narrowing down to the precise one.
362 /// \param TLoc the TypeLoc of the type of the declaration
363 /// \param BoundedType indicates whether it is a pointer or an array
364 /// \return ReportReason if it cannot narrow down the rewrite range to the
365 /// aforementioned range. std::nullopt and updated \p Result otherwise.
366 std::optional<ReportReason>
367 computeRewriteRange(SourceLocation DeclBegin, SourceLocation NameLoc,
369 const ASTContext &Ctx, SourceRange &RewriteRange) {
370 TypeLoc InnerTypeLoc = getInnerTypeLoc(TLoc);
371
372 if (!InnerTypeLoc)
374
375 SourceLocation RewriteRangeBegin = InnerTypeLoc.getBeginLoc();
377
379 auto PTL = TLoc.getUnqualifiedLoc().getAs<PointerTypeLoc>();
380
381 if (!PTL || TLoc.getEndLoc() != PTL.getStarLoc())
383 if (auto Reason =
384 extendLeadingQualifiers(DeclBegin, RewriteRangeBegin, Ctx))
385 return Reason;
386 Result = {RewriteRangeBegin, PTL.getStarLoc()};
387 } else {
388 SourceLocation RewriteRangeEnd = InnerTypeLoc.getEndLoc();
389
390 if (auto Reason =
391 extendLeadingQualifiers(DeclBegin, RewriteRangeBegin, Ctx))
392 return Reason;
393 if (auto Reason = extendTrailingQualifiers(RewriteRangeEnd, NameLoc, Ctx))
394 return Reason;
395 Result = {RewriteRangeBegin, RewriteRangeEnd};
396 }
397
398 if (Result.getBegin().isMacroID() || Result.getEnd().isMacroID())
400 if (Result.getBegin().isInvalid() || Result.getEnd().isInvalid())
402
403 const SourceManager &SM = Ctx.getSourceManager();
404 if (SM.getFileID(Result.getBegin()) != SM.getFileID(Result.getEnd()))
406 RewriteRange = Result;
407 return std::nullopt;
408 }
409
410 /// Emits the type-token replacement (and, for arrays, deletes the trailing
411 /// extent). Returns false without emitting anything if a valid,
412 /// self-contained edit cannot be formed.
413 std::optional<ReportReason> emit(SourceLocation DeclBegin,
414 SourceLocation NameLoc, TypeLoc TLoc,
415 QualType T, const ClassifyResult &R) {
416 const SourceManager &SM = Ctx.getSourceManager();
417 SourceRange TypeRewriteRange;
418
419 if (auto Reason = computeRewriteRange(DeclBegin, NameLoc, TLoc, R.NewType,
420 Ctx, TypeRewriteRange))
421 return Reason;
422
423 // TypeRewriteRange is bounded by the tokens (begin location) of the two
424 // ends. Now convert it to char range for source edit, which requires the
425 // bounds to be the characters of the two ends.
426 CharSourceRange TypeRewriteCharRange =
427 Lexer::getAsCharRange(TypeRewriteRange, SM, Ctx.getLangOpts());
429
430 Edited.emplace_back(SM, TypeRewriteCharRange, renderNewType(R, T, Ctx),
431 Ctx.getLangOpts());
432
433 if (R.NewType == BoundedType::Array) {
435
436 if (!ATL)
438
439 SourceLocation LBracket = ATL.getLBracketLoc();
440 SourceLocation RBracket = ATL.getRBracketLoc();
441 // A clean array declarator ends at its closing bracket; otherwise the
442 // element spelling wraps the name (e.g. an array of function pointers)
443 // and cannot be rewritten by stripping a trailing extent.
444 if (ATL.getEndLoc() != RBracket)
446 if (LBracket.isInvalid() || RBracket.isInvalid())
448 Edited.emplace_back(SM,
449 CharSourceRange::getTokenRange(LBracket, RBracket),
450 "", Ctx.getLangOpts());
451 }
452
453 if (!llvm::all_of(Edited, std::mem_fn(&tooling::Replacement::isApplicable)))
455 for (tooling::Replacement &Repl : Edited)
456 Edits.addReplacement(std::move(Repl));
457 return std::nullopt;
458 }
459
460 /// Reports \p Reason for \p D, if one is given. Always returns true so that
461 /// visitors can tail-call it.
462 bool report(const DeclaratorDecl *D, std::optional<ReportReason> Reason) {
463 if (Reason)
464 Report.addResult(SkippedRuleId, SarifResultLevel::Note, declTypeRange(D),
465 messageFor(*Reason));
466 return true;
467 }
468
469 ASTContext &Ctx;
470 DeclLevels &Decls;
471 ReturnLevels &Returns;
472 SourceEditEmitter &Edits;
474};
475
476} // namespace
477
478namespace clang::ssaf {
479
480llvm::StringRef messageFor(ReportReason Reason) {
481 switch (Reason) {
483 return "the array type does not end in a closing bracket";
485 return "declarator of a multi-declarator group is not yet rewritten";
487 return "no source edit could be formed for this declarator";
489 return "array of unknown bound is not yet rewritten";
491 return "declarator spelled through a macro is not yet rewritten";
493 return "multi-dimensional array is not yet rewritten";
495 return "multi-level pointer indirection is not yet rewritten";
497 return "no TypeLoc for the pointee or array element type";
499 return "pointer declarator does not end at its '*'";
501 return "this declaration was not transformed";
503 return "pointer to array is not yet rewritten";
505 return "reference to pointer is not yet rewritten";
507 return "trailing return type is not yet rewritten";
509 return "unexpected token between a leading cv-qualifier and the type";
511 return "unexpected token between the type and a trailing cv-qualifier";
513 return "the pointee or array element type has no name that can be written "
514 "as a template argument";
515 }
516 llvm_unreachable("unhandled ReportReason");
517}
518
520classifyDeclType(QualType T, const llvm::SmallSet<unsigned, 4> &ReachableLevels,
521 const ASTContext &Ctx) {
523 if (!ReachableLevels.count(1))
524 return R;
525
526 // A deeper indirection level is reachable too; that is a multi-level rewrite,
527 // which is not yet supported.
528 if (llvm::any_of(ReachableLevels, [](unsigned L) { return L > 1; })) {
530 return R;
531 }
532
533 if (T->isReferenceType()) {
534 QualType Pointee = T.getNonReferenceType();
535 if (Pointee->isPointerType() || Pointee->isArrayType())
537 return R;
538 }
539
540 if (const auto *PT = T->getAs<PointerType>()) {
541 QualType Pointee = PT->getPointeeType();
542 if (Pointee->isFunctionType()) {
543 assert(false &&
544 "function pointer entities are not expected to be reachable");
545 return R;
546 }
547 if (Pointee->isPointerType()) {
549 return R;
550 }
551 if (Pointee->isArrayType()) {
553 return R;
554 }
555 if (!isNamable(Pointee)) {
557 return R;
558 }
559 R.NewType = BoundedType::Ptr;
560 R.InnerSpelling = Pointee->isVoidType() ? "char" : spell(Pointee, Ctx);
561 R.Skip = std::nullopt;
562 return R;
563 }
564
565 if (const auto *CAT = Ctx.getAsConstantArrayType(T)) {
566 QualType Element = CAT->getElementType();
567 if (Element->isArrayType()) {
569 return R;
570 }
571 if (!isNamable(Element)) {
573 return R;
574 }
575 R.NewType = BoundedType::Array;
576 R.InnerSpelling = spell(Element, Ctx);
577 R.Skip = std::nullopt;
578 return R;
579 }
580
581 if (T->isArrayType())
583 return R;
584}
585
587 auto Reachable = Suite.get<UnsafeBufferReachableAnalysisResult>();
588 if (!Reachable) {
589 llvm::consumeError(Reachable.takeError());
590 return;
591 }
592
593 ReachabilityMap Reach(Suite, Reachable->Reachables);
594 DeclLevels Decls;
595 ReturnLevels Returns;
596
597 Decl *TU = Ctx.getTranslationUnitDecl();
598 CollectVisitor(Reach, Decls, Returns).TraverseDecl(TU);
599 RewriteVisitor(Ctx, Decls, Returns, Edits, Report).TraverseDecl(TU);
600}
601
602} // namespace clang::ssaf
603
604namespace clang::ssaf {
605// NOLINTNEXTLINE(misc-use-internal-linkage)
607} // namespace clang::ssaf
608
609static clang::ssaf::TransformationRegistry::Add<CppBoundedBuffers>
610 RegisterCppBoundedBuffers("cpp-bounded-buffers",
611 "Rewrites buffers into bounded types");
Defines the clang::ASTContext interface.
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static clang::ssaf::TransformationRegistry::Add< CppBoundedBuffers > RegisterCppBoundedBuffers("cpp-bounded-buffers", "Rewrites buffers into bounded types")
static constexpr llvm::StringLiteral SkippedRuleId
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Token Tok
The Token.
Result
Implement __builtin_bit_cast and related operations.
Defines the clang::LangOptions interface.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
SourceManager & getSourceManager()
Definition ASTContext.h:885
TranslationUnitDecl * getTranslationUnitDecl() const
const ConstantArrayType * getAsConstantArrayType(QualType T) const
const LangOptions & getLangOpts() const
Definition ASTContext.h:981
const clang::PrintingPolicy & getPrintingPolicy() const
Definition ASTContext.h:877
Wrapper for source info for arrays.
Definition TypeLoc.h:1808
SourceLocation getLBracketLoc() const
Definition TypeLoc.h:1810
SourceLocation getRBracketLoc() const
Definition TypeLoc.h:1818
Represents a byte-granular source range.
static CharSourceRange getTokenRange(SourceRange R)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2403
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isTemplated() const
Determine whether this declaration is a templated entity (whether it is.
Definition DeclBase.cpp:308
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:935
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:780
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2072
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
TypeSourceInfo * getTypeSourceInfo() const
Definition Decl.h:809
Represents a member of a struct/union/class.
Definition Decl.h:3294
Represents a function declaration or definition.
Definition Decl.h:2058
QualType getReturnType() const
Definition Decl.h:2975
FunctionTypeLoc getFunctionTypeLoc() const
Find the source location information for how the type of this function was written.
Definition Decl.cpp:4045
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5421
bool hasTrailingReturn() const
Whether this function prototype has a trailing return type.
Definition TypeBase.h:5841
Wrapper for source info for functions.
Definition TypeLoc.h:1675
TypeLoc getReturnLoc() const
Definition TypeLoc.h:1756
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static CharSourceRange getAsCharRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Given a token range, produce a corresponding CharSourceRange that is not a token range.
Definition Lexer.h:438
static std::optional< Token > findNextToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeComments=false)
Finds the token that comes right after the given location.
Definition Lexer.cpp:1376
static bool getRawToken(SourceLocation Loc, Token &Result, const SourceManager &SM, const LangOptions &LangOpts, bool IgnoreWhiteSpace=false)
Relex the token at the specified location.
Definition Lexer.cpp:543
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
Wrapper for source info for pointers.
Definition TypeLoc.h:1544
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3408
A (possibly-)qualified type.
Definition TypeBase.h:938
Represents a struct/union/class.
Definition Decl.h:4459
Encodes a location in the source.
This class handles loading and caching of source files into memory.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
A trivial tuple used to represent a source range.
TypedefNameDecl * getTypedefNameForAnonDecl() const
Definition Decl.h:4088
Token - This structure provides full information about a lexed token.
Definition Token.h:36
Base wrapper for a particular "section" of type source info.
Definition TypeLoc.h:59
UnqualTypeLoc getUnqualifiedLoc() const
Skips past any qualifiers, if this is qualified.
Definition TypeLoc.h:349
T getAs() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
Definition TypeLoc.h:89
SourceLocation getEndLoc() const
Get the end source location.
Definition TypeLoc.cpp:227
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
A container of type source information.
Definition TypeBase.h:8473
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition TypeLoc.h:267
bool isVoidType() const
Definition TypeBase.h:9111
bool isArrayType() const
Definition TypeBase.h:8838
bool isPointerType() const
Definition TypeBase.h:8739
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isFunctionType() const
Definition TypeBase.h:8735
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9338
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
void HandleTranslationUnit(clang::ASTContext &Ctx) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
void forEach(llvm::function_ref< void(const EntityName &, EntityId)> Callback) const
Invokes the callback for each entity in the table.
Lightweight opaque handle representing an entity in an EntityIdTable.
Definition EntityId.h:31
Uniquely identifies an entity in a program.
Definition EntityName.h:28
virtual void addReplacement(clang::tooling::Replacement R)=0
SourceEditEmitter & Edits
TransformationReportEmitter & Report
Bundles the EntityIdTable (moved from the LUSummary) and the analysis results produced by one Analysi...
Definition WPASuite.h:37
const EntityIdTable & getIdTable() const
Returns the EntityIdTable that maps EntityId values to their symbolic names.
Definition WPASuite.h:50
A text replacement.
Definition Replacement.h:83
bool isApplicable() const
Returns whether this replacement can be applied to a file.
BoundedType
The bounded type a raw declarator is rewritten to.
volatile int CppBoundedBuffersAnchorSource
std::optional< EntityName > getEntityNameForReturn(const FunctionDecl *FD)
Maps return entity of a function to an EntityName.
ClassifyResult classifyDeclType(QualType T, const llvm::SmallSet< unsigned, 4 > &ReachableLevels, const ASTContext &Ctx)
Classifies the declared type T of a reachable entity.
std::optional< EntityName > getEntityName(const Decl *D)
Maps a declaration to an EntityName.
llvm::StringRef messageFor(ReportReason Reason)
Returns the report message for Reason.
ReportReason
Why a reachable declarator was reported instead of rewritten.
Top level wrappers for InstallAPI frontend operations.
const FunctionProtoType * T
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
@ Other
Other implicit parameter.
Definition Decl.h:1774
The outcome of classifying a declared type against the reachable pointer levels of its entity: a boun...