https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/117315
>From e30ae8a6e0c1df8e33c2add6502342cb269c1cfd Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena <u...@google.com> Date: Fri, 22 Nov 2024 11:02:49 +0000 Subject: [PATCH 1/3] [clang] Check specialization for annotation --- clang/lib/Sema/CheckExprLifetime.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp index 8886e5e307ddf8..64dc4794b6235a 100644 --- a/clang/lib/Sema/CheckExprLifetime.cpp +++ b/clang/lib/Sema/CheckExprLifetime.cpp @@ -253,9 +253,12 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, LocalVisitor Visit); template <typename T> static bool isRecordWithAttr(QualType Type) { - if (auto *RD = Type->getAsCXXRecordDecl()) - return RD->hasAttr<T>(); - return false; + auto *RD = Type->getAsCXXRecordDecl(); + if (!RD) + return false; + if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) + RD = CTSD->getSpecializedTemplate()->getTemplatedDecl(); + return RD->hasAttr<T>(); } // Decl::isInStdNamespace will return false for iterators in some STL >From db163394b70054694734c269f5fd61ef438eda3b Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena <u...@google.com> Date: Thu, 28 Nov 2024 09:01:25 +0000 Subject: [PATCH 2/3] move to Sema.h --- clang/include/clang/Sema/Sema.h | 12 ++++++++ clang/lib/Sema/CheckExprLifetime.cpp | 45 ++++++++++------------------ clang/lib/Sema/SemaAttr.cpp | 5 ++++ 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6ea6c67447b6f0..9029d54e90f028 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1760,6 +1760,18 @@ class Sema final : public SemaBase { /// Add [[gsl::Pointer]] attributes for std:: types. void inferGslPointerAttribute(TypedefNameDecl *TD); + template <typename T> static bool isRecordWithAttr(QualType Type) { + auto *RD = Type->getAsCXXRecordDecl(); + if (!RD) + return false; + if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) + RD = CTSD->getSpecializedTemplate()->getTemplatedDecl(); + return RD->hasAttr<T>(); + } + + /// .... + static bool isPointerLikeType(QualType Type); + LifetimeCaptureByAttr *ParseLifetimeCaptureByAttr(const ParsedAttr &AL, StringRef ParamName); // Processes the argument 'X' in [[clang::lifetime_capture_by(X)]]. Since 'X' diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp index 64dc4794b6235a..e18651d8e12ab9 100644 --- a/clang/lib/Sema/CheckExprLifetime.cpp +++ b/clang/lib/Sema/CheckExprLifetime.cpp @@ -252,15 +252,6 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit); -template <typename T> static bool isRecordWithAttr(QualType Type) { - auto *RD = Type->getAsCXXRecordDecl(); - if (!RD) - return false; - if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - RD = CTSD->getSpecializedTemplate()->getTemplatedDecl(); - return RD->hasAttr<T>(); -} - // Decl::isInStdNamespace will return false for iterators in some STL // implementations due to them being defined in a namespace outside of the std // namespace. @@ -279,11 +270,6 @@ static bool isInStlNamespace(const Decl *D) { return DC->isStdNamespace(); } -static bool isPointerLikeType(QualType Type) { - return isRecordWithAttr<PointerAttr>(Type) || Type->isPointerType() || - Type->isNullPtrType(); -} - // Returns true if the given Record decl is a form of `GSLOwner<Pointer>` // type, e.g. std::vector<string_view>, std::optional<string_view>. static bool isContainerOfPointer(const RecordDecl *Container) { @@ -293,7 +279,7 @@ static bool isContainerOfPointer(const RecordDecl *Container) { return false; const auto &TAs = CTSD->getTemplateArgs(); return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type && - isPointerLikeType(TAs[0].getAsType()); + Sema::isPointerLikeType(TAs[0].getAsType()); } return false; } @@ -306,7 +292,7 @@ static bool isContainerOfOwner(const RecordDecl *Container) { return false; const auto &TAs = CTSD->getTemplateArgs(); return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type && - isRecordWithAttr<OwnerAttr>(TAs[0].getAsType()); + Sema::isRecordWithAttr<OwnerAttr>(TAs[0].getAsType()); } // Returns true if the given Record is `std::initializer_list<pointer>`. @@ -317,23 +303,24 @@ static bool isStdInitializerListOfPointer(const RecordDecl *RD) { return isInStlNamespace(RD) && RD->getIdentifier() && RD->getName() == "initializer_list" && TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type && - isPointerLikeType(TAs[0].getAsType()); + Sema::isPointerLikeType(TAs[0].getAsType()); } return false; } static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) { if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee)) - if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()) && + if (Sema::isRecordWithAttr<PointerAttr>(Conv->getConversionType()) && Callee->getParent()->hasAttr<OwnerAttr>()) return true; if (!isInStlNamespace(Callee->getParent())) return false; - if (!isRecordWithAttr<PointerAttr>( + if (!Sema::isRecordWithAttr<PointerAttr>( Callee->getFunctionObjectParameterType()) && - !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType())) + !Sema::isRecordWithAttr<OwnerAttr>( + Callee->getFunctionObjectParameterType())) return false; - if (isPointerLikeType(Callee->getReturnType())) { + if (Sema::isPointerLikeType(Callee->getReturnType())) { if (!Callee->getIdentifier()) return false; return llvm::StringSwitch<bool>(Callee->getName()) @@ -366,7 +353,7 @@ static bool shouldTrackFirstArgument(const FunctionDecl *FD) { if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>()) return false; if (FD->getReturnType()->isPointerType() || - isRecordWithAttr<PointerAttr>(FD->getReturnType())) { + Sema::isRecordWithAttr<PointerAttr>(FD->getReturnType())) { return llvm::StringSwitch<bool>(FD->getName()) .Cases("begin", "rbegin", "cbegin", "crbegin", true) .Cases("end", "rend", "cend", "crend", true) @@ -438,7 +425,7 @@ shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor) { return true; // RHS must be an owner. - if (!isRecordWithAttr<OwnerAttr>(RHSArgType)) + if (!Sema::isRecordWithAttr<OwnerAttr>(RHSArgType)) return false; // Bail out if the RHS is Owner<Pointer>. @@ -565,7 +552,7 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call, // Once we initialized a value with a non gsl-owner reference, it can no // longer dangle. if (ReturnType->isReferenceType() && - !isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) { + !Sema::isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) { for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) { if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit || PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall) @@ -1111,7 +1098,7 @@ static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef, bool EnableGSLAssignmentWarnings = !SemaRef.getDiagnostics().isIgnored( diag::warn_dangling_lifetime_pointer_assignment, SourceLocation()); return (EnableGSLAssignmentWarnings && - (isRecordWithAttr<PointerAttr>(Entity.LHS->getType()) || + (Sema::isRecordWithAttr<PointerAttr>(Entity.LHS->getType()) || isAssignmentOperatorLifetimeBound(Entity.AssignmentOperator))); } @@ -1146,12 +1133,12 @@ checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, // someContainer.add(std::move(localUniquePtr)); // return p; if (pathContainsInit(Path) || - !isRecordWithAttr<OwnerAttr>(L->getType())) + !Sema::isRecordWithAttr<OwnerAttr>(L->getType())) return false; } else { IsGslPtrValueFromGslTempOwner = MTE && !MTE->getExtendingDecl() && - isRecordWithAttr<OwnerAttr>(MTE->getType()); + Sema::isRecordWithAttr<OwnerAttr>(MTE->getType()); // Skipping a chain of initializing gsl::Pointer annotated objects. // We are looking only for the final source to find out if it was // a local or temporary owner or the address of a local variable/param. @@ -1280,7 +1267,7 @@ checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, auto *DRE = dyn_cast<DeclRefExpr>(L); // Suppress false positives for code like the one below: // Ctor(unique_ptr<T> up) : pointer(up.get()), owner(move(up)) {} - if (DRE && isRecordWithAttr<OwnerAttr>(DRE->getType())) + if (DRE && Sema::isRecordWithAttr<OwnerAttr>(DRE->getType())) return false; auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr; @@ -1441,7 +1428,7 @@ checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, break; } case LK_LifetimeCapture: { - if (isPointerLikeType(Init->getType())) + if (Sema::isPointerLikeType(Init->getType())) Path.push_back({IndirectLocalPathEntry::GslPointerInit, Init}); break; } diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 9fbad7ed67ccbe..9d21a01cd1b186 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -215,6 +215,11 @@ void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) { inferGslPointerAttribute(Record, Record); } +bool Sema::isPointerLikeType(QualType Type) { + return isRecordWithAttr<PointerAttr>(Type) || Type->isPointerType() || + Type->isNullPtrType(); +} + void Sema::inferLifetimeBoundAttribute(FunctionDecl *FD) { if (FD->getNumParams() == 0) return; >From 9b412ba242f47f2d16f53615dba6cbd2392a5042 Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena <u...@google.com> Date: Thu, 28 Nov 2024 09:12:46 +0000 Subject: [PATCH 3/3] reuse in lifetime capture by --- clang/lib/Sema/SemaAttr.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index ba87262fc6d435..53a7387ad69353 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -274,18 +274,6 @@ void Sema::inferLifetimeBoundAttribute(FunctionDecl *FD) { } } -static bool isPointerLikeType(QualType QT) { - QT = QT.getNonReferenceType(); - if (QT->isPointerType()) - return true; - auto *RD = QT->getAsCXXRecordDecl(); - if (!RD) - return false; - if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - RD = CTSD->getSpecializedTemplate()->getTemplatedDecl(); - return RD->hasAttr<PointerAttr>(); -} - void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) { if (!FD) return; @@ -304,7 +292,7 @@ void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) { if (PVD->hasAttr<LifetimeCaptureByAttr>()) return; for (ParmVarDecl *PVD : MD->parameters()) { - if (isPointerLikeType(PVD->getType())) { + if (isPointerLikeType(PVD->getType().getNonReferenceType())) { int CaptureByThis[] = {LifetimeCaptureByAttr::THIS}; PVD->addAttr( LifetimeCaptureByAttr::CreateImplicit(Context, CaptureByThis, 1)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits