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"
21#include "clang/Lex/Lexer.h"
30#include "llvm/ADT/STLExtras.h"
31#include "llvm/ADT/SmallVector.h"
32#include <cassert>
33#include <map>
34#include <optional>
35#include <string>
36
37using namespace clang;
38using namespace clang::ssaf;
39
40static constexpr llvm::StringLiteral SkippedRuleId =
41 "cpp-bounded-buffers-skipped";
42
43namespace {
44
45/// A declarator whose type can carry pointer levels.
46bool isCandidateType(QualType T) {
47 QualType U = T.getNonReferenceType();
48 return U->isPointerType() || U->isArrayType();
49}
50
51std::string spell(QualType T, const ASTContext &Ctx) {
52 return T.getAsString(Ctx.getPrintingPolicy());
53}
54
55/// Whether \p T is a type with a name that can be used in template arguments.
56bool isNamable(QualType T) {
57 if (!T->isTypedefNameType())
58 if (const auto *RT = T->getAs<RecordType>()) {
59 const RecordDecl *RD = RT->getDecl();
60 return RD->getIdentifier() || RD->getTypedefNameForAnonDecl();
61 }
62 return true;
63}
64
65std::string renderNewType(const ClassifyResult &R, QualType T,
66 const ASTContext &Ctx) {
67 assert(!R.Skip);
68 if (R.NewType == BoundedType::Ptr)
69 return "bounded_ptr<" + R.InnerSpelling + "> ";
70 const auto *CAT = Ctx.getAsConstantArrayType(T);
71 std::string N = std::to_string(CAT->getSize().getZExtValue());
72 return "bounded_array<" + R.InnerSpelling + ", " + N + ">";
73}
74
75/// Whether another declarator in \p D's lexical context shares its type
76/// specifier, i.e. \p D is one declarator of a multi-declarator group.
77bool sharesTypeSpecifier(const DeclaratorDecl *D) {
78 const TypeSourceInfo *TSI = D->getTypeSourceInfo();
79 const DeclContext *DC = D->getLexicalDeclContext();
80 if (!TSI || !DC)
81 return false;
82 SourceLocation Begin = TSI->getTypeLoc().getBeginLoc();
83 for (const Decl *Sibling : DC->decls()) {
84 if (Sibling == D)
85 continue;
86 const auto *Other = dyn_cast<DeclaratorDecl>(Sibling);
87 if (Other && Other->getTypeSourceInfo() &&
88 Other->getTypeSourceInfo()->getTypeLoc().getBeginLoc() == Begin)
89 return true;
90 }
91 return false;
92}
93
94bool hasTrailingReturnType(const FunctionDecl *FD) {
95 const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
96 return FPT && FPT->hasTrailingReturn();
97}
98
99CharSourceRange declTypeRange(const DeclaratorDecl *D) {
100 if (const TypeSourceInfo *TSI = D->getTypeSourceInfo())
101 return CharSourceRange::getTokenRange(TSI->getTypeLoc().getSourceRange());
103}
104
105/// \return the pointee or element types TypeLoc if TL is a (qualified) pointer
106/// or array type.
107TypeLoc getInnerTypeLoc(TypeLoc TL) {
108 TL = TL.getUnqualifiedLoc();
109 if (auto PTL = TL.getAs<PointerTypeLoc>())
110 return PTL.getPointeeLoc();
111 if (auto ATL = TL.getAs<ArrayTypeLoc>())
112 return ATL.getElementLoc();
113 return {};
114}
115
116/// Whether \p T spells a cv-qualifier keyword.
117bool isCVQualifier(const Token &T) {
118 return T.is(tok::raw_identifier) && (T.getRawIdentifier() == "const" ||
119 T.getRawIdentifier() == "volatile");
120}
121
122/// Probe leading qualifiers for a type 'T'. The probe is bounded in the range
123/// [ \p DeclBegin, \p TypeBegin ), where the lower bound is the begin location
124/// of the declaration where 'T' is spelled and the upper bound is the begin of
125/// the spell of 'T'.
126///
127/// The function updates \p TypeBegin if it finds cv-qualifiers preceding the
128/// original \p TypeBegin without any other token intervening in between. \p
129/// TypeBegin is not updated if there is no leading cv-qualifier. Otherwise,
130/// returns the probe failed reason.
131///
132/// \p TypeBegin is always token location.
133std::optional<ReportReason> extendLeadingQualifiers(SourceLocation DeclBegin,
134 SourceLocation &TypeBegin,
135 const ASTContext &Ctx) {
136 const SourceManager &SM = Ctx.getSourceManager();
137 const LangOptions &LangOpts = Ctx.getLangOpts();
138
139 std::optional<SourceLocation> FirstCVBegin;
140 std::optional<Token> Tok = Token();
141
142 if (Lexer::getRawToken(DeclBegin, *Tok, SM, LangOpts,
143 /*IgnoreWhiteSpace=*/true))
145 while (SM.isBeforeInTranslationUnit(Tok->getLocation(), TypeBegin)) {
146 if (isCVQualifier(*Tok)) {
147 if (!FirstCVBegin) {
148 // Found first cv-qualifier, set `FirstCVBegin`.
149 FirstCVBegin = Tok->getLocation();
150 }
151 } else if (FirstCVBegin)
152 // Bail when there is unexpected token between cv-qualifiers and the
153 // original TypeBegin:
155 Tok = Lexer::findNextToken(Tok->getEndLoc(), SM, LangOpts,
156 /*IncludeComments=*/true);
157 if (!Tok)
159 }
160 if (FirstCVBegin)
161 TypeBegin = *FirstCVBegin; // set the real TypeBegin after propagation
162 return std::nullopt;
163}
164
165/// Probe trailing qualifiers for a type 'T'. The probe is bounded in the range
166/// ( \p TypeEnd, \p UpperBound ), where the lower bound is the end location
167/// of 'T' and the upper bound should be a location within the declaration where
168/// 'T' is spelled.
169///
170/// The function updates \p TypeEnd if it finds cv-qualifiers following the
171/// original \p TypeEnd without any other token intervening in between.
172/// \p TypeEnd is not updated if there is no following cv-qualifier. Otherwise,
173/// returns the probe failed reason.
174///
175/// \p TypeBegin is always token location.
176std::optional<ReportReason> extendTrailingQualifiers(SourceLocation &TypeEnd,
177 SourceLocation UpperBound,
178 const ASTContext &Ctx) {
179 const SourceManager &SM = Ctx.getSourceManager();
180 const LangOptions &LangOpts = Ctx.getLangOpts();
181
182 std::optional<SourceLocation> LastCVBegin;
183 bool RunEnded = false;
184
185 std::optional<Token> Tok = Lexer::findNextToken(TypeEnd, SM, LangOpts,
186 /*IncludeComments=*/true);
187 if (!Tok)
189 while (SM.isBeforeInTranslationUnit(Tok->getLocation(), UpperBound)) {
190 if (isCVQualifier(*Tok)) {
191 // Bail if there is anything unexpected between TypeEnd and a
192 // cv-qualifier.
193 if (RunEnded)
195 LastCVBegin = Tok->getLocation();
196 } else
197 RunEnded = true;
198 Tok = Lexer::findNextToken(Tok->getEndLoc(), SM, LangOpts,
199 /*IncludeComments=*/true);
200 if (!Tok)
202 }
203 if (LastCVBegin)
204 TypeEnd = *LastCVBegin; // set the real TypeEnd after propagation
205 return std::nullopt;
206}
207
208using Levels = llvm::SmallSet<unsigned, 4>;
209using DeclLevels = std::map<const Decl *, Levels>;
210using ReturnLevels = std::map<const FunctionDecl *, Levels>;
211
212/// Reverse index from the whole-program reachability result onto entity names,
213/// so a declaration in this TU can look up its reachable pointer levels.
214class ReachabilityMap {
215 const EntityPointerLevelSet &Reachables;
216 std::map<EntityName, EntityId> NameToId;
217
218public:
219 ReachabilityMap(const WPASuite &Suite,
220 const EntityPointerLevelSet &Reachables)
221 : Reachables(Reachables) {
222 Suite.getIdTable().forEach([this](const EntityName &Name, EntityId Id) {
223 NameToId.emplace(Name, Id);
224 });
225 }
226
227 llvm::SmallSet<unsigned, 4> levelsFor(std::optional<EntityName> Name) const {
228 llvm::SmallSet<unsigned, 4> Levels;
229 if (!Name)
230 return Levels;
231 auto NameIt = NameToId.find(*Name);
232 if (NameIt == NameToId.end())
233 return Levels;
234 auto [Begin, End] = Reachables.equal_range(NameIt->second);
235 for (const EntityPointerLevel &EPL : llvm::make_range(Begin, End))
236 Levels.insert(EPL.getPointerLevel());
237 return Levels;
238 }
239};
240
241/// Collects the reachable pointer/array declarators and function returns
242/// declared in this TU.
243class CollectVisitor : public DynamicRecursiveASTVisitor {
244public:
245 CollectVisitor(const ReachabilityMap &Reach,
246 const NestedBuildNamespace &TUNamespace,
247 const NestedBuildNamespace &LUNamespace, DeclLevels &Decls,
248 ReturnLevels &Returns)
249 : Reach(Reach), TUNamespace(TUNamespace), LUNamespace(LUNamespace),
250 Decls(Decls), Returns(Returns) {}
251
252 bool VisitVarDecl(VarDecl *D) override {
253 collect(D, D->getType(),
254 getQualifiedEntityName(D, TUNamespace, LUNamespace));
255 return true;
256 }
257
258 bool VisitFieldDecl(FieldDecl *D) override {
259 collect(D, D->getType(),
260 getQualifiedEntityName(D, TUNamespace, LUNamespace));
261 return true;
262 }
263
264 bool VisitFunctionDecl(FunctionDecl *FD) override {
265 if (!FD->isTemplated() && isCandidateType(FD->getReturnType())) {
266 llvm::SmallSet<unsigned, 4> Levels = Reach.levelsFor(
267 getQualifiedEntityNameForReturn(FD, TUNamespace, LUNamespace));
268 if (!Levels.empty())
269 Returns[FD] = std::move(Levels);
270 }
271 return true;
272 }
273
274private:
275 void collect(const Decl *D, QualType T, std::optional<EntityName> Name) {
276 if (D->isTemplated() || !isCandidateType(T))
277 return;
278 llvm::SmallSet<unsigned, 4> Levels = Reach.levelsFor(Name);
279 if (!Levels.empty())
280 Decls[D] = std::move(Levels);
281 }
282
283 const ReachabilityMap &Reach;
284 NestedBuildNamespace TUNamespace;
285 NestedBuildNamespace LUNamespace;
286 DeclLevels &Decls;
287 ReturnLevels &Returns;
288};
289
290/// Rewrites or reports every collected declarator and function return.
291class RewriteVisitor : public DynamicRecursiveASTVisitor {
292public:
293 RewriteVisitor(ASTContext &Ctx, DeclLevels &Decls, ReturnLevels &Returns,
295 : Ctx(Ctx), Decls(Decls), Returns(Returns), Edits(Edits), Report(Report) {
296 }
297
298 bool VisitVarDecl(VarDecl *D) override {
299 processDecl(D, D->getType());
300 return true;
301 }
302
303 bool VisitFieldDecl(FieldDecl *D) override {
304 processDecl(D, D->getType());
305 return true;
306 }
307
308 bool VisitFunctionDecl(FunctionDecl *FD) override {
309 auto It = Returns.find(FD);
310 if (It == Returns.end())
311 return true;
312 const Levels &ReachableLevels = It->second;
313 if (hasTrailingReturnType(FD))
314 return report(FD, ReportReason::TrailingReturnType);
315
316 SourceLocation NameLoc = FD->getLocation();
317
319 classifyDeclType(FD->getReturnType(), ReachableLevels, Ctx);
320 if (R.Skip)
321 return report(FD, *R.Skip);
322
323 FunctionTypeLoc FunTypeLoc = FD->getFunctionTypeLoc();
324
325 if (!FunTypeLoc)
326 return report(FD, ReportReason::EmissionFailed);
327 return report(FD, emit(FD->getBeginLoc(), NameLoc,
328 FunTypeLoc.getReturnLoc(), FD->getReturnType(), R));
329 }
330
331private:
332 void processDecl(DeclaratorDecl *D, QualType T) {
333 auto It = Decls.find(D);
334 if (It == Decls.end())
335 return;
336 const Levels &ReachableLevels = It->second;
337 if (sharesTypeSpecifier(D))
338 return (void)report(D, ReportReason::DeclarationGroup);
339
340 const TypeSourceInfo *TSI = D->getTypeSourceInfo();
341
342 if (!TSI)
343 return (void)report(D, ReportReason::EmissionFailed);
344
345 SourceLocation NameLoc = D->getLocation();
346 ClassifyResult R = classifyDeclType(T, ReachableLevels, Ctx);
347
348 if (R.Skip)
349 return (void)report(D, *R.Skip);
350 report(D, emit(D->getBeginLoc(), NameLoc, TSI->getTypeLoc(), T, R));
351 }
352
353 /// Compute the precise source range for rewriting. The produced range is
354 /// token range.
355 ///
356 /// For pointer types, the rewrite range is from the leading cv-qualifier of
357 /// the pointee type to the '*' token of the pointer type.
358 ///
359 /// For array types, the rewrite range is from the leading cv-qualifier to the
360 /// trailing cv-qualifier around the element type. It stops short of the
361 /// declarator name, leaving the name and the extent that follows it to be
362 /// handled separately.
363 ///
364 /// \param DeclBegin the begin location of the declaration, the lower bound of
365 /// the source range before narrowing down to the precise one.
366 /// \param NameLoc the location of the name of the declaration, the upper
367 /// bound of the source range before narrowing down to the precise one.
368 /// \param TLoc the TypeLoc of the type of the declaration
369 /// \param BoundedType indicates whether it is a pointer or an array
370 /// \return ReportReason if it cannot narrow down the rewrite range to the
371 /// aforementioned range. std::nullopt and updated \p Result otherwise.
372 std::optional<ReportReason>
373 computeRewriteRange(SourceLocation DeclBegin, SourceLocation NameLoc,
375 const ASTContext &Ctx, SourceRange &RewriteRange) {
376 TypeLoc InnerTypeLoc = getInnerTypeLoc(TLoc);
377
378 if (!InnerTypeLoc)
380
381 SourceLocation RewriteRangeBegin = InnerTypeLoc.getBeginLoc();
383
385 auto PTL = TLoc.getUnqualifiedLoc().getAs<PointerTypeLoc>();
386
387 if (!PTL || TLoc.getEndLoc() != PTL.getStarLoc())
389 if (auto Reason =
390 extendLeadingQualifiers(DeclBegin, RewriteRangeBegin, Ctx))
391 return Reason;
392 Result = {RewriteRangeBegin, PTL.getStarLoc()};
393 } else {
394 SourceLocation RewriteRangeEnd = InnerTypeLoc.getEndLoc();
395
396 if (auto Reason =
397 extendLeadingQualifiers(DeclBegin, RewriteRangeBegin, Ctx))
398 return Reason;
399 if (auto Reason = extendTrailingQualifiers(RewriteRangeEnd, NameLoc, Ctx))
400 return Reason;
401 Result = {RewriteRangeBegin, RewriteRangeEnd};
402 }
403
404 if (Result.getBegin().isMacroID() || Result.getEnd().isMacroID())
406 if (Result.getBegin().isInvalid() || Result.getEnd().isInvalid())
408
409 const SourceManager &SM = Ctx.getSourceManager();
410 if (SM.getFileID(Result.getBegin()) != SM.getFileID(Result.getEnd()))
412 RewriteRange = Result;
413 return std::nullopt;
414 }
415
416 /// Emits the type-token replacement (and, for arrays, deletes the trailing
417 /// extent). Returns false without emitting anything if a valid,
418 /// self-contained edit cannot be formed.
419 std::optional<ReportReason> emit(SourceLocation DeclBegin,
420 SourceLocation NameLoc, TypeLoc TLoc,
421 QualType T, const ClassifyResult &R) {
422 const SourceManager &SM = Ctx.getSourceManager();
423 SourceRange TypeRewriteRange;
424
425 if (auto Reason = computeRewriteRange(DeclBegin, NameLoc, TLoc, R.NewType,
426 Ctx, TypeRewriteRange))
427 return Reason;
428
429 // TypeRewriteRange is bounded by the tokens (begin location) of the two
430 // ends. Now convert it to char range for source edit, which requires the
431 // bounds to be the characters of the two ends.
432 CharSourceRange TypeRewriteCharRange =
433 Lexer::getAsCharRange(TypeRewriteRange, SM, Ctx.getLangOpts());
435
436 Edited.emplace_back(SM, TypeRewriteCharRange, renderNewType(R, T, Ctx),
437 Ctx.getLangOpts());
438
439 if (R.NewType == BoundedType::Array) {
441
442 if (!ATL)
444
445 SourceLocation LBracket = ATL.getLBracketLoc();
446 SourceLocation RBracket = ATL.getRBracketLoc();
447 // A clean array declarator ends at its closing bracket; otherwise the
448 // element spelling wraps the name (e.g. an array of function pointers)
449 // and cannot be rewritten by stripping a trailing extent.
450 if (ATL.getEndLoc() != RBracket)
452 if (LBracket.isInvalid() || RBracket.isInvalid())
454 Edited.emplace_back(SM,
455 CharSourceRange::getTokenRange(LBracket, RBracket),
456 "", Ctx.getLangOpts());
457 }
458
459 if (!llvm::all_of(Edited, std::mem_fn(&tooling::Replacement::isApplicable)))
461 for (tooling::Replacement &Repl : Edited)
462 Edits.addReplacement(std::move(Repl));
463 return std::nullopt;
464 }
465
466 /// Reports \p Reason for \p D, if one is given. Always returns true so that
467 /// visitors can tail-call it.
468 bool report(const DeclaratorDecl *D, std::optional<ReportReason> Reason) {
469 if (Reason) {
471 declTypeRange(D), Ctx.getSourceManager(), Ctx.getLangOpts());
473 messageFor(*Reason));
474 }
475 return true;
476 }
477
478 ASTContext &Ctx;
479 DeclLevels &Decls;
480 ReturnLevels &Returns;
481 SourceEditEmitter &Edits;
483};
484
485} // namespace
486
487namespace clang::ssaf {
488
489llvm::StringRef messageFor(ReportReason Reason) {
490 switch (Reason) {
492 return "the array type does not end in a closing bracket";
494 return "declarator of a multi-declarator group is not yet rewritten";
496 return "no source edit could be formed for this declarator";
498 return "array of unknown bound is not yet rewritten";
500 return "declarator spelled through a macro is not yet rewritten";
502 return "multi-dimensional array is not yet rewritten";
504 return "multi-level pointer indirection is not yet rewritten";
506 return "no TypeLoc for the pointee or array element type";
508 return "pointer declarator does not end at its '*'";
510 return "this declaration was not transformed";
512 return "pointer to array is not yet rewritten";
514 return "reference to pointer is not yet rewritten";
516 return "trailing return type is not yet rewritten";
518 return "unexpected token between a leading cv-qualifier and the type";
520 return "unexpected token between the type and a trailing cv-qualifier";
522 return "the pointee or array element type has no name that can be written "
523 "as a template argument";
524 }
525 llvm_unreachable("unhandled ReportReason");
526}
527
529classifyDeclType(QualType T, const llvm::SmallSet<unsigned, 4> &ReachableLevels,
530 const ASTContext &Ctx) {
532 if (!ReachableLevels.count(1))
533 return R;
534
535 // A deeper indirection level is reachable too; that is a multi-level rewrite,
536 // which is not yet supported.
537 if (llvm::any_of(ReachableLevels, [](unsigned L) { return L > 1; })) {
539 return R;
540 }
541
542 if (T->isReferenceType()) {
543 QualType Pointee = T.getNonReferenceType();
544 if (Pointee->isPointerType() || Pointee->isArrayType())
546 return R;
547 }
548
549 if (const auto *PT = T->getAs<PointerType>()) {
550 QualType Pointee = PT->getPointeeType();
551 if (Pointee->isFunctionType()) {
552 assert(false &&
553 "function pointer entities are not expected to be reachable");
554 return R;
555 }
556 if (Pointee->isPointerType()) {
558 return R;
559 }
560 if (Pointee->isArrayType()) {
562 return R;
563 }
564 if (!isNamable(Pointee)) {
566 return R;
567 }
568 R.NewType = BoundedType::Ptr;
569 R.InnerSpelling = Pointee->isVoidType() ? "char" : spell(Pointee, Ctx);
570 R.Skip = std::nullopt;
571 return R;
572 }
573
574 if (const auto *CAT = Ctx.getAsConstantArrayType(T)) {
575 QualType Element = CAT->getElementType();
576 if (Element->isArrayType()) {
578 return R;
579 }
580 if (!isNamable(Element)) {
582 return R;
583 }
584 R.NewType = BoundedType::Array;
585 R.InnerSpelling = spell(Element, Ctx);
586 R.Skip = std::nullopt;
587 return R;
588 }
589
590 if (T->isArrayType())
592 return R;
593}
594
596 auto Reachable = Suite.get<UnsafeBufferReachableAnalysisResult>();
597 if (!Reachable) {
598 llvm::consumeError(Reachable.takeError());
599 return;
600 }
601
602 ReachabilityMap Reach(Suite, Reachable->Reachables);
603 NestedBuildNamespace TUNamespace =
605 NestedBuildNamespace LUNamespace =
607 DeclLevels Decls;
608 ReturnLevels Returns;
609
610 Decl *TU = Ctx.getTranslationUnitDecl();
611 CollectVisitor(Reach, TUNamespace, LUNamespace, Decls, Returns)
612 .TraverseDecl(TU);
613 RewriteVisitor(Ctx, Decls, Returns, Edits, Report).TraverseDecl(TU);
614}
615
616} // namespace clang::ssaf
617
618namespace clang::ssaf {
619// NOLINTNEXTLINE(misc-use-internal-linkage)
621} // namespace clang::ssaf
622
623static clang::ssaf::TransformationRegistry::Add<CppBoundedBuffers>
624 RegisterCppBoundedBuffers("cpp-bounded-buffers",
625 "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:239
SourceManager & getSourceManager()
Definition ASTContext.h:907
TranslationUnitDecl * getTranslationUnitDecl() const
const ConstantArrayType * getAsConstantArrayType(QualType T) const
const LangOptions & getLangOpts() const
const clang::PrintingPolicy & getPrintingPolicy() const
Definition ASTContext.h:899
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:781
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2072
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:832
TypeSourceInfo * getTypeSourceInfo() const
Definition Decl.h:810
Represents a member of a struct/union/class.
Definition Decl.h:3295
Represents a function declaration or definition.
Definition Decl.h:2059
QualType getReturnType() const
Definition Decl.h:2976
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:5385
bool hasTrailingReturn() const
Whether this function prototype has a trailing return type.
Definition TypeBase.h:5805
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:440
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:1381
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:296
Wrapper for source info for pointers.
Definition TypeLoc.h:1544
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3396
A (possibly-)qualified type.
Definition TypeBase.h:938
Represents a struct/union/class.
Definition Decl.h:4460
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:4089
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:8389
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition TypeLoc.h:267
bool isVoidType() const
Definition TypeBase.h:9027
bool isArrayType() const
Definition TypeBase.h:8754
bool isPointerType() const
Definition TypeBase.h:8655
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:8651
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9254
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
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
Represents a hierarchical sequence of build namespaces.
static NestedBuildNamespace makeCompilationUnit(llvm::StringRef CompilationId)
Creates a NestedBuildNamespace representing a compilation unit.
static NestedBuildNamespace makeLinkUnit(llvm::StringRef LinkUnitId)
Creates a NestedBuildNamespace representing a link unit.
virtual void addReplacement(clang::tooling::Replacement R)=0
SourceEditEmitter & Edits
const SSAFOptions & Opts
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
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 > getQualifiedEntityNameForReturn(const FunctionDecl *FD, const NestedBuildNamespace &TUNamespace, const NestedBuildNamespace &LUNamespace)
Similar to getQualifiedEntityName, but for entities of function return values.
std::optional< EntityName > getQualifiedEntityName(const Decl *D, const NestedBuildNamespace &TUNamespace, const NestedBuildNamespace &LUNamespace)
Returns the EntityName qualified with the build namespaces it would carry after linking into LUNamesp...
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:1775
The outcome of classifying a declared type against the reachable pointer levels of its entity: a boun...