clang 24.0.0git
LifetimeAnnotations.cpp
Go to the documentation of this file.
1//===- LifetimeAnnotations.cpp - -*--------------- C++------------------*-===//
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//===----------------------------------------------------------------------===//
10#include "clang/AST/Attr.h"
11#include "clang/AST/Decl.h"
12#include "clang/AST/DeclCXX.h"
14#include "clang/AST/Expr.h"
15#include "clang/AST/ExprCXX.h"
17#include "clang/AST/Type.h"
18#include "clang/AST/TypeLoc.h"
21#include "llvm/ADT/StringSet.h"
22
23namespace clang::lifetimes {
24
25const FunctionDecl *
27 return FD != nullptr ? FD->getMostRecentDecl() : nullptr;
28}
29
30const CXXMethodDecl *
32 const FunctionDecl *FD = CMD;
33 return cast_if_present<CXXMethodDecl>(
35}
36
39 bool IsAssignment = OO == OO_Equal || isCompoundAssignmentOperator(OO);
40 if (!IsAssignment)
41 return false;
42 QualType RetT = FD->getReturnType();
43 if (!RetT->isLValueReferenceType())
44 return false;
45 ASTContext &Ctx = FD->getASTContext();
46 QualType LHST;
47 auto *MD = dyn_cast<CXXMethodDecl>(FD);
48 if (MD && MD->isCXXInstanceMember())
49 LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());
50 else
51 LHST = FD->getParamDecl(0)->getType();
52 return Ctx.hasSameType(RetT, LHST);
53}
54
57 return CMD && isNormalAssignmentOperator(CMD) && CMD->param_size() == 1 &&
58 CMD->getParamDecl(0)->hasAttr<clang::LifetimeBoundAttr>();
59}
60
61/// Check if a function has an attribute on its function type
62/// (which represents the implicit 'this' parameter for methods).
63/// Returns the attribute if found, nullptr otherwise.
64template <typename AttrType>
65static const AttrType *getAttrFromFunctionType(const FunctionDecl *FD) {
66 const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
67 if (!TSI)
68 return nullptr;
69 TypeLoc TL = TSI->getTypeLoc();
70 while (true) {
71 auto ATL = TL.getAsAdjusted<AttributedTypeLoc>();
72 if (!ATL)
73 break;
74 if (auto *Attr = ATL.getAttrAs<AttrType>())
75 return Attr;
76 TL = ATL.getModifiedLoc();
77 }
78 return nullptr;
79}
80
81template <typename AttrType>
82static const AttrType *getImplicitObjectParamAttr(const FunctionDecl *FD) {
83 // getDeclWithMergedLifetimeBoundAttrs just returns the most recent decl,
84 // so it is perfectly safe to reuse for capture_by as well.
86 // Attribute merging doesn't work well with attributes on function types (like
87 // 'this' param). We need to check all redeclarations.
88 auto CheckRedecls = [](const FunctionDecl *F) -> const AttrType * {
89 for (const FunctionDecl *Redecl : F->redecls())
90 if (const auto *Attr = getAttrFromFunctionType<AttrType>(Redecl))
91 return Attr;
92 return nullptr;
93 };
94
95 if (const auto *Attr = CheckRedecls(FD))
96 return Attr;
97 if (const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern())
98 return CheckRedecls(Pattern);
99 return nullptr;
100}
101
102const LifetimeBoundAttr *
106
107const LifetimeBoundAttr *
111
117
119 if (PVD.hasAttr<LifetimeBoundAttr>())
120 return true;
122 llvm::any_of(PVD.specific_attrs<LifetimeCaptureByAttr>(),
123 [](const LifetimeCaptureByAttr *A) {
124 return llvm::is_contained(A->params(),
125 LifetimeCaptureByAttr::This);
126 });
127}
128
129const LifetimeCaptureByAttr *
133
135 if (!Call)
136 return;
137
138 std::optional<AnyCall> AC = AnyCall::forExpr(ignoreParensAndImpCasts(Call));
139 if (!AC)
140 return;
141
142 Args = AC->arguments();
143 FD = dyn_cast_or_null<FunctionDecl>(AC->getDecl());
144}
145
146bool hasObjectArg(const FunctionDecl &FD) {
147 const auto *MD = dyn_cast<CXXMethodDecl>(&FD);
148 return MD && MD->isInstance() && !isa<CXXConstructorDecl>(MD);
149}
150
152 return hasObjectArg(FD) &&
153 cast<CXXMethodDecl>(FD).isImplicitObjectMemberFunction();
154}
155
156const ParmVarDecl *getParamForArg(const FunctionDecl &FD, unsigned I) {
157 if (hasImplicitObjectArg(FD)) {
158 if (I == 0)
159 return nullptr;
160 --I;
161 }
162 return I < FD.getNumParams() ? FD.getParamDecl(I) : nullptr;
163}
164
165std::optional<LifetimeBoundParamInfo>
167 unsigned I) {
169 if (!FD || I >= Args.size())
170 return std::nullopt;
171
172 if (I == 0 && hasObjectArg(*FD)) {
173 const auto *Method = cast<CXXMethodDecl>(FD);
174 bool TrackObject =
177 /*RunningUnderLifetimeSafety=*/true);
178 if (hasImplicitObjectArg(*FD))
179 return TrackObject ? std::optional(LifetimeBoundParamInfo(Method))
180 : std::nullopt;
181 // An explicit object parameter is reported as the parameter it is.
182 if (TrackObject)
183 return LifetimeBoundParamInfo(Method->getParamDecl(0));
184 }
185 if (!hasImplicitObjectArg(*FD)) {
186 if (I == 0 && shouldTrackFirstArgument(FD))
187 return LifetimeBoundParamInfo(FD->getParamDecl(I));
188 if (I == 1 && shouldTrackSecondArgument(FD))
189 return LifetimeBoundParamInfo(FD->getParamDecl(I));
190 }
191
192 if (const ParmVarDecl *PVD = getParamForArg(*FD, I);
193 PVD && paramIsLifetimeBound(*PVD))
194 return LifetimeBoundParamInfo(PVD);
195
196 return std::nullopt;
197}
198
199std::optional<LifetimeBoundParamInfo>
200getTrackingInfoForCallArg(const Expr *Call, const Expr *Source) {
201 if (!Call || !Source)
202 return std::nullopt;
203
204 auto [FD, Args] = FunctionCallInfo(Call);
205 if (!FD)
206 return std::nullopt;
207
208 for (unsigned I = 0; I < Args.size(); ++I)
209 if (ignoreParensAndImpCasts(Args[I]) == ignoreParensAndImpCasts(Source))
210 if (std::optional<LifetimeBoundParamInfo> ParamInfo =
211 getTrackedArgInfo(FD, Args, I))
212 return ParamInfo;
213
214 return std::nullopt;
215}
216
217bool isInStlNamespace(const Decl *D) {
218 for (const DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent()) {
219 if (DC->isStdNamespace())
220 return true;
221 if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
222 if (const IdentifierInfo *II = ND->getIdentifier()) {
223 StringRef Name = II->getName();
224 if (Name.size() >= 2 && Name.front() == '_' &&
225 (Name[1] == '_' || isUppercase(Name[1])))
226 return true;
227 }
228 }
229 return false;
230}
231
233 return isGslPointerType(QT) || QT->isPointerType() || QT->isNullPtrType();
234}
235
237 return QT->isReferenceType() || isPointerLikeType(QT);
238}
239
240bool shouldTrackImplicitObjectArg(const Expr &ImplicitObjectArgument,
241 const CXXMethodDecl *Callee,
242 bool RunningUnderLifetimeSafety) {
243 if (!Callee)
244 return false;
245 // Check both the declaring class and the call-site object: a gsl::Owner
246 // may inherit its accessors from a non-Owner base (e.g. libc++ optional).
247 const bool IsGslOwnerImplicitObject =
248 isGslOwnerType(Callee->getFunctionObjectParameterType()) ||
249 (RunningUnderLifetimeSafety &&
250 isGslOwnerType(ImplicitObjectArgument.getBestDynamicClassType()));
251 if (auto *Conv = dyn_cast<CXXConversionDecl>(Callee))
252 if (isGslPointerType(Conv->getConversionType()) && IsGslOwnerImplicitObject)
253 return true;
254 if (!isGslPointerType(Callee->getFunctionObjectParameterType()) &&
255 !IsGslOwnerImplicitObject)
256 return false;
257
258 // Begin and end iterators.
259 static const llvm::StringSet<> IteratorMembers = {
260 "begin", "end", "rbegin", "rend", "cbegin", "cend", "crbegin", "crend"};
261 static const llvm::StringSet<> InnerPointerGetters = {
262 // Inner pointer getters.
263 "c_str", "data", "get"};
264 static const llvm::StringSet<> ContainerFindFns = {
265 // Map and set types.
266 "find", "equal_range", "lower_bound", "upper_bound"};
267 // Track dereference operator and transparent functions like begin(), get(),
268 // etc. for all GSL pointers. Only do so for lifetime safety analysis and not
269 // for Sema's statement-local analysis as it starts to have false-positives.
270 if (RunningUnderLifetimeSafety &&
271 isGslPointerType(Callee->getFunctionObjectParameterType()) &&
272 isReferenceOrPointerLikeType(Callee->getReturnType())) {
273 // Propagate origins through GSL pointer arithmetic and dereference
274 // operators.
275 switch (Callee->getOverloadedOperator()) {
276 case OO_Arrow:
277 case OO_Star:
278 case OO_Plus:
279 case OO_Minus:
280 case OO_PlusPlus:
281 case OO_MinusMinus:
282 return true;
283 default:
284 break;
285 }
286 if (Callee->getIdentifier() &&
287 (IteratorMembers.contains(Callee->getName()) ||
288 InnerPointerGetters.contains(Callee->getName())))
289 return true;
290 }
291
292 if (!isInStlNamespace(Callee->getParent()))
293 return false;
294
295 if (isPointerLikeType(Callee->getReturnType())) {
296 if (!Callee->getIdentifier())
297 // e.g., std::optional<T>::operator->() returns T*.
298 return RunningUnderLifetimeSafety
299 ? IsGslOwnerImplicitObject &&
300 Callee->getOverloadedOperator() ==
301 OverloadedOperatorKind::OO_Arrow
302 : false;
303 return IteratorMembers.contains(Callee->getName()) ||
304 InnerPointerGetters.contains(Callee->getName()) ||
305 ContainerFindFns.contains(Callee->getName());
306 }
307 if (Callee->getReturnType()->isReferenceType()) {
308 if (!Callee->getIdentifier()) {
309 auto OO = Callee->getOverloadedOperator();
310 if (!IsGslOwnerImplicitObject)
311 return false;
312 return OO == OverloadedOperatorKind::OO_Subscript ||
313 OO == OverloadedOperatorKind::OO_Star;
314 }
315 return llvm::StringSwitch<bool>(Callee->getName())
316 .Cases({"front", "back", "at", "top", "value"}, true)
317 .Default(false);
318 }
319 return false;
320}
321
323 if (!FD->getIdentifier() || FD->getNumParams() < 1)
324 return false;
325 if (!FD->isInStdNamespace())
326 return false;
327 // Track std:: algorithm functions that return an iterator whose lifetime is
328 // bound to the first argument.
329 if (FD->getNumParams() >= 2 && FD->isInStdNamespace() &&
331 if (llvm::StringSwitch<bool>(FD->getName())
332 .Cases(
333 {
334 "find",
335 "find_if",
336 "find_if_not",
337 "find_first_of",
338 "adjacent_find",
339 "search",
340 "find_end",
341 "lower_bound",
342 "upper_bound",
343 "partition_point",
344 },
345 true)
346 .Default(false))
347 return true;
348 }
349 const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
350 if (!RD || !RD->isInStdNamespace())
351 return false;
352 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
353 return false;
354
355 if (FD->getNumParams() != 1)
356 return false;
357
358 if (FD->getReturnType()->isPointerType() ||
360 return llvm::StringSwitch<bool>(FD->getName())
361 .Cases({"begin", "rbegin", "cbegin", "crbegin"}, true)
362 .Cases({"end", "rend", "cend", "crend"}, true)
363 .Case("data", true)
364 .Default(false);
365 }
366 if (FD->getReturnType()->isReferenceType()) {
367 return llvm::StringSwitch<bool>(FD->getName())
368 .Cases({"get", "any_cast"}, true)
369 .Default(false);
370 }
371 return false;
372}
373
375 if (FD->getNumParams() < 2)
376 return false;
377 const auto *RD = FD->getParamDecl(1)->getType()->getAsCXXRecordDecl();
378 if (!RD)
379 return false;
380 // For free-standing `+`/`-` operators annotated with `gsl::Pointer`, track
381 // the second parameter when its type matches the return type.
382 return RD->hasAttr<PointerAttr>() &&
383 (FD->getOverloadedOperator() == OO_Plus ||
384 FD->getOverloadedOperator() == OO_Minus) &&
386 FD->getReturnType()) &&
388}
389
390template <typename T> static bool isRecordWithAttr(const CXXRecordDecl *RD) {
391 if (!RD)
392 return false;
393 // Generally, if a primary template class declaration is annotated with an
394 // attribute, all its specializations generated from template instantiations
395 // should inherit the attribute.
396 //
397 // However, since lifetime analysis occurs during parsing, we may encounter
398 // cases where a full definition of the specialization is not required. In
399 // such cases, the specialization declaration remains incomplete and lacks the
400 // attribute. Therefore, we fall back to checking the primary template class.
401 //
402 // Note: it is possible for a specialization declaration to have an attribute
403 // even if the primary template does not.
404 //
405 // FIXME: What if the primary template and explicit specialization
406 // declarations have conflicting attributes? We should consider diagnosing
407 // this scenario.
408 bool Result = RD->hasAttr<T>();
409
410 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
411 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<T>();
412
413 return Result;
414}
415
416template <typename T> static bool isRecordWithAttr(QualType Type) {
418}
419
424}
425
426bool isOwnerPtrCtor(const CXXConstructorDecl *Ctor, const ParmVarDecl *PVD) {
427 return Ctor && PVD->getType()->isPointerType() &&
428 isGslOwnerType(Ctor->getParent());
429}
430
431static StringRef getName(const CXXRecordDecl &RD) {
432 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(&RD))
433 return CTSD->getSpecializedTemplate()->getName();
434 if (RD.getIdentifier())
435 return RD.getName();
436 return "";
437}
438
439static StringRef getName(const FunctionDecl &FD) {
440 if (FD.getIdentifier())
441 return FD.getName();
442 return "";
443}
444
445static bool isStdUniquePtr(const CXXRecordDecl &RD) {
446 return RD.isInStdNamespace() && getName(RD) == "unique_ptr";
447}
448
450 return MD.getIdentifier() && MD.getName() == "release" &&
451 MD.getNumParams() == 0 && isStdUniquePtr(*MD.getParent());
452}
453
455 const CXXRecordDecl *RD = MD.getParent();
456 if (!isInStlNamespace(RD))
457 return false;
458
459 // `pop_back` is excluded: it only invalidates references to the removed
460 // element, not to other elements.
461 static const llvm::StringSet<> Vector = {// Insertion
462 "insert", "emplace", "emplace_back",
463 "push_back", "insert_range",
464 "append_range",
465 // Removal
466 "erase", "clear",
467 // Memory management
468 "reserve", "resize", "shrink_to_fit",
469 // Assignment
470 "assign", "assign_range"};
471
472 // `pop_*` methods are excluded: they only invalidate references to the
473 // removed element, not to other elements.
474 static const llvm::StringSet<> Deque = {// Insertion
475 "insert", "emplace", "insert_range",
476 // Removal
477 "erase", "clear",
478 // Memory management
479 "resize", "shrink_to_fit",
480 // Assignment
481 "assign", "assign_range"};
482
483 static const llvm::StringSet<> String = {
484 // Insertion
485 "insert", "push_back", "append", "replace", "replace_with_range",
486 "insert_range", "append_range",
487 // Removal
488 "pop_back", "erase", "clear",
489 // Memory management
490 "reserve", "resize", "resize_and_overwrite", "shrink_to_fit",
491 // Assignment
492 "swap", "assign", "assign_range"};
493
494 // FIXME: Add queue and stack and check for underlying container
495 // (e.g. no invalidation for std::list).
496 static const llvm::StringSet<> PriorityQueue = {// Insertion
497 "push", "emplace",
498 "push_range",
499 // Removal
500 "pop"};
501
502 // `erase` and `extract` are excluded: they only affect the removed element,
503 // not to other elements.
504 static const llvm::StringSet<> NodeBased = {// Removal
505 "clear"};
506
507 // For `flat_*` container adaptors, `try_emplace` and `insert_or_assign`
508 // only exist on `flat_map`. Listing them here is harmless since the methods
509 // won't be found on other types.
510 static const llvm::StringSet<> Flat = {// Insertion
511 "insert", "emplace", "emplace_hint",
512 "try_emplace", "insert_or_assign",
513 "insert_range", "merge",
514 // Removal
515 "extract", "erase", "clear",
516 // Assignment
517 "replace"};
518
519 static const llvm::StringSet<> UniquePtr = {// Reallocation
520 "reset"};
521
522 const StringRef RecordName = getName(*RD);
523 // TODO: Consider caching this lookup by CXXMethodDecl pointer if this
524 // StringSwitch becomes a performance bottleneck.
525 const llvm::StringSet<> *InvalidatingMethods =
526 llvm::StringSwitch<const llvm::StringSet<> *>(RecordName)
527 .Case("vector", &Vector)
528 .Case("basic_string", &String)
529 .Case("deque", &Deque)
530 .Case("priority_queue", &PriorityQueue)
531 .Cases({"set", "multiset", "map", "multimap", "unordered_set",
532 "unordered_multiset", "unordered_map", "unordered_multimap"},
533 &NodeBased)
534 .Cases({"flat_map", "flat_set", "flat_multimap", "flat_multiset"},
535 &Flat)
536 .Case("unique_ptr", &UniquePtr)
537 .Default(nullptr);
538
539 if (!InvalidatingMethods)
540 return false;
541
542 // Handle Operators via OverloadedOperatorKind
544 if (OO != OO_None) {
545 switch (OO) {
546 case OO_Equal: // operator= : Always invalidates (Assignment)
547 case OO_PlusEqual: // operator+= : Append (String/Vector)
548 return true;
549 case OO_Subscript: // operator[] : Invalidation only for
550 // `flat_map` (Insert-or-access).
551 // `map` and `unordered_map` are excluded.
552 return RecordName == "flat_map";
553 default:
554 return false;
555 }
556 }
557
558 if (!MD.getIdentifier())
559 return false;
560
561 return InvalidatingMethods->contains(MD.getName());
562}
563
566 return true;
567 return isInStlNamespace(&FD) && getName(FD) == "destroy_at";
568}
569
571 switch (FD.getBuiltinID()) {
572 case Builtin::BImalloc:
573 case Builtin::BI__builtin_malloc:
574 case Builtin::BIcalloc:
575 case Builtin::BI__builtin_calloc:
576 case Builtin::BIrealloc:
577 case Builtin::BI__builtin_realloc:
578 return true;
579 default:
580 break;
581 }
582 return llvm::any_of(FD.specific_attrs<OwnershipAttr>(),
583 [](const OwnershipAttr *Attr) {
584 return Attr->getOwnKind() == OwnershipAttr::Returns;
585 });
586}
587
589 switch (FD.getBuiltinID()) {
590 case Builtin::BIfree:
591 case Builtin::BI__builtin_free:
592 case Builtin::BIrealloc:
593 case Builtin::BI__builtin_realloc:
594 return true;
595 default:
596 break;
597 }
598 return llvm::any_of(FD.specific_attrs<OwnershipAttr>(),
599 [](const OwnershipAttr *Attr) {
600 return Attr->getOwnKind() == OwnershipAttr::Takes;
601 });
602}
603
605 if (!RD || !isInStlNamespace(RD))
606 return false;
607 StringRef Name = getName(*RD);
608 return Name == "function" || Name == "move_only_function";
609}
610
612 if (!FD)
613 return false;
614 switch (FD->getBuiltinID()) {
615 case Builtin::BImove:
616 case Builtin::BImove_if_noexcept:
617 case Builtin::BIforward:
618 case Builtin::BIforward_like:
619 case Builtin::BIas_const:
620 return true;
621 default:
622 return false;
623 }
624}
625
630
631} // namespace clang::lifetimes
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines an enumeration for C++ overloaded operators.
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:245
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
static std::optional< AnyCall > forExpr(const Expr *E)
If E is a generic call (to ObjC method /function/block/etc), return a constructed AnyCall object.
Definition AnyCall.h:114
Attr - This represents one attribute.
Definition Attr.h:47
Type source information for an attributed type.
Definition TypeLoc.h:1008
Represents a C++ constructor within a class.
Definition DeclCXX.h:2645
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2153
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2296
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1467
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2108
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isInStdNamespace() const
Definition DeclBase.cpp:453
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:550
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:568
DeclContext * getDeclContext()
Definition DeclBase.h:457
bool hasAttr() const
Definition DeclBase.h:586
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
TypeSourceInfo * getTypeSourceInfo() const
Definition Decl.h:811
This represents one expression.
Definition Expr.h:114
const CXXRecordDecl * getBestDynamicClassType() const
For an expression of class type or pointer to class type, return the most derived class decl the expr...
Definition Expr.cpp:70
Represents a function declaration or definition.
Definition Decl.h:2082
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2974
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
Definition Decl.cpp:3835
QualType getReturnType() const
Definition Decl.h:3022
FunctionDecl * getTemplateInstantiationPattern(bool ForDefinition=true) const
Retrieve the function declaration from which this function could be instantiated, if it is an instant...
Definition Decl.cpp:4339
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Definition Decl.cpp:4205
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3899
size_t param_size() const
Definition Decl.h:2963
One of these records is kept for each identifier that is lexed.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:297
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:303
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:342
Represents a parameter to a function.
Definition Decl.h:1832
A (possibly-)qualified type.
Definition TypeBase.h:938
Base wrapper for a particular "section" of type source info.
Definition TypeLoc.h:59
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
Definition TypeLoc.h:2766
A container of type source information.
Definition TypeBase.h:8549
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition TypeLoc.h:267
The base class of the type hierarchy.
Definition TypeBase.h:1879
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isPointerType() const
Definition TypeBase.h:8815
bool isReferenceType() const
Definition TypeBase.h:8839
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
Definition Type.cpp:2080
bool isLValueReferenceType() const
Definition TypeBase.h:8843
bool isNullPtrType() const
Definition TypeBase.h:9241
QualType getType() const
Definition Decl.h:725
const Expr * ignoreParensAndImpCasts(const Expr *E)
bool isFreeingFunction(const FunctionDecl &FD)
static const AttrType * getAttrFromFunctionType(const FunctionDecl *FD)
Check if a function has an attribute on its function type (which represents the implicit 'this' param...
const LifetimeBoundAttr * getDirectImplicitObjectLifetimeBoundAttr(const FunctionDecl *FD)
bool isGslPointerType(QualType QT)
bool isStdCallableWrapperType(const CXXRecordDecl *RD)
bool shouldTrackFirstArgument(const FunctionDecl *FD)
static StringRef getName(const CXXRecordDecl &RD)
bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
bool shouldTrackImplicitObjectArg(const Expr &ImplicitObjectArgument, const CXXMethodDecl *Callee, bool RunningUnderLifetimeSafety)
bool isPointerLikeType(QualType QT)
bool paramIsLifetimeBound(const ParmVarDecl &PVD)
bool hasObjectArg(const FunctionDecl &FD)
bool isOwnerPtrCtor(const CXXConstructorDecl *Ctor, const ParmVarDecl *PVD)
bool isNormalAssignmentOperator(const FunctionDecl *FD)
static const AttrType * getImplicitObjectParamAttr(const FunctionDecl *FD)
bool isUniquePtrRelease(const CXXMethodDecl &MD)
static bool isRecordWithAttr(const CXXRecordDecl *RD)
static bool isReferenceOrPointerLikeType(QualType QT)
bool isStdReferenceCast(const FunctionDecl *FD)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
bool hasImplicitObjectArg(const FunctionDecl &FD)
const LifetimeBoundAttr * getImplicitObjectParamLifetimeBoundAttr(const FunctionDecl *FD)
const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
bool isInvalidationMethod(const CXXMethodDecl &MD)
std::optional< LifetimeBoundParamInfo > getTrackingInfoForCallArg(const Expr *Call, const Expr *Source)
bool destructsFirstArg(const FunctionDecl &FD)
bool isGslOwnerType(QualType QT)
std::optional< LifetimeBoundParamInfo > getTrackedArgInfo(const FunctionDecl *FD, llvm::ArrayRef< const Expr * > Args, unsigned I)
bool isInStlNamespace(const Decl *D)
bool isAllocatingFunction(const FunctionDecl &FD)
bool shouldTrackSecondArgument(const FunctionDecl *FD)
const LifetimeCaptureByAttr * getCaptureByAttrFromFunctionType(const FunctionDecl *FD)
static bool isStdUniquePtr(const CXXRecordDecl &RD)
const ParmVarDecl * getParamForArg(const FunctionDecl &FD, unsigned I)
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool isCompoundAssignmentOperator(OverloadedOperatorKind Kind)
Determine if this is a compound assignment operator.
Expr * IgnoreExprNodes(Expr *E, FnTys &&... Fns)
Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, Recursively apply each of the f...
Definition IgnoreExpr.h:24
LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
Definition CharInfo.h:126
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Default
Set to the current date and time.
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
Expr * IgnoreImplicitCastsSingleStep(Expr *E)
Definition IgnoreExpr.h:38
Expr * IgnoreParensSingleStep(Expr *E)
Definition IgnoreExpr.h:157
U cast(CodeGen::Address addr)
Definition Address.h:327
llvm::SmallVector< const Expr *, 4 > Args