Author: Nikita Popov Date: 2024-11-11T20:57:26+01:00 New Revision: 3a03513fc6ef8f3272d33be19164243c9dbf0452
URL: https://github.com/llvm/llvm-project/commit/3a03513fc6ef8f3272d33be19164243c9dbf0452 DIFF: https://github.com/llvm/llvm-project/commit/3a03513fc6ef8f3272d33be19164243c9dbf0452.diff LOG: Revert "[clang] Introduce [[clang::lifetime_capture_by(X)]] (#111499)" This reverts commit 8c4331c1abeb33eabf3cdbefa7f2b6e0540e7f4f. Causes a large compile-time regression, see: https://llvm-compile-time-tracker.com/compare.php?from=4a68e4cbd2423dcacada8162ab7c4bb8d7f7e2cf&to=8c4331c1abeb33eabf3cdbefa7f2b6e0540e7f4f&stat=instructions:u Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Sema/Sema.h clang/lib/AST/TypePrinter.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaType.cpp Removed: clang/test/AST/attr-lifetime-capture-by.cpp clang/test/SemaCXX/attr-lifetime-capture-by.cpp ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e817b0ceb3fd06..e235a04f78112b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -449,9 +449,6 @@ Attribute Changes in Clang - Fix a bug where clang doesn't automatically apply the ``[[gsl::Owner]]`` or ``[[gsl::Pointer]]`` to STL explicit template specialization decls. (#GH109442) -- Clang now supports ``[[clang::lifetime_capture_by(X)]]``. Similar to lifetimebound, this can be - used to specify when a reference to a function parameter is captured by another capturing entity ``X``. - Improvements to Clang's diagnostics ----------------------------------- diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 6a77967c32cbcb..a631e81d40aa68 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1889,39 +1889,6 @@ def LifetimeBound : DeclOrTypeAttr { let SimpleHandler = 1; } -def LifetimeCaptureBy : DeclOrTypeAttr { - let Spellings = [Clang<"lifetime_capture_by", 0>]; - let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>; - let Args = [VariadicParamOrParamIdxArgument<"Params">]; - let Documentation = [LifetimeCaptureByDocs]; - let AdditionalMembers = [{ -private: - SmallVector<IdentifierInfo*, 1> ArgIdents; - SmallVector<SourceLocation, 1> ArgLocs; - -public: - static constexpr int THIS = 0; - static constexpr int INVALID = -1; - static constexpr int UNKNOWN = -2; - static constexpr int GLOBAL = -3; - - void setArgs(SmallVector<IdentifierInfo*>&& Idents, - SmallVector<SourceLocation>&& Locs) { - assert(Idents.size() == Locs.size()); - assert(Idents.size() == params_Size); - ArgIdents = std::move(Idents); - ArgLocs = std::move(Locs); - } - - ArrayRef<IdentifierInfo*> getArgIdents() const { return ArgIdents; } - ArrayRef<SourceLocation> getArgLocs() const { return ArgLocs; } - void setParamIdx(size_t Idx, int Val) { - assert(Idx < params_Size); - params_[Idx] = Val; - } -}]; -} - def TrivialABI : InheritableAttr { // This attribute does not have a C [[]] spelling because it requires the // CPlusPlus language option. diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 21fcd183e8969c..b64dbef6332e6a 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3918,75 +3918,6 @@ have their lifetimes extended. }]; } -def LifetimeCaptureByDocs : Documentation { - let Category = DocCatFunction; - let Content = [{ - Similar to `lifetimebound`_, the ``lifetime_capture_by(X)`` attribute on a function -parameter or implicit object parameter indicates that that objects that are referred to -by that parameter may also be referred to by the capturing entity ``X``. - -By default, a reference is considered to refer to its referenced object, a -pointer is considered to refer to its pointee, a ``std::initializer_list<T>`` -is considered to refer to its underlying array, and aggregates (arrays and -simple ``struct``\s) are considered to refer to all objects that their -transitive subobjects refer to. - -The capturing entity ``X`` can be one of the following: -- Another (named) function parameter. - - .. code-block:: c++ - - void addToSet(std::string_view a [[clang::lifetime_capture_by(s)]], std::set<std::string_view>& s) { - s.insert(a); - } - -- ``this`` (in case of member functions). - - .. code-block:: c++ - - class S { - void addToSet(std::string_view a [[clang::lifetime_capture_by(this)]]) { - s.insert(a); - } - std::set<std::string_view> s; - }; - -- 'global', 'unknown' (without quotes). - - .. code-block:: c++ - - std::set<std::string_view> s; - void addToSet(std::string_view a [[clang::lifetime_capture_by(global)]]) { - s.insert(a); - } - void addSomewhere(std::string_view a [[clang::lifetime_capture_by(unknown)]]); - -The attribute can be applied to the implicit ``this`` parameter of a member -function by writing the attribute after the function type: - -.. code-block:: c++ - - struct S { - const char *data(std::set<S*>& s) [[clang::lifetime_capture_by(s)]] { - s.insert(this); - } - }; - -The attribute supports specifying more than one capturing entities: - -.. code-block:: c++ - - void addToSets(std::string_view a [[clang::lifetime_capture_by(s1, s2)]], - std::set<std::string_view>& s1, - std::set<std::string_view>& s2) { - s1.insert(a); - s2.insert(a); - } - -.. _`lifetimebound`: https://clang.llvm.org/docs/AttributeReference.html#lifetimebound - }]; -} - def TrivialABIDocs : Documentation { let Category = DocCatDecl; let Content = [{ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f4452fbb57e736..a5d97d7e545ffd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3383,20 +3383,6 @@ def err_callback_callee_is_variadic : Error< "'callback' attribute callee may not be variadic">; def err_callback_implicit_this_not_available : Error< "'callback' argument at position %0 references unavailable implicit 'this'">; - -def err_capture_by_attribute_multiple : Error< - "multiple 'lifetime_capture' attributes specified">; -def err_capture_by_attribute_no_entity : Error< - "'lifetime_capture_by' attribute specifies no capturing entity">; -def err_capture_by_implicit_this_not_available : Error< - "'lifetime_capture_by' argument references unavailable implicit 'this'">; -def err_capture_by_attribute_argument_unknown : Error< - "'lifetime_capture_by' attribute argument %0 is not a known function parameter" - "; must be a function parameter, 'this', 'global' or 'unknown'">; -def err_capture_by_references_itself : Error<"'lifetime_capture_by' argument references itself">; -def err_capture_by_param_uses_reserved_name : Error< - "parameter cannot be named '%select{global|unknown}0' while using 'lifetime_capture_by(%select{global|unknown}0)'">; - def err_init_method_bad_return_type : Error< "init methods must return an object pointer type, not %0">; def err_attribute_invalid_size : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d6f3508a5243f3..fad446a05e782f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1760,14 +1760,6 @@ class Sema final : public SemaBase { /// Add [[gsl::Pointer]] attributes for std:: types. void inferGslPointerAttribute(TypedefNameDecl *TD); - LifetimeCaptureByAttr *ParseLifetimeCaptureByAttr(const ParsedAttr &AL, - StringRef ParamName); - // Processes the argument 'X' in [[clang::lifetime_capture_by(X)]]. Since 'X' - // can be the name of a function parameter, we need to parse the function - // declaration and rest of the parameters before processesing 'X'. Therefore - // do this lazily instead of processing while parsing the annotation itself. - void LazyProcessLifetimeCaptureByParams(FunctionDecl *FD); - /// Add _Nullable attributes for std:: types. void inferNullableClassAttribute(CXXRecordDecl *CRD); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index a073a6a4b7d454..6d8db5cf4ffd22 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -25,7 +25,6 @@ #include "clang/AST/TextNodeDumper.h" #include "clang/AST/Type.h" #include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/AttrKinds.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" @@ -1910,19 +1909,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, OS << " [[clang::lifetimebound]]"; return; } - if (T->getAttrKind() == attr::LifetimeCaptureBy) { - OS << " [[clang::lifetime_capture_by("; - if (auto *attr = dyn_cast_or_null<LifetimeCaptureByAttr>(T->getAttr())) { - auto Idents = attr->getArgIdents(); - for (unsigned I = 0; I < Idents.size(); ++I) { - OS << Idents[I]->getName(); - if (I != Idents.size() - 1) - OS << ", "; - } - } - OS << ")]]"; - return; - } // The printing of the address_space attribute is handled by the qualifier // since it is still stored in the qualifier. Return early to prevent printing @@ -1990,7 +1976,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::SizedBy: case attr::SizedByOrNull: case attr::LifetimeBound: - case attr::LifetimeCaptureBy: case attr::TypeNonNull: case attr::TypeNullable: case attr::TypeNullableResult: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a3bc8e4191c819..61c29e320d5c73 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16687,7 +16687,6 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } } - LazyProcessLifetimeCaptureByParams(FD); inferLifetimeBoundAttribute(FD); AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(FD); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b4aaa58c082002..d05d326178e1b8 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -14,7 +14,6 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" -#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -3868,113 +3867,6 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Context, AL, EncodingIndices.data(), EncodingIndices.size())); } -LifetimeCaptureByAttr *Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL, - StringRef ParamName) { - // Atleast one capture by is required. - if (AL.getNumArgs() == 0) { - Diag(AL.getLoc(), diag::err_capture_by_attribute_no_entity) - << AL.getRange(); - return nullptr; - } - SmallVector<IdentifierInfo *, 1> ParamIdents; - SmallVector<SourceLocation, 1> ParamLocs; - for (unsigned I = 0; I < AL.getNumArgs(); ++I) { - if (AL.isArgExpr(I)) { - Expr *E = AL.getArgAsExpr(I); - Diag(E->getExprLoc(), diag::err_capture_by_attribute_argument_unknown) - << E << E->getExprLoc(); - continue; - } - assert(AL.isArgIdent(I)); - IdentifierLoc *IdLoc = AL.getArgAsIdent(I); - if (IdLoc->Ident->getName() == ParamName) { - Diag(IdLoc->Loc, diag::err_capture_by_references_itself) << IdLoc->Loc; - continue; - } - ParamIdents.push_back(IdLoc->Ident); - ParamLocs.push_back(IdLoc->Loc); - } - SmallVector<int, 1> FakeParamIndices(ParamIdents.size(), - LifetimeCaptureByAttr::INVALID); - LifetimeCaptureByAttr *CapturedBy = ::new (Context) LifetimeCaptureByAttr( - Context, AL, FakeParamIndices.data(), FakeParamIndices.size()); - CapturedBy->setArgs(std::move(ParamIdents), std::move(ParamLocs)); - return CapturedBy; -} - -static void HandleLifetimeCaptureByAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - // Do not allow multiple attributes. - if (D->hasAttr<LifetimeCaptureByAttr>()) { - S.Diag(AL.getLoc(), diag::err_capture_by_attribute_multiple) - << AL.getRange(); - return; - } - auto *PVD = dyn_cast<ParmVarDecl>(D); - assert(PVD); - auto *CaptureByAttr = S.ParseLifetimeCaptureByAttr(AL, PVD->getName()); - if (CaptureByAttr) - D->addAttr(CaptureByAttr); -} - -void Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) { - bool HasImplicitThisParam = isInstanceMethod(FD); - - llvm::StringMap<int> NameIdxMapping; - NameIdxMapping["global"] = LifetimeCaptureByAttr::GLOBAL; - NameIdxMapping["unknown"] = LifetimeCaptureByAttr::UNKNOWN; - int Idx = 0; - if (HasImplicitThisParam) { - NameIdxMapping["this"] = 0; - Idx++; - } - for (const ParmVarDecl *PVD : FD->parameters()) - NameIdxMapping[PVD->getName()] = Idx++; - auto DisallowReservedParams = [&](StringRef Reserved) { - for (const ParmVarDecl *PVD : FD->parameters()) - if (PVD->getName() == Reserved) - Diag(PVD->getLocation(), diag::err_capture_by_param_uses_reserved_name) - << (PVD->getName() == "unknown"); - }; - auto HandleCaptureBy = [&](LifetimeCaptureByAttr *CapturedBy) { - if (!CapturedBy) - return; - const auto &Entities = CapturedBy->getArgIdents(); - for (size_t I = 0; I < Entities.size(); ++I) { - StringRef Name = Entities[I]->getName(); - auto It = NameIdxMapping.find(Name); - if (It == NameIdxMapping.end()) { - auto Loc = CapturedBy->getArgLocs()[I]; - if (!HasImplicitThisParam && Name == "this") - Diag(Loc, diag::err_capture_by_implicit_this_not_available) << Loc; - else - Diag(Loc, diag::err_capture_by_attribute_argument_unknown) - << Entities[I] << Loc; - continue; - } - if (Name == "unknown" || Name == "global") - DisallowReservedParams(Name); - CapturedBy->setParamIdx(I, It->second); - } - }; - for (ParmVarDecl *PVD : FD->parameters()) - HandleCaptureBy(PVD->getAttr<LifetimeCaptureByAttr>()); - if (!HasImplicitThisParam) - return; - TypeSourceInfo *TSI = FD->getTypeSourceInfo(); - if (!TSI) - return; - AttributedTypeLoc ATL; - for (TypeLoc TL = TSI->getTypeLoc(); - (ATL = TL.getAsAdjusted<AttributedTypeLoc>()); - TL = ATL.getModifiedLoc()) { - auto *A = ATL.getAttrAs<LifetimeCaptureByAttr>(); - if (!A) - continue; - HandleCaptureBy(const_cast<LifetimeCaptureByAttr *>(A)); - } -} - static bool isFunctionLike(const Type &T) { // Check for explicit function types. // 'called_once' is only supported in Objective-C and it has @@ -6752,9 +6644,6 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_Callback: handleCallbackAttr(S, D, AL); break; - case ParsedAttr::AT_LifetimeCaptureBy: - HandleLifetimeCaptureByAttr(S, D, AL); - break; case ParsedAttr::AT_CalledOnce: handleCalledOnceAttr(S, D, AL); break; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index eb7516b3ef1ece..515b9f689a248a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -8609,15 +8609,6 @@ static void HandleLifetimeBoundAttr(TypeProcessingState &State, } } -static void HandleLifetimeCaptureByAttr(TypeProcessingState &State, - QualType &CurType, ParsedAttr &PA) { - if (State.getDeclarator().isDeclarationOfFunction()) { - auto *Attr = State.getSema().ParseLifetimeCaptureByAttr(PA, "this"); - if (Attr) - CurType = State.getAttributedType(Attr, CurType, CurType); - } -} - static void HandleHLSLParamModifierAttr(TypeProcessingState &State, QualType &CurType, const ParsedAttr &Attr, Sema &S) { @@ -8779,10 +8770,6 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (TAL == TAL_DeclChunk) HandleLifetimeBoundAttr(state, type, attr); break; - case ParsedAttr::AT_LifetimeCaptureBy: - if (TAL == TAL_DeclChunk) - HandleLifetimeCaptureByAttr(state, type, attr); - break; case ParsedAttr::AT_NoDeref: { // FIXME: `noderef` currently doesn't work correctly in [[]] syntax. diff --git a/clang/test/AST/attr-lifetime-capture-by.cpp b/clang/test/AST/attr-lifetime-capture-by.cpp deleted file mode 100644 index da2eb0cf3d592e..00000000000000 --- a/clang/test/AST/attr-lifetime-capture-by.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// RUN: %clang_cc1 %s -ast-dump | FileCheck %s - -// Verify that we print the [[clang::lifetime_capture_by(X)]] attribute. - -struct S { - void foo(int &a, int &b) [[clang::lifetime_capture_by(a, b, global)]]; -}; - -// CHECK: CXXMethodDecl {{.*}}clang::lifetime_capture_by(a, b, global) diff --git a/clang/test/SemaCXX/attr-lifetime-capture-by.cpp b/clang/test/SemaCXX/attr-lifetime-capture-by.cpp deleted file mode 100644 index 3115dc8d6150c9..00000000000000 --- a/clang/test/SemaCXX/attr-lifetime-capture-by.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// RUN: %clang_cc1 -std=c++23 -verify %s - -struct S { - const int *x; - void captureInt(const int&x [[clang::lifetime_capture_by(this)]]) { this->x = &x; } -}; - -/////////////////////////// -// Test for valid usages. -/////////////////////////// -[[clang::lifetime_capture_by(unknown)]] // expected-error {{'lifetime_capture_by' attribute only applies to parameters and implicit object parameters}} -void nonMember( - const int &x1 [[clang::lifetime_capture_by(s, t)]], - S &s, - S &t, - const int &x2 [[clang::lifetime_capture_by(12345 + 12)]], // expected-error {{'lifetime_capture_by' attribute argument 12345 + 12 is not a known function parameter; must be a function parameter, 'this', 'global' or 'unknown'}} - const int &x3 [[clang::lifetime_capture_by(abcdefgh)]], // expected-error {{'lifetime_capture_by' attribute argument 'abcdefgh' is not a known function parameter; must be a function parameter, 'this', 'global' or 'unknown'}} - const int &x4 [[clang::lifetime_capture_by("abcdefgh")]], // expected-error {{'lifetime_capture_by' attribute argument "abcdefgh" is not a known function parameter; must be a function parameter, 'this', 'global' or 'unknown'}} - const int &x5 [[clang::lifetime_capture_by(this)]], // expected-error {{'lifetime_capture_by' argument references unavailable implicit 'this'}} - const int &x6 [[clang::lifetime_capture_by()]], // expected-error {{'lifetime_capture_by' attribute specifies no capturing entity}} - const int& x7 [[clang::lifetime_capture_by(u, - x7)]], // expected-error {{'lifetime_capture_by' argument references itself}} - const int &x8 [[clang::lifetime_capture_by(global)]], - const int &x9 [[clang::lifetime_capture_by(unknown)]], - const S& u - ) -{ - s.captureInt(x1); -} - -void unknown_param_name(const int& unknown, // expected-error {{parameter cannot be named 'unknown' while using 'lifetime_capture_by(unknown)'}} - const int& s [[clang::lifetime_capture_by(unknown)]]); -void global_param_name(const int& global, // expected-error {{parameter cannot be named 'global' while using 'lifetime_capture_by(global)'}} - const int& s [[clang::lifetime_capture_by(global)]]); -struct T { - void member( - const int &x [[clang::lifetime_capture_by(s)]], - S &s, - S &t, - const int &y [[clang::lifetime_capture_by(s)]], - const int &z [[clang::lifetime_capture_by(this, x, y)]], - const int &u [[clang::lifetime_capture_by(global, unknown, x, s)]]) - { - s.captureInt(x); - } -}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits