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"
16#include "clang/AST/Type.h"
17#include "clang/AST/TypeLoc.h"
20#include "llvm/ADT/StringSet.h"
21
22namespace clang::lifetimes {
23
24const FunctionDecl *
26 return FD != nullptr ? FD->getMostRecentDecl() : nullptr;
27}
28
29const CXXMethodDecl *
31 const FunctionDecl *FD = CMD;
32 return cast_if_present<CXXMethodDecl>(
34}
35
38 bool IsAssignment = OO == OO_Equal || isCompoundAssignmentOperator(OO);
39 if (!IsAssignment)
40 return false;
41 QualType RetT = FD->getReturnType();
42 if (!RetT->isLValueReferenceType())
43 return false;
44 ASTContext &Ctx = FD->getASTContext();
45 QualType LHST;
46 auto *MD = dyn_cast<CXXMethodDecl>(FD);
47 if (MD && MD->isCXXInstanceMember())
48 LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());
49 else
50 LHST = FD->getParamDecl(0)->getType();
51 return Ctx.hasSameType(RetT, LHST);
52}
53
56 return CMD && isNormalAssignmentOperator(CMD) && CMD->param_size() == 1 &&
57 CMD->getParamDecl(0)->hasAttr<clang::LifetimeBoundAttr>();
58}
59
60/// Check if a function has a lifetimebound attribute on its function type
61/// (which represents the implicit 'this' parameter for methods).
62/// Returns the attribute if found, nullptr otherwise.
63static const LifetimeBoundAttr *
65 // Walk through the type layers looking for a lifetimebound attribute.
66 TypeLoc TL = TSI.getTypeLoc();
67 while (true) {
68 auto ATL = TL.getAsAdjusted<AttributedTypeLoc>();
69 if (!ATL)
70 break;
71 if (auto *LBAttr = ATL.getAttrAs<LifetimeBoundAttr>())
72 return LBAttr;
73 TL = ATL.getModifiedLoc();
74 }
75 return nullptr;
76}
77
78const LifetimeBoundAttr *
80 if (const TypeSourceInfo *TSI = FD->getTypeSourceInfo())
81 if (const auto *Attr = getLifetimeBoundAttrFromFunctionType(*TSI))
82 return Attr;
83 return nullptr;
84}
85
86const LifetimeBoundAttr *
89 // Attribute merging doesn't work well with attributes on function types (like
90 // 'this' param). We need to check all redeclarations.
91 auto CheckRedecls = [](const FunctionDecl *F) -> const LifetimeBoundAttr * {
92 for (const FunctionDecl *Redecl : F->redecls())
93 if (const auto *Attr = getDirectImplicitObjectLifetimeBoundAttr(Redecl))
94 return Attr;
95 return nullptr;
96 };
97
98 if (const auto *Attr = CheckRedecls(FD))
99 return Attr;
100 if (const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern())
101 return CheckRedecls(Pattern);
102 return nullptr;
103}
104
110
111FunctionCallInfo getFunctionCallInfo(const Expr *Call) {
112 FunctionCallInfo Info;
113 if (!Call)
114 return Info;
115
116 Call = Call->IgnoreParenImpCasts();
117 std::optional<AnyCall> AC = AnyCall::forExpr(Call);
118 if (!AC)
119 return Info;
120
121 Info.FD = dyn_cast_or_null<FunctionDecl>(AC->getDecl());
122 if (!Info.FD)
123 return Info;
124
125 if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(Call))
126 Info.Args.push_back(MCE->getImplicitObjectArgument());
127
128 Info.Args.append(AC->arg_begin(), AC->arg_end());
129
130 if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call))
131 // For `static operator()`, the first argument is the object argument,
132 // remove it from the argument list to avoid off-by-one errors.
133 if (OCE->getOperator() == OO_Call && Info.FD->isStatic())
134 Info.Args.erase(Info.Args.begin());
135
136 return Info;
137}
138
139std::optional<LifetimeBoundParamInfo>
141 unsigned I) {
143 if (!FD || I >= Args.size())
144 return std::nullopt;
145
146 const ParmVarDecl *PVD = nullptr;
147
148 if (const auto *Method = dyn_cast<CXXMethodDecl>(FD);
149 Method && Method->isInstance() && !isa<CXXConstructorDecl>(FD)) {
150 if (I == 0) {
151 // For the 'this' argument, the attribute is on the method itself.
154 /*RunningUnderLifetimeSafety=*/true))
155 return LifetimeBoundParamInfo(Method);
156 return std::nullopt;
157 }
158 if ((I - 1) < Method->getNumParams())
159 // For explicit arguments, find the corresponding parameter declaration.
160 PVD = Method->getParamDecl(I - 1);
161 } else if (I == 0 && shouldTrackFirstArgument(FD)) {
162 return LifetimeBoundParamInfo(FD->getParamDecl(I));
163 } else if (I == 1 && shouldTrackSecondArgument(FD)) {
164 return LifetimeBoundParamInfo(FD->getParamDecl(I));
165 } else if (I < FD->getNumParams()) {
166 // For free functions or static methods.
167 PVD = FD->getParamDecl(I);
168 }
169
170 if (PVD && PVD->hasAttr<clang::LifetimeBoundAttr>())
171 return LifetimeBoundParamInfo(PVD);
172
173 return std::nullopt;
174}
175
176std::optional<LifetimeBoundParamInfo>
177getTrackingInfoForCallArg(const Expr *Call, const Expr *Source) {
178 if (!Call || !Source)
179 return std::nullopt;
180
181 FunctionCallInfo CallInfo = getFunctionCallInfo(Call);
182 if (!CallInfo.FD)
183 return std::nullopt;
184
185 for (unsigned I = 0; I < CallInfo.Args.size(); ++I)
186 if (CallInfo.Args[I]->IgnoreParenImpCasts() ==
187 Source->IgnoreParenImpCasts())
188 if (std::optional<LifetimeBoundParamInfo> ParamInfo =
189 getTrackedArgInfo(CallInfo.FD, CallInfo.Args, I))
190 return ParamInfo;
191
192 return std::nullopt;
193}
194
195bool isInStlNamespace(const Decl *D) {
196 for (const DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent()) {
197 if (DC->isStdNamespace())
198 return true;
199 if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
200 if (const IdentifierInfo *II = ND->getIdentifier()) {
201 StringRef Name = II->getName();
202 if (Name.size() >= 2 && Name.front() == '_' &&
203 (Name[1] == '_' || isUppercase(Name[1])))
204 return true;
205 }
206 }
207 return false;
208}
209
211 return isGslPointerType(QT) || QT->isPointerType() || QT->isNullPtrType();
212}
213
215 return QT->isReferenceType() || isPointerLikeType(QT);
216}
217
218bool shouldTrackImplicitObjectArg(const Expr &ImplicitObjectArgument,
219 const CXXMethodDecl *Callee,
220 bool RunningUnderLifetimeSafety) {
221 if (!Callee)
222 return false;
223 // Check both the declaring class and the call-site object: a gsl::Owner
224 // may inherit its accessors from a non-Owner base (e.g. libc++ optional).
225 const bool IsGslOwnerImplicitObject =
226 isGslOwnerType(Callee->getFunctionObjectParameterType()) ||
227 (RunningUnderLifetimeSafety &&
228 isGslOwnerType(ImplicitObjectArgument.getBestDynamicClassType()));
229 if (auto *Conv = dyn_cast<CXXConversionDecl>(Callee))
230 if (isGslPointerType(Conv->getConversionType()) && IsGslOwnerImplicitObject)
231 return true;
232 if (!isGslPointerType(Callee->getFunctionObjectParameterType()) &&
233 !IsGslOwnerImplicitObject)
234 return false;
235
236 // Begin and end iterators.
237 static const llvm::StringSet<> IteratorMembers = {
238 "begin", "end", "rbegin", "rend", "cbegin", "cend", "crbegin", "crend"};
239 static const llvm::StringSet<> InnerPointerGetters = {
240 // Inner pointer getters.
241 "c_str", "data", "get"};
242 static const llvm::StringSet<> ContainerFindFns = {
243 // Map and set types.
244 "find", "equal_range", "lower_bound", "upper_bound"};
245 // Track dereference operator and transparent functions like begin(), get(),
246 // etc. for all GSL pointers. Only do so for lifetime safety analysis and not
247 // for Sema's statement-local analysis as it starts to have false-positives.
248 if (RunningUnderLifetimeSafety &&
249 isGslPointerType(Callee->getFunctionObjectParameterType()) &&
250 isReferenceOrPointerLikeType(Callee->getReturnType())) {
251 // Propagate origins through GSL pointer arithmetic and dereference
252 // operators.
253 switch (Callee->getOverloadedOperator()) {
254 case OO_Arrow:
255 case OO_Star:
256 case OO_Plus:
257 case OO_Minus:
258 case OO_PlusPlus:
259 case OO_MinusMinus:
260 return true;
261 default:
262 break;
263 }
264 if (Callee->getIdentifier() &&
265 (IteratorMembers.contains(Callee->getName()) ||
266 InnerPointerGetters.contains(Callee->getName())))
267 return true;
268 }
269
270 if (!isInStlNamespace(Callee->getParent()))
271 return false;
272
273 if (isPointerLikeType(Callee->getReturnType())) {
274 if (!Callee->getIdentifier())
275 // e.g., std::optional<T>::operator->() returns T*.
276 return RunningUnderLifetimeSafety
277 ? IsGslOwnerImplicitObject &&
278 Callee->getOverloadedOperator() ==
279 OverloadedOperatorKind::OO_Arrow
280 : false;
281 return IteratorMembers.contains(Callee->getName()) ||
282 InnerPointerGetters.contains(Callee->getName()) ||
283 ContainerFindFns.contains(Callee->getName());
284 }
285 if (Callee->getReturnType()->isReferenceType()) {
286 if (!Callee->getIdentifier()) {
287 auto OO = Callee->getOverloadedOperator();
288 if (!IsGslOwnerImplicitObject)
289 return false;
290 return OO == OverloadedOperatorKind::OO_Subscript ||
291 OO == OverloadedOperatorKind::OO_Star;
292 }
293 return llvm::StringSwitch<bool>(Callee->getName())
294 .Cases({"front", "back", "at", "top", "value"}, true)
295 .Default(false);
296 }
297 return false;
298}
299
301 if (!FD->getIdentifier() || FD->getNumParams() < 1)
302 return false;
303 if (!FD->isInStdNamespace())
304 return false;
305 // Track std:: algorithm functions that return an iterator whose lifetime is
306 // bound to the first argument.
307 if (FD->getNumParams() >= 2 && FD->isInStdNamespace() &&
309 if (llvm::StringSwitch<bool>(FD->getName())
310 .Cases(
311 {
312 "find",
313 "find_if",
314 "find_if_not",
315 "find_first_of",
316 "adjacent_find",
317 "search",
318 "find_end",
319 "lower_bound",
320 "upper_bound",
321 "partition_point",
322 },
323 true)
324 .Default(false))
325 return true;
326 }
327 const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
328 if (!RD || !RD->isInStdNamespace())
329 return false;
330 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
331 return false;
332
333 if (FD->getNumParams() != 1)
334 return false;
335
336 if (FD->getReturnType()->isPointerType() ||
338 return llvm::StringSwitch<bool>(FD->getName())
339 .Cases({"begin", "rbegin", "cbegin", "crbegin"}, true)
340 .Cases({"end", "rend", "cend", "crend"}, true)
341 .Case("data", true)
342 .Default(false);
343 }
344 if (FD->getReturnType()->isReferenceType()) {
345 return llvm::StringSwitch<bool>(FD->getName())
346 .Cases({"get", "any_cast"}, true)
347 .Default(false);
348 }
349 return false;
350}
351
353 if (FD->getNumParams() < 2)
354 return false;
355 const auto *RD = FD->getParamDecl(1)->getType()->getAsCXXRecordDecl();
356 if (!RD)
357 return false;
358 // For free-standing `+`/`-` operators annotated with `gsl::Pointer`, track
359 // the second parameter when its type matches the return type.
360 return RD->hasAttr<PointerAttr>() &&
361 (FD->getOverloadedOperator() == OO_Plus ||
362 FD->getOverloadedOperator() == OO_Minus) &&
364 FD->getReturnType()) &&
366}
367
368template <typename T> static bool isRecordWithAttr(const CXXRecordDecl *RD) {
369 if (!RD)
370 return false;
371 // Generally, if a primary template class declaration is annotated with an
372 // attribute, all its specializations generated from template instantiations
373 // should inherit the attribute.
374 //
375 // However, since lifetime analysis occurs during parsing, we may encounter
376 // cases where a full definition of the specialization is not required. In
377 // such cases, the specialization declaration remains incomplete and lacks the
378 // attribute. Therefore, we fall back to checking the primary template class.
379 //
380 // Note: it is possible for a specialization declaration to have an attribute
381 // even if the primary template does not.
382 //
383 // FIXME: What if the primary template and explicit specialization
384 // declarations have conflicting attributes? We should consider diagnosing
385 // this scenario.
386 bool Result = RD->hasAttr<T>();
387
388 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
389 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<T>();
390
391 return Result;
392}
393
394template <typename T> static bool isRecordWithAttr(QualType Type) {
396}
397
402}
403
404static StringRef getName(const CXXRecordDecl &RD) {
405 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(&RD))
406 return CTSD->getSpecializedTemplate()->getName();
407 if (RD.getIdentifier())
408 return RD.getName();
409 return "";
410}
411
412static StringRef getName(const FunctionDecl &FD) {
413 if (FD.getIdentifier())
414 return FD.getName();
415 return "";
416}
417
418static bool isStdUniquePtr(const CXXRecordDecl &RD) {
419 return RD.isInStdNamespace() && getName(RD) == "unique_ptr";
420}
421
423 return MD.getIdentifier() && MD.getName() == "release" &&
424 MD.getNumParams() == 0 && isStdUniquePtr(*MD.getParent());
425}
426
428 const CXXRecordDecl *RD = MD.getParent();
429 if (!isInStlNamespace(RD))
430 return false;
431
432 // `pop_back` is excluded: it only invalidates references to the removed
433 // element, not to other elements.
434 static const llvm::StringSet<> Vector = {// Insertion
435 "insert", "emplace", "emplace_back",
436 "push_back", "insert_range",
437 "append_range",
438 // Removal
439 "erase", "clear",
440 // Memory management
441 "reserve", "resize", "shrink_to_fit",
442 // Assignment
443 "assign", "assign_range"};
444
445 // `pop_*` methods are excluded: they only invalidate references to the
446 // removed element, not to other elements.
447 static const llvm::StringSet<> Deque = {// Insertion
448 "insert", "emplace", "insert_range",
449 // Removal
450 "erase", "clear",
451 // Memory management
452 "resize", "shrink_to_fit",
453 // Assignment
454 "assign", "assign_range"};
455
456 static const llvm::StringSet<> String = {
457 // Insertion
458 "insert", "push_back", "append", "replace", "replace_with_range",
459 "insert_range", "append_range",
460 // Removal
461 "pop_back", "erase", "clear",
462 // Memory management
463 "reserve", "resize", "resize_and_overwrite", "shrink_to_fit",
464 // Assignment
465 "swap", "assign", "assign_range"};
466
467 // FIXME: Add queue and stack and check for underlying container
468 // (e.g. no invalidation for std::list).
469 static const llvm::StringSet<> PriorityQueue = {// Insertion
470 "push", "emplace",
471 "push_range",
472 // Removal
473 "pop"};
474
475 // `erase` and `extract` are excluded: they only affect the removed element,
476 // not to other elements.
477 static const llvm::StringSet<> NodeBased = {// Removal
478 "clear"};
479
480 // For `flat_*` container adaptors, `try_emplace` and `insert_or_assign`
481 // only exist on `flat_map`. Listing them here is harmless since the methods
482 // won't be found on other types.
483 static const llvm::StringSet<> Flat = {// Insertion
484 "insert", "emplace", "emplace_hint",
485 "try_emplace", "insert_or_assign",
486 "insert_range", "merge",
487 // Removal
488 "extract", "erase", "clear",
489 // Assignment
490 "replace"};
491
492 static const llvm::StringSet<> UniquePtr = {// Reallocation
493 "reset"};
494
495 const StringRef RecordName = getName(*RD);
496 // TODO: Consider caching this lookup by CXXMethodDecl pointer if this
497 // StringSwitch becomes a performance bottleneck.
498 const llvm::StringSet<> *InvalidatingMethods =
499 llvm::StringSwitch<const llvm::StringSet<> *>(RecordName)
500 .Case("vector", &Vector)
501 .Case("basic_string", &String)
502 .Case("deque", &Deque)
503 .Case("priority_queue", &PriorityQueue)
504 .Cases({"set", "multiset", "map", "multimap", "unordered_set",
505 "unordered_multiset", "unordered_map", "unordered_multimap"},
506 &NodeBased)
507 .Cases({"flat_map", "flat_set", "flat_multimap", "flat_multiset"},
508 &Flat)
509 .Case("unique_ptr", &UniquePtr)
510 .Default(nullptr);
511
512 if (!InvalidatingMethods)
513 return false;
514
515 // Handle Operators via OverloadedOperatorKind
517 if (OO != OO_None) {
518 switch (OO) {
519 case OO_Equal: // operator= : Always invalidates (Assignment)
520 case OO_PlusEqual: // operator+= : Append (String/Vector)
521 return true;
522 case OO_Subscript: // operator[] : Invalidation only for
523 // `flat_map` (Insert-or-access).
524 // `map` and `unordered_map` are excluded.
525 return RecordName == "flat_map";
526 default:
527 return false;
528 }
529 }
530
531 if (!MD.getIdentifier())
532 return false;
533
534 return InvalidatingMethods->contains(MD.getName());
535}
536
539 return true;
540 return isInStlNamespace(&FD) && getName(FD) == "destroy_at";
541}
542
544 if (!RD || !isInStlNamespace(RD))
545 return false;
546 StringRef Name = getName(*RD);
547 return Name == "function" || Name == "move_only_function";
548}
549
551 if (!FD)
552 return false;
553 switch (FD->getBuiltinID()) {
554 case Builtin::BImove:
555 case Builtin::BImove_if_noexcept:
556 case Builtin::BIforward:
557 case Builtin::BIforward_like:
558 case Builtin::BIas_const:
559 return true;
560 default:
561 return false;
562 }
563}
564
565} // 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:223
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:113
Attr - This represents one attribute.
Definition Attr.h:46
Type source information for an attributed type.
Definition TypeLoc.h:1008
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2288
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:1466
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2126
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
DeclContext * getDeclContext()
Definition DeclBase.h:456
bool hasAttr() const
Definition DeclBase.h:585
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:809
This represents one expression.
Definition Expr.h:113
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:2058
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2927
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
Definition Decl.cpp:3806
QualType getReturnType() const
Definition Decl.h:2975
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:4308
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:4174
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3870
size_t param_size() const
Definition Decl.h:2920
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:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
Represents a parameter to a function.
Definition Decl.h:1819
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:8473
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:8739
bool isReferenceType() const
Definition TypeBase.h:8763
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:1984
bool isLValueReferenceType() const
Definition TypeBase.h:8767
bool isNullPtrType() const
Definition TypeBase.h:9148
QualType getType() const
Definition Decl.h:723
FunctionCallInfo getFunctionCallInfo(const Expr *Call)
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)
static const LifetimeBoundAttr * getLifetimeBoundAttrFromFunctionType(const TypeSourceInfo &TSI)
Check if a function has a lifetimebound attribute on its function type (which represents the implicit...
bool isPointerLikeType(QualType QT)
bool isNormalAssignmentOperator(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)
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 shouldTrackSecondArgument(const FunctionDecl *FD)
static bool isStdUniquePtr(const CXXRecordDecl &RD)
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.
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