16#include "llvm/ADT/StringSet.h"
28 return cast_if_present<CXXMethodDecl>(
42 auto *MD = dyn_cast<CXXMethodDecl>(FD);
43 if (MD && MD->isCXXInstanceMember())
59static const LifetimeBoundAttr *
67 if (
auto *LBAttr = ATL.getAttrAs<LifetimeBoundAttr>())
69 TL = ATL.getModifiedLoc();
79 return llvm::any_of(F->redecls(), [](
const FunctionDecl *Redecl) {
80 const TypeSourceInfo *TSI = Redecl->getTypeSourceInfo();
81 return TSI && getLifetimeBoundAttrFromFunctionType(*TSI);
88 Pattern && CheckRedecls(Pattern))
97 if (
const auto *ND = dyn_cast<NamespaceDecl>(DC))
99 StringRef Name = II->getName();
100 if (Name.size() >= 2 && Name.front() ==
'_' &&
116 bool RunningUnderLifetimeSafety) {
119 if (
auto *Conv = dyn_cast<CXXConversionDecl>(Callee))
121 Callee->getParent()->hasAttr<OwnerAttr>())
128 static const llvm::StringSet<> IteratorMembers = {
129 "begin",
"end",
"rbegin",
"rend",
"cbegin",
"cend",
"crbegin",
"crend"};
130 static const llvm::StringSet<> InnerPointerGetters = {
132 "c_str",
"data",
"get"};
133 static const llvm::StringSet<> ContainerFindFns = {
135 "find",
"equal_range",
"lower_bound",
"upper_bound"};
139 if (RunningUnderLifetimeSafety &&
142 if (Callee->getOverloadedOperator() == OverloadedOperatorKind::OO_Star ||
143 Callee->getOverloadedOperator() == OverloadedOperatorKind::OO_Arrow)
145 if (Callee->getIdentifier() &&
146 (IteratorMembers.contains(Callee->getName()) ||
147 InnerPointerGetters.contains(Callee->getName())))
155 if (!Callee->getIdentifier())
157 return RunningUnderLifetimeSafety
158 ? Callee->getParent()->hasAttr<OwnerAttr>() &&
159 Callee->getOverloadedOperator() ==
160 OverloadedOperatorKind::OO_Arrow
162 return IteratorMembers.contains(Callee->getName()) ||
163 InnerPointerGetters.contains(Callee->getName()) ||
164 ContainerFindFns.contains(Callee->getName());
166 if (Callee->getReturnType()->isReferenceType()) {
167 if (!Callee->getIdentifier()) {
168 auto OO = Callee->getOverloadedOperator();
169 if (!Callee->getParent()->hasAttr<OwnerAttr>())
171 return OO == OverloadedOperatorKind::OO_Subscript ||
172 OO == OverloadedOperatorKind::OO_Star;
174 return llvm::StringSwitch<bool>(Callee->getName())
175 .Cases({
"front",
"back",
"at",
"top",
"value"},
true)
190 if (llvm::StringSwitch<bool>(FD->
getName())
209 if (!RD || !RD->isInStdNamespace())
211 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
219 return llvm::StringSwitch<bool>(FD->
getName())
220 .Cases({
"begin",
"rbegin",
"cbegin",
"crbegin"},
true)
221 .Cases({
"end",
"rend",
"cend",
"crend"},
true)
226 return llvm::StringSwitch<bool>(FD->
getName())
227 .Cases({
"get",
"any_cast"},
true)
252 bool Result = RD->hasAttr<T>();
254 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
255 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<T>();
264 if (
const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(&RD))
265 return CTSD->getSpecializedTemplate()->getName();
287 static const llvm::StringSet<>
Vector = {
288 "insert",
"emplace",
"emplace_back",
289 "push_back",
"insert_range",
294 "reserve",
"resize",
"shrink_to_fit",
296 "assign",
"assign_range"};
300 static const llvm::StringSet<> Deque = {
301 "insert",
"emplace",
"insert_range",
305 "resize",
"shrink_to_fit",
307 "assign",
"assign_range"};
309 static const llvm::StringSet<> String = {
311 "insert",
"push_back",
"append",
"replace",
"replace_with_range",
312 "insert_range",
"append_range",
314 "pop_back",
"erase",
"clear",
316 "reserve",
"resize",
"resize_and_overwrite",
"shrink_to_fit",
318 "swap",
"assign",
"assign_range"};
322 static const llvm::StringSet<> PriorityQueue = {
330 static const llvm::StringSet<> NodeBased = {
336 static const llvm::StringSet<> Flat = {
337 "insert",
"emplace",
"emplace_hint",
338 "try_emplace",
"insert_or_assign",
339 "insert_range",
"merge",
341 "extract",
"erase",
"clear",
345 const StringRef ContainerName =
getName(*RD);
348 const llvm::StringSet<> *InvalidatingMethods =
349 llvm::StringSwitch<const llvm::StringSet<> *>(ContainerName)
351 .Case(
"basic_string", &String)
352 .Case(
"deque", &Deque)
353 .Case(
"priority_queue", &PriorityQueue)
354 .Cases({
"set",
"multiset",
"map",
"multimap",
"unordered_set",
355 "unordered_multiset",
"unordered_map",
"unordered_multimap"},
357 .Cases({
"flat_map",
"flat_set",
"flat_multimap",
"flat_multiset"},
361 if (!InvalidatingMethods)
374 return ContainerName ==
"flat_map";
383 return InvalidatingMethods->contains(MD.
getName());
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::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.
Type source information for an attributed type.
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...
bool isStdNamespace() const
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
ASTContext & getASTContext() const LLVM_READONLY
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...
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
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.
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.
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
static bool isRecordWithAttr(QualType Type)
bool isGslPointerType(QualType QT)
bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee, bool RunningUnderLifetimeSafety)
bool shouldTrackFirstArgument(const FunctionDecl *FD)
static StringRef getName(const CXXRecordDecl &RD)
bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
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 isContainerInvalidationMethod(const CXXMethodDecl &MD)
bool isUniquePtrRelease(const CXXMethodDecl &MD)
static bool isReferenceOrPointerLikeType(QualType QT)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
bool isGslOwnerType(QualType QT)
bool isInStlNamespace(const Decl *D)
static bool isStdUniquePtr(const CXXRecordDecl &RD)
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
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].
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Result
The result type of a method or function.