21#include "llvm/ADT/StringSet.h"
33 return cast_if_present<CXXMethodDecl>(
47 auto *MD = dyn_cast<CXXMethodDecl>(FD);
48 if (MD && MD->isCXXInstanceMember())
64template <
typename AttrType>
74 if (
auto *
Attr = ATL.getAttrAs<AttrType>())
76 TL = ATL.getModifiedLoc();
81template <
typename AttrType>
88 auto CheckRedecls = [](
const FunctionDecl *F) ->
const AttrType * {
95 if (
const auto *
Attr = CheckRedecls(FD))
98 return CheckRedecls(Pattern);
102const LifetimeBoundAttr *
107const LifetimeBoundAttr *
119 if (PVD.
hasAttr<LifetimeBoundAttr>())
123 [](
const LifetimeCaptureByAttr *A) {
124 return llvm::is_contained(A->params(),
125 LifetimeCaptureByAttr::This);
129const LifetimeCaptureByAttr *
142 Args = AC->arguments();
143 FD = dyn_cast_or_null<FunctionDecl>(AC->getDecl());
147 const auto *MD = dyn_cast<CXXMethodDecl>(&FD);
165std::optional<LifetimeBoundParamInfo>
169 if (!FD || I >= Args.size())
179 return TrackObject ? std::optional(LifetimeBoundParamInfo(
Method))
183 return LifetimeBoundParamInfo(
Method->getParamDecl(0));
194 return LifetimeBoundParamInfo(PVD);
199std::optional<LifetimeBoundParamInfo>
201 if (!
Call || !Source)
204 auto [FD, Args] = FunctionCallInfo(
Call);
208 for (
unsigned I = 0; I < Args.size(); ++I)
210 if (std::optional<LifetimeBoundParamInfo> ParamInfo =
219 if (DC->isStdNamespace())
221 if (
const auto *ND = dyn_cast<NamespaceDecl>(DC))
223 StringRef Name = II->getName();
224 if (Name.size() >= 2 && Name.front() ==
'_' &&
242 bool RunningUnderLifetimeSafety) {
247 const bool IsGslOwnerImplicitObject =
249 (RunningUnderLifetimeSafety &&
251 if (
auto *Conv = dyn_cast<CXXConversionDecl>(Callee))
252 if (
isGslPointerType(Conv->getConversionType()) && IsGslOwnerImplicitObject)
255 !IsGslOwnerImplicitObject)
259 static const llvm::StringSet<> IteratorMembers = {
260 "begin",
"end",
"rbegin",
"rend",
"cbegin",
"cend",
"crbegin",
"crend"};
261 static const llvm::StringSet<> InnerPointerGetters = {
263 "c_str",
"data",
"get"};
264 static const llvm::StringSet<> ContainerFindFns = {
266 "find",
"equal_range",
"lower_bound",
"upper_bound"};
270 if (RunningUnderLifetimeSafety &&
275 switch (Callee->getOverloadedOperator()) {
286 if (Callee->getIdentifier() &&
287 (IteratorMembers.contains(Callee->getName()) ||
288 InnerPointerGetters.contains(Callee->getName())))
296 if (!Callee->getIdentifier())
298 return RunningUnderLifetimeSafety
299 ? IsGslOwnerImplicitObject &&
300 Callee->getOverloadedOperator() ==
301 OverloadedOperatorKind::OO_Arrow
303 return IteratorMembers.contains(Callee->getName()) ||
304 InnerPointerGetters.contains(Callee->getName()) ||
305 ContainerFindFns.contains(Callee->getName());
307 if (Callee->getReturnType()->isReferenceType()) {
308 if (!Callee->getIdentifier()) {
309 auto OO = Callee->getOverloadedOperator();
310 if (!IsGslOwnerImplicitObject)
312 return OO == OverloadedOperatorKind::OO_Subscript ||
313 OO == OverloadedOperatorKind::OO_Star;
315 return llvm::StringSwitch<bool>(Callee->getName())
316 .Cases({
"front",
"back",
"at",
"top",
"value"},
true)
331 if (llvm::StringSwitch<bool>(FD->
getName())
350 if (!RD || !RD->isInStdNamespace())
352 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
360 return llvm::StringSwitch<bool>(FD->
getName())
361 .Cases({
"begin",
"rbegin",
"cbegin",
"crbegin"},
true)
362 .Cases({
"end",
"rend",
"cend",
"crend"},
true)
367 return llvm::StringSwitch<bool>(FD->
getName())
368 .Cases({
"get",
"any_cast"},
true)
382 return RD->
hasAttr<PointerAttr>() &&
410 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
411 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<
T>();
432 if (
const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(&RD))
433 return CTSD->getSpecializedTemplate()->getName();
461 static const llvm::StringSet<>
Vector = {
462 "insert",
"emplace",
"emplace_back",
463 "push_back",
"insert_range",
468 "reserve",
"resize",
"shrink_to_fit",
470 "assign",
"assign_range"};
474 static const llvm::StringSet<> Deque = {
475 "insert",
"emplace",
"insert_range",
479 "resize",
"shrink_to_fit",
481 "assign",
"assign_range"};
483 static const llvm::StringSet<> String = {
485 "insert",
"push_back",
"append",
"replace",
"replace_with_range",
486 "insert_range",
"append_range",
488 "pop_back",
"erase",
"clear",
490 "reserve",
"resize",
"resize_and_overwrite",
"shrink_to_fit",
492 "swap",
"assign",
"assign_range"};
496 static const llvm::StringSet<> PriorityQueue = {
504 static const llvm::StringSet<> NodeBased = {
510 static const llvm::StringSet<> Flat = {
511 "insert",
"emplace",
"emplace_hint",
512 "try_emplace",
"insert_or_assign",
513 "insert_range",
"merge",
515 "extract",
"erase",
"clear",
519 static const llvm::StringSet<> UniquePtr = {
522 const StringRef RecordName =
getName(*RD);
525 const llvm::StringSet<> *InvalidatingMethods =
526 llvm::StringSwitch<const llvm::StringSet<> *>(RecordName)
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"},
534 .Cases({
"flat_map",
"flat_set",
"flat_multimap",
"flat_multiset"},
536 .Case(
"unique_ptr", &UniquePtr)
539 if (!InvalidatingMethods)
552 return RecordName ==
"flat_map";
561 return InvalidatingMethods->contains(MD.
getName());
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:
583 [](
const OwnershipAttr *
Attr) {
584 return Attr->getOwnKind() == OwnershipAttr::Returns;
590 case Builtin::BIfree:
591 case Builtin::BI__builtin_free:
592 case Builtin::BIrealloc:
593 case Builtin::BI__builtin_realloc:
599 [](
const OwnershipAttr *
Attr) {
600 return Attr->getOwnKind() == OwnershipAttr::Takes;
608 return Name ==
"function" || Name ==
"move_only_function";
615 case Builtin::BImove:
616 case Builtin::BImove_if_noexcept:
617 case Builtin::BIforward:
618 case Builtin::BIforward_like:
619 case Builtin::BIas_const:
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 ...
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.
Attr - This represents one attribute.
Type source information for an attributed type.
Represents a C++ constructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
ASTContext & getASTContext() const LLVM_READONLY
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
DeclContext * getDeclContext()
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
This represents one expression.
const CXXRecordDecl * getBestDynamicClassType() const
For an expression of class type or pointer to class type, return the most derived class decl the expr...
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
QualType getReturnType() const
FunctionDecl * getTemplateInstantiationPattern(bool ForDefinition=true) const
Retrieve the function declaration from which this function could be instantiated, if it is an instant...
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.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
size_t param_size() const
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.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a parameter to a function.
A (possibly-)qualified type.
Base wrapper for a particular "section" of type source info.
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isPointerType() const
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
bool isLValueReferenceType() const
bool isNullPtrType() const
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)
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...
LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
@ 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.
const FunctionProtoType * T
Expr * IgnoreImplicitCastsSingleStep(Expr *E)
Expr * IgnoreParensSingleStep(Expr *E)
U cast(CodeGen::Address addr)
llvm::SmallVector< const Expr *, 4 > Args
FunctionCallInfo(const Expr *Call)