https://github.com/NeKon69 updated 
https://github.com/llvm/llvm-project/pull/196635

>From 2814f5ac8f2d74b1fd863df47b1267490c2dc621 Mon Sep 17 00:00:00 2001
From: NeKon69 <[email protected]>
Date: Fri, 8 May 2026 21:15:49 +0300
Subject: [PATCH 1/4] add support for __global__/__unknown__

---
 clang/include/clang/Basic/AttrDocs.td         |  9 ++++---
 .../clang/Basic/DiagnosticSemaKinds.td        |  7 +++--
 clang/lib/Sema/SemaDeclAttr.cpp               | 18 ++++++++++---
 .../warn-lifetime-analysis-capture-by.cpp     |  4 +--
 .../test/SemaCXX/attr-lifetime-capture-by.cpp | 26 ++++++++++++-------
 5 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 4b45f413054f3..2884a7a9359f4 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -4643,15 +4643,18 @@ The capturing entity ``X`` can be one of the following:
 
   Note: When applied to a constructor parameter, 
`[[clang::lifetime_capture_by(this)]]` is just an alias of 
`[[clang::lifetimebound]]`.
 
-- `global`, `unknown`.
+- ``__global__``, ``__unknown__``.
 
   .. code-block:: c++
 
     std::set<std::string_view> s;
-    void addToSet(std::string_view a [[clang::lifetime_capture_by(global)]]) {
+    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)]]);
+    void addSomewhere(std::string_view a 
[[clang::lifetime_capture_by(__unknown__)]]);
+
+  The older spellings ``global`` and ``unknown`` are deprecated, but remain
+  accepted for compatibility.
 
 The attribute can be applied to the implicit ``this`` parameter of a member
 function by writing the attribute after the function type:
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c15a9ec1ff0f6..7964006f5ce0b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3560,10 +3560,13 @@ 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'">;
+  "; 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)'">;
+  "parameter cannot be named '%0' while using 'lifetime_capture_by(%0)'">;
+def warn_deprecated_capture_by_special_entity : Warning<
+  "'lifetime_capture_by(%0)' is deprecated; use 'lifetime_capture_by(%1)' 
instead">,
+  InGroup<DeprecatedAttributes>;
 
 def err_init_method_bad_return_type : Error<
   "init methods must return an object pointer type, not %0">;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 55b6cbcbba57d..9785c381c7ff6 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4426,6 +4426,15 @@ LifetimeCaptureByAttr 
*Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL,
     }
     assert(AL.isArgIdent(I));
     IdentifierLoc *IdLoc = AL.getArgAsIdent(I);
+    StringRef Name = IdLoc->getIdentifierInfo()->getName();
+    StringRef Replacement;
+    if (Name == "global")
+      Replacement = "__global__";
+    else if (Name == "unknown")
+      Replacement = "__unknown__";
+    if (!Replacement.empty())
+      Diag(IdLoc->getLoc(), diag::warn_deprecated_capture_by_special_entity)
+          << Name << Replacement;
     if (IdLoc->getIdentifierInfo()->getName() == ParamName) {
       Diag(IdLoc->getLoc(), diag::err_capture_by_references_itself)
           << IdLoc->getLoc();
@@ -4481,7 +4490,9 @@ void 
Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
     return;
   llvm::StringMap<int> NameIdxMapping = {
       {"global", LifetimeCaptureByAttr::Global},
-      {"unknown", LifetimeCaptureByAttr::Unknown}};
+      {"unknown", LifetimeCaptureByAttr::Unknown},
+      {"__global__", LifetimeCaptureByAttr::Global},
+      {"__unknown__", LifetimeCaptureByAttr::Unknown}};
   int Idx = 0;
   if (HasImplicitThisParam) {
     NameIdxMapping["this"] = 0;
@@ -4493,7 +4504,7 @@ void 
Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
     for (const ParmVarDecl *PVD : FD->parameters())
       if (PVD->getName() == Reserved)
         Diag(PVD->getLocation(), diag::err_capture_by_param_uses_reserved_name)
-            << (PVD->getName() == "unknown");
+            << PVD->getName();
   };
   for (auto *CapturedBy : Attrs) {
     const auto &Entities = CapturedBy->getArgIdents();
@@ -4509,7 +4520,8 @@ void 
Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
               << Entities[I] << Loc;
         continue;
       }
-      if (Name == "unknown" || Name == "global")
+      if (Name == "unknown" || Name == "global" || Name == "__unknown__" ||
+          Name == "__global__")
         DisallowReservedParams(Name);
       CapturedBy->setParamIdx(I, It->second);
     }
diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp 
b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
index 2877d8d6cd5f9..bfd87490cf7b7 100644
--- a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
@@ -161,8 +161,8 @@ void test() {
 // Capture by Global and Unknown.
 // ****************************************************************************
 namespace capture_by_global_unknown {
-void captureByGlobal(std::string_view s 
[[clang::lifetime_capture_by(global)]]);
-void captureByUnknown(std::string_view s 
[[clang::lifetime_capture_by(unknown)]]);
+void captureByGlobal(std::string_view s 
[[clang::lifetime_capture_by(__global__)]]);
+void captureByUnknown(std::string_view s 
[[clang::lifetime_capture_by(__unknown__)]]);
 
 std::string_view getLifetimeBoundView(const std::string& s 
[[clang::lifetimebound]]);
 
diff --git a/clang/test/SemaCXX/attr-lifetime-capture-by.cpp 
b/clang/test/SemaCXX/attr-lifetime-capture-by.cpp
index 8606592c6b771..68299192bf8aa 100644
--- a/clang/test/SemaCXX/attr-lifetime-capture-by.cpp
+++ b/clang/test/SemaCXX/attr-lifetime-capture-by.cpp
@@ -13,16 +13,18 @@ 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 &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 int &test_memory_leak[[clang::lifetime_capture_by(x1,x2, x3, x4, x5, 
x6, x7, x8, x9)]],
+                                                x7)]], // expected-error 
{{'lifetime_capture_by' argument references itself}}
+    const int &x8 [[clang::lifetime_capture_by(global)]], // expected-warning 
{{'lifetime_capture_by(global)' is deprecated; use 
'lifetime_capture_by(__global__)' instead}}
+    const int &x9 [[clang::lifetime_capture_by(unknown)]], // expected-warning 
{{'lifetime_capture_by(unknown)' is deprecated; use 
'lifetime_capture_by(__unknown__)' instead}}
+    const int &x10 [[clang::lifetime_capture_by(__global__)]],
+    const int &x11 [[clang::lifetime_capture_by(__unknown__)]],
+    const int &test_memory_leak[[clang::lifetime_capture_by(x1,x2, x3, x4, x5, 
x6, x7, x8, x9, x10, x11)]],
     const S& u
   )
 {
@@ -30,9 +32,13 @@ void nonMember(
 }
 
 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)]]);
+                        const int& s [[clang::lifetime_capture_by(unknown)]]); 
// expected-warning {{'lifetime_capture_by(unknown)' is deprecated; use 
'lifetime_capture_by(__unknown__)' instead}}
 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)]]);
+                       const int& s [[clang::lifetime_capture_by(global)]]); 
// expected-warning {{'lifetime_capture_by(global)' is deprecated; use 
'lifetime_capture_by(__global__)' instead}}
+void unknown_param_name_new(const int& unknown,
+                            const int& s 
[[clang::lifetime_capture_by(__unknown__)]]);
+void global_param_name_new(const int& global,
+                           const int& s 
[[clang::lifetime_capture_by(__global__)]]);
 struct T {
   void member(
     const int &x [[clang::lifetime_capture_by(s)]],
@@ -40,7 +46,7 @@ struct T {
     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)]])
+    const int &u [[clang::lifetime_capture_by(global, unknown, __global__, 
__unknown__, x, s)]]) // expected-warning 2 {{deprecated}}
   {
     s.captureInt(x);
   }

>From aeded69e5ecf76c4527a202d016ad9eadffb9cc8 Mon Sep 17 00:00:00 2001
From: NeKon69 <[email protected]>
Date: Wed, 13 May 2026 11:53:27 +0300
Subject: [PATCH 2/4] implement a draft with different spellings for the same
 attribute

---
 clang/include/clang/Basic/Attr.td             |  9 ++-
 clang/include/clang/Basic/AttrDocs.td         |  9 +--
 .../clang/Basic/DiagnosticSemaKinds.td        |  6 +-
 clang/lib/Sema/CheckExprLifetime.cpp          | 14 ++--
 clang/lib/Sema/SemaAttr.cpp                   |  4 +-
 clang/lib/Sema/SemaChecking.cpp               |  7 +-
 clang/lib/Sema/SemaDeclAttr.cpp               | 68 +++++++++++++------
 .../warn-lifetime-analysis-capture-by.cpp     | 22 +++---
 .../test/SemaCXX/attr-lifetime-capture-by.cpp | 32 ++++-----
 9 files changed, 99 insertions(+), 72 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 70b5773f95b08..f0cde6a359601 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2134,9 +2134,14 @@ def LifetimeBound : DeclOrTypeAttr {
 }
 
 def LifetimeCaptureBy : DeclOrTypeAttr {
-  let Spellings = [Clang<"lifetime_capture_by", 0>];
+  let Spellings = [Clang<"lifetime_capture_by", 0>,
+                   Clang<"lifetime_capture_by_this", 0>,
+                   Clang<"lifetime_capture_by_global", 0>,
+                   Clang<"lifetime_capture_by_unknown", 0>];
   let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;
-  let Args = [VariadicParamOrParamIdxArgument<"Params">];
+  let Args = [VariadicParamOrParamIdxArgument<"Params">,
+              DefaultBoolArgument<"IsStandaloneSpecial", /*default=*/0,
+                                  /*fake=*/1>];
   let Documentation = [LifetimeCaptureByDocs];
   let AdditionalMembers = [{
 private:
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 2884a7a9359f4..4b45f413054f3 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -4643,18 +4643,15 @@ The capturing entity ``X`` can be one of the following:
 
   Note: When applied to a constructor parameter, 
`[[clang::lifetime_capture_by(this)]]` is just an alias of 
`[[clang::lifetimebound]]`.
 
-- ``__global__``, ``__unknown__``.
+- `global`, `unknown`.
 
   .. code-block:: c++
 
     std::set<std::string_view> s;
-    void addToSet(std::string_view a 
[[clang::lifetime_capture_by(__global__)]]) {
+    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 older spellings ``global`` and ``unknown`` are deprecated, but remain
-  accepted for compatibility.
+    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:
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7964006f5ce0b..754019a8e7d41 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3558,14 +3558,16 @@ 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_this_attr_without_implicit_this : Error<
+  "'lifetime_capture_by_this' attribute requires an implicit object 
parameter">;
 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__'">;
+  "; 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 '%0' while using 'lifetime_capture_by(%0)'">;
 def warn_deprecated_capture_by_special_entity : Warning<
-  "'lifetime_capture_by(%0)' is deprecated; use 'lifetime_capture_by(%1)' 
instead">,
+  "'lifetime_capture_by(%0)' is deprecated; use '%1' instead">,
   InGroup<DeprecatedAttributes>;
 
 def err_init_method_bad_return_type : Error<
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index 4e050e9bf6045..7a256e33b88f5 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -502,12 +502,14 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
     if (CheckCoroCall ||
         CanonCallee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
       VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg);
-    else if (const auto *CaptureAttr =
-                 
CanonCallee->getParamDecl(I)->getAttr<LifetimeCaptureByAttr>();
-             CaptureAttr && isa<CXXConstructorDecl>(CanonCallee) &&
-             llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
-               return ArgIdx == LifetimeCaptureByAttr::This;
-             }))
+    else if (isa<CXXConstructorDecl>(CanonCallee) &&
+             llvm::any_of(CanonCallee->getParamDecl(I)
+                              ->specific_attrs<LifetimeCaptureByAttr>(),
+                          [](const LifetimeCaptureByAttr *CaptureAttr) {
+                            return llvm::is_contained(
+                                CaptureAttr->params(),
+                                LifetimeCaptureByAttr::This);
+                          }))
       // `lifetime_capture_by(this)` in a class constructor has the same
       // semantics as `lifetimebound`:
       //
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index ffd546138008a..8f5617cda1e5e 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -332,8 +332,8 @@ void Sema::inferLifetimeCaptureByAttribute(FunctionDecl 
*FD) {
       if (PVD->getType()->isReferenceType() &&
           lifetimes::isGslPointerType(PVD->getType().getNonReferenceType())) {
         int CaptureByThis[] = {LifetimeCaptureByAttr::This};
-        PVD->addAttr(
-            LifetimeCaptureByAttr::CreateImplicit(Context, CaptureByThis, 1));
+        PVD->addAttr(LifetimeCaptureByAttr::CreateImplicit(
+            Context, CaptureByThis, 1, /*IsStandaloneSpecial=*/false));
       }
     }
   };
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 4706fa5d3cde0..b7ddfc34dac55 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4230,6 +4230,8 @@ void Sema::checkLifetimeCaptureBy(FunctionDecl *FD, bool 
IsMemberFunction,
 
     Expr *Captured = const_cast<Expr *>(GetArgAt(ArgIdx));
     for (int CapturingParamIdx : Attr->params()) {
+      if (CapturingParamIdx == LifetimeCaptureByAttr::Invalid)
+        continue;
       // lifetime_capture_by(this) case is handled in the lifetimebound expr
       // initialization codepath.
       if (CapturingParamIdx == LifetimeCaptureByAttr::This &&
@@ -4242,8 +4244,9 @@ void Sema::checkLifetimeCaptureBy(FunctionDecl *FD, bool 
IsMemberFunction,
     }
   };
   for (unsigned I = 0; I < FD->getNumParams(); ++I)
-    HandleCaptureByAttr(FD->getParamDecl(I)->getAttr<LifetimeCaptureByAttr>(),
-                        I + IsMemberFunction);
+    for (const auto *A :
+         FD->getParamDecl(I)->specific_attrs<LifetimeCaptureByAttr>())
+      HandleCaptureByAttr(A, I + IsMemberFunction);
   // Check when the implicit object param is captured.
   if (IsMemberFunction) {
     TypeSourceInfo *TSI = FD->getTypeSourceInfo();
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 9785c381c7ff6..44148f39fdbec 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4404,17 +4404,43 @@ static void handleCallbackAttr(Sema &S, Decl *D, const 
ParsedAttr &AL) {
 
 LifetimeCaptureByAttr *Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL,
                                                         StringRef ParamName) {
+  StringRef AttrName = AL.getAttrName()->getName();
+  StringRef SpecialEntity;
+  if (AttrName == "lifetime_capture_by_this")
+    SpecialEntity = "this";
+  else if (AttrName == "lifetime_capture_by_global")
+    SpecialEntity = "global";
+  else if (AttrName == "lifetime_capture_by_unknown")
+    SpecialEntity = "unknown";
+  bool IsStandaloneSpecial = !SpecialEntity.empty();
+
+  if (IsStandaloneSpecial && AL.getNumArgs() != 0) {
+    Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 0;
+    return nullptr;
+  }
+
   // Atleast one capture by is required.
-  if (AL.getNumArgs() == 0) {
+  if (!IsStandaloneSpecial && AL.getNumArgs() == 0) {
     Diag(AL.getLoc(), diag::err_capture_by_attribute_no_entity)
         << AL.getRange();
     return nullptr;
   }
-  unsigned N = AL.getNumArgs();
+  unsigned N = IsStandaloneSpecial ? 1 : AL.getNumArgs();
   auto ParamIdents =
       MutableArrayRef<IdentifierInfo *>(new (Context) IdentifierInfo *[N], N);
   auto ParamLocs =
       MutableArrayRef<SourceLocation>(new (Context) SourceLocation[N], N);
+  if (IsStandaloneSpecial) {
+    ParamIdents[0] = &Context.Idents.get(SpecialEntity);
+    ParamLocs[0] = AL.getRange().getEnd();
+    SmallVector<int> FakeParamIndices(N, LifetimeCaptureByAttr::Invalid);
+    auto *CapturedBy =
+        LifetimeCaptureByAttr::Create(Context, FakeParamIndices.data(), N,
+                                      IsStandaloneSpecial, AL);
+    CapturedBy->setArgs(ParamIdents, ParamLocs);
+    return CapturedBy;
+  }
+
   bool IsValid = true;
   for (unsigned I = 0; I < N; ++I) {
     if (AL.isArgExpr(I)) {
@@ -4428,13 +4454,15 @@ LifetimeCaptureByAttr 
*Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL,
     IdentifierLoc *IdLoc = AL.getArgAsIdent(I);
     StringRef Name = IdLoc->getIdentifierInfo()->getName();
     StringRef Replacement;
-    if (Name == "global")
-      Replacement = "__global__";
+    if (Name == "this")
+      Replacement = "lifetime_capture_by_this";
+    else if (Name == "global")
+      Replacement = "lifetime_capture_by_global";
     else if (Name == "unknown")
-      Replacement = "__unknown__";
+      Replacement = "lifetime_capture_by_unknown";
     if (!Replacement.empty())
       Diag(IdLoc->getLoc(), diag::warn_deprecated_capture_by_special_entity)
-          << Name << Replacement;
+          << Name << Replacement << IdLoc->getLoc();
     if (IdLoc->getIdentifierInfo()->getName() == ParamName) {
       Diag(IdLoc->getLoc(), diag::err_capture_by_references_itself)
           << IdLoc->getLoc();
@@ -4448,19 +4476,14 @@ LifetimeCaptureByAttr 
*Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL,
     return nullptr;
   SmallVector<int> FakeParamIndices(N, LifetimeCaptureByAttr::Invalid);
   auto *CapturedBy =
-      LifetimeCaptureByAttr::Create(Context, FakeParamIndices.data(), N, AL);
+      LifetimeCaptureByAttr::Create(Context, FakeParamIndices.data(), N,
+                                    IsStandaloneSpecial, AL);
   CapturedBy->setArgs(ParamIdents, 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());
@@ -4472,7 +4495,7 @@ void 
Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
   bool HasImplicitThisParam = hasImplicitObjectParameter(FD);
   SmallVector<LifetimeCaptureByAttr *, 1> Attrs;
   for (ParmVarDecl *PVD : FD->parameters())
-    if (auto *A = PVD->getAttr<LifetimeCaptureByAttr>())
+    for (auto *A : PVD->specific_attrs<LifetimeCaptureByAttr>())
       Attrs.push_back(A);
   if (HasImplicitThisParam) {
     TypeSourceInfo *TSI = FD->getTypeSourceInfo();
@@ -4490,9 +4513,7 @@ void 
Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
     return;
   llvm::StringMap<int> NameIdxMapping = {
       {"global", LifetimeCaptureByAttr::Global},
-      {"unknown", LifetimeCaptureByAttr::Unknown},
-      {"__global__", LifetimeCaptureByAttr::Global},
-      {"__unknown__", LifetimeCaptureByAttr::Unknown}};
+      {"unknown", LifetimeCaptureByAttr::Unknown}};
   int Idx = 0;
   if (HasImplicitThisParam) {
     NameIdxMapping["this"] = 0;
@@ -4513,15 +4534,18 @@ void 
Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
       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
+        if (!HasImplicitThisParam && Name == "this") {
+          unsigned DiagID = CapturedBy->getIsStandaloneSpecial()
+                                ? 
diag::err_capture_by_this_attr_without_implicit_this
+                                : 
diag::err_capture_by_implicit_this_not_available;
+          Diag(Loc, DiagID) << Loc;
+        } else
           Diag(Loc, diag::err_capture_by_attribute_argument_unknown)
               << Entities[I] << Loc;
         continue;
       }
-      if (Name == "unknown" || Name == "global" || Name == "__unknown__" ||
-          Name == "__global__")
+      if ((Name == "unknown" || Name == "global") &&
+          !CapturedBy->getIsStandaloneSpecial())
         DisallowReservedParams(Name);
       CapturedBy->setParamIdx(I, It->second);
     }
diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp 
b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
index bfd87490cf7b7..285f50d61fa1d 100644
--- a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
@@ -145,7 +145,7 @@ void use() {
 
 namespace temporary_capturing_object {
 struct S {
-  void add(const int& x [[clang::lifetime_capture_by(this)]]);
+  void add(const int& x [[clang::lifetime_capture_by_this]]);
 };
 
 void test() {
@@ -161,8 +161,8 @@ void test() {
 // Capture by Global and Unknown.
 // ****************************************************************************
 namespace capture_by_global_unknown {
-void captureByGlobal(std::string_view s 
[[clang::lifetime_capture_by(__global__)]]);
-void captureByUnknown(std::string_view s 
[[clang::lifetime_capture_by(__unknown__)]]);
+void captureByGlobal(std::string_view s [[clang::lifetime_capture_by_global]]);
+void captureByUnknown(std::string_view s 
[[clang::lifetime_capture_by_unknown]]);
 
 std::string_view getLifetimeBoundView(const std::string& s 
[[clang::lifetimebound]]);
 
@@ -188,8 +188,8 @@ void use() {
 // ****************************************************************************
 namespace capture_by_this {
 struct S {
-  void captureInt(const int& x [[clang::lifetime_capture_by(this)]]);
-  void captureView(std::string_view sv [[clang::lifetime_capture_by(this)]]);
+  void captureInt(const int& x [[clang::lifetime_capture_by_this]]);
+  void captureView(std::string_view sv [[clang::lifetime_capture_by_this]]);
 };
 std::string_view getLifetimeBoundView(const std::string& s 
[[clang::lifetimebound]]);
 std::string_view getNotLifetimeBoundView(const std::string& s);
@@ -248,8 +248,8 @@ void useCaptureDefaultArg() {
 namespace containers_no_distinction {
 template<class T>
 struct MySet {
-  void insert(T&& t [[clang::lifetime_capture_by(this)]]);
-  void insert(const T& t [[clang::lifetime_capture_by(this)]]);
+  void insert(T&& t [[clang::lifetime_capture_by_this]]);
+  void insert(const T& t [[clang::lifetime_capture_by_this]]);
 };
 void user_defined_containers() {
   MySet<int> set_of_int;
@@ -269,8 +269,8 @@ template<> struct IsPointerLikeTypeImpl<std::string_view> : 
std::true_type {};
 template<typename T> concept IsPointerLikeType = std::is_pointer<T>::value || 
IsPointerLikeTypeImpl<T>::value;
 
 template<class T> struct MyVector {
-  void push_back(T&& t [[clang::lifetime_capture_by(this)]]) requires 
IsPointerLikeType<T>;
-  void push_back(const T& t [[clang::lifetime_capture_by(this)]]) requires 
IsPointerLikeType<T>;
+  void push_back(T&& t [[clang::lifetime_capture_by_this]]) requires 
IsPointerLikeType<T>;
+  void push_back(const T& t [[clang::lifetime_capture_by_this]]) requires 
IsPointerLikeType<T>;
 
   void push_back(T&& t) requires (!IsPointerLikeType<T>);
   void push_back(const T& t) requires (!IsPointerLikeType<T>);
@@ -428,13 +428,13 @@ void use() {
 
 namespace on_constructor {
 struct T {
-  T(const int& t [[clang::lifetime_capture_by(this)]]);
+  T(const int& t [[clang::lifetime_capture_by_this]]);
 };
 struct T2 {
   T2(const int& t [[clang::lifetime_capture_by(x)]], int& x);
 };
 struct T3 {
-  T3(const T& t [[clang::lifetime_capture_by(this)]]);
+  T3(const T& t [[clang::lifetime_capture_by_this]]);
 };
 
 int foo(const T& t);
diff --git a/clang/test/SemaCXX/attr-lifetime-capture-by.cpp 
b/clang/test/SemaCXX/attr-lifetime-capture-by.cpp
index 68299192bf8aa..d31fa4503b644 100644
--- a/clang/test/SemaCXX/attr-lifetime-capture-by.cpp
+++ b/clang/test/SemaCXX/attr-lifetime-capture-by.cpp
@@ -2,7 +2,7 @@
 
 struct S {
   const int *x;
-  void captureInt(const int&x [[clang::lifetime_capture_by(this)]]) { this->x 
= &x; }
+  void captureInt(const int&x [[clang::lifetime_capture_by_this]]) { this->x = 
&x; }
 };
 
 ///////////////////////////
@@ -13,18 +13,16 @@ 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 &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_this' attribute requires an implicit object parameter}}
     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)]], // expected-warning 
{{'lifetime_capture_by(global)' is deprecated; use 
'lifetime_capture_by(__global__)' instead}}
-    const int &x9 [[clang::lifetime_capture_by(unknown)]], // expected-warning 
{{'lifetime_capture_by(unknown)' is deprecated; use 
'lifetime_capture_by(__unknown__)' instead}}
-    const int &x10 [[clang::lifetime_capture_by(__global__)]],
-    const int &x11 [[clang::lifetime_capture_by(__unknown__)]],
-    const int &test_memory_leak[[clang::lifetime_capture_by(x1,x2, x3, x4, x5, 
x6, x7, x8, x9, x10, x11)]],
+    const int &x8 [[clang::lifetime_capture_by(global)]], // expected-warning 
{{'lifetime_capture_by(global)' is deprecated; use 'lifetime_capture_by_global' 
instead}}
+    const int &x9 [[clang::lifetime_capture_by(unknown)]], // expected-warning 
{{'lifetime_capture_by(unknown)' is deprecated; use 
'lifetime_capture_by_unknown' instead}}
+    const int &test_memory_leak[[clang::lifetime_capture_by(x1,x2, x3, x4, x5, 
x6, x7, x8, x9)]],
     const S& u
   )
 {
@@ -32,25 +30,21 @@ void nonMember(
 }
 
 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)]]); 
// expected-warning {{'lifetime_capture_by(unknown)' is deprecated; use 
'lifetime_capture_by(__unknown__)' instead}}
+                        const int& s [[clang::lifetime_capture_by(unknown)]]); 
// expected-warning {{'lifetime_capture_by(unknown)' is deprecated; use 
'lifetime_capture_by_unknown' instead}}
 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)]]); 
// expected-warning {{'lifetime_capture_by(global)' is deprecated; use 
'lifetime_capture_by(__global__)' instead}}
-void unknown_param_name_new(const int& unknown,
-                            const int& s 
[[clang::lifetime_capture_by(__unknown__)]]);
-void global_param_name_new(const int& global,
-                           const int& s 
[[clang::lifetime_capture_by(__global__)]]);
+                       const int& s [[clang::lifetime_capture_by(global)]]); 
// expected-warning {{'lifetime_capture_by(global)' is deprecated; use 
'lifetime_capture_by_global' instead}}
 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, __global__, 
__unknown__, x, s)]]) // expected-warning 2 {{deprecated}}
+    const int &z [[clang::lifetime_capture_by(x, y), 
clang::lifetime_capture_by_this]],
+    const int &u [[clang::lifetime_capture_by(global, unknown, x, s)]]) // 
expected-warning 2 {{deprecated}}
   {
     s.captureInt(x);
   }
 
   void explicit_this1(this T& self, const int &x 
[[clang::lifetime_capture_by(self)]]);
-  void explicit_this2(this T& self, const int &x 
[[clang::lifetime_capture_by(this)]]); // expected-error {{argument references 
unavailable implicit 'this'}}
+  void explicit_this2(this T& self, const int &x 
[[clang::lifetime_capture_by(this)]]); // expected-warning 
{{'lifetime_capture_by(this)' is deprecated; use 'lifetime_capture_by_this' 
instead}} expected-error {{argument references unavailable implicit 'this'}}
 };

>From 26ae9d538924d24e9b2c6c2be3ebba92afe4d991 Mon Sep 17 00:00:00 2001
From: NeKon69 <[email protected]>
Date: Wed, 13 May 2026 11:57:00 +0300
Subject: [PATCH 3/4] clang-format

---
 clang/lib/Sema/SemaDeclAttr.cpp | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 44148f39fdbec..e95004177e762 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4434,9 +4434,8 @@ LifetimeCaptureByAttr 
*Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL,
     ParamIdents[0] = &Context.Idents.get(SpecialEntity);
     ParamLocs[0] = AL.getRange().getEnd();
     SmallVector<int> FakeParamIndices(N, LifetimeCaptureByAttr::Invalid);
-    auto *CapturedBy =
-        LifetimeCaptureByAttr::Create(Context, FakeParamIndices.data(), N,
-                                      IsStandaloneSpecial, AL);
+    auto *CapturedBy = LifetimeCaptureByAttr::Create(
+        Context, FakeParamIndices.data(), N, IsStandaloneSpecial, AL);
     CapturedBy->setArgs(ParamIdents, ParamLocs);
     return CapturedBy;
   }
@@ -4475,9 +4474,8 @@ LifetimeCaptureByAttr 
*Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL,
   if (!IsValid)
     return nullptr;
   SmallVector<int> FakeParamIndices(N, LifetimeCaptureByAttr::Invalid);
-  auto *CapturedBy =
-      LifetimeCaptureByAttr::Create(Context, FakeParamIndices.data(), N,
-                                    IsStandaloneSpecial, AL);
+  auto *CapturedBy = LifetimeCaptureByAttr::Create(
+      Context, FakeParamIndices.data(), N, IsStandaloneSpecial, AL);
   CapturedBy->setArgs(ParamIdents, ParamLocs);
   return CapturedBy;
 }
@@ -4535,9 +4533,10 @@ void 
Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
       if (It == NameIdxMapping.end()) {
         auto Loc = CapturedBy->getArgLocs()[I];
         if (!HasImplicitThisParam && Name == "this") {
-          unsigned DiagID = CapturedBy->getIsStandaloneSpecial()
-                                ? 
diag::err_capture_by_this_attr_without_implicit_this
-                                : 
diag::err_capture_by_implicit_this_not_available;
+          unsigned DiagID =
+              CapturedBy->getIsStandaloneSpecial()
+                  ? diag::err_capture_by_this_attr_without_implicit_this
+                  : diag::err_capture_by_implicit_this_not_available;
           Diag(Loc, DiagID) << Loc;
         } else
           Diag(Loc, diag::err_capture_by_attribute_argument_unknown)

>From 78f59904114e70e0f3011d19d410f9a0d7eb740f Mon Sep 17 00:00:00 2001
From: NeKon69 <[email protected]>
Date: Wed, 13 May 2026 16:53:29 +0300
Subject: [PATCH 4/4] add accessors

---
 clang/include/clang/Basic/Attr.td             | 11 ++--
 .../clang/Basic/DiagnosticSemaKinds.td        |  2 -
 clang/lib/Sema/SemaAttr.cpp                   |  4 +-
 clang/lib/Sema/SemaDeclAttr.cpp               | 50 +++++++++++--------
 .../test/SemaCXX/attr-lifetime-capture-by.cpp |  1 +
 5 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index f0cde6a359601..8baeb6709d6cd 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2139,9 +2139,14 @@ def LifetimeCaptureBy : DeclOrTypeAttr {
                    Clang<"lifetime_capture_by_global", 0>,
                    Clang<"lifetime_capture_by_unknown", 0>];
   let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;
-  let Args = [VariadicParamOrParamIdxArgument<"Params">,
-              DefaultBoolArgument<"IsStandaloneSpecial", /*default=*/0,
-                                  /*fake=*/1>];
+  let Args = [VariadicParamOrParamIdxArgument<"Params">];
+  let Accessors = [Accessor<"isThis", [Clang<"lifetime_capture_by_this", 0>]>,
+                   Accessor<"isGlobal", [Clang<"lifetime_capture_by_global", 
0>]>,
+                   Accessor<"isUnknown", [Clang<"lifetime_capture_by_unknown", 
0>]>,
+                   Accessor<"isStandaloneSpecial",
+                            [Clang<"lifetime_capture_by_this", 0>,
+                             Clang<"lifetime_capture_by_global", 0>,
+                             Clang<"lifetime_capture_by_unknown", 0>]>];
   let Documentation = [LifetimeCaptureByDocs];
   let AdditionalMembers = [{
 private:
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 754019a8e7d41..cb26337a37cc1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3552,8 +3552,6 @@ def err_callback_callee_is_variadic : Error<
 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<
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 8f5617cda1e5e..ffd546138008a 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -332,8 +332,8 @@ void Sema::inferLifetimeCaptureByAttribute(FunctionDecl 
*FD) {
       if (PVD->getType()->isReferenceType() &&
           lifetimes::isGslPointerType(PVD->getType().getNonReferenceType())) {
         int CaptureByThis[] = {LifetimeCaptureByAttr::This};
-        PVD->addAttr(LifetimeCaptureByAttr::CreateImplicit(
-            Context, CaptureByThis, 1, /*IsStandaloneSpecial=*/false));
+        PVD->addAttr(
+            LifetimeCaptureByAttr::CreateImplicit(Context, CaptureByThis, 1));
       }
     }
   };
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index e95004177e762..fe75f2e8735b0 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4402,40 +4402,48 @@ static void handleCallbackAttr(Sema &S, Decl *D, const 
ParsedAttr &AL) {
       S.Context, AL, EncodingIndices.data(), EncodingIndices.size()));
 }
 
+static StringRef getLifetimeCaptureBySpecialEntity(const ParsedAttr &AL) {
+  switch (AL.getSemanticSpelling()) {
+  case LifetimeCaptureByAttr::GNU_lifetime_capture_by_this:
+  case LifetimeCaptureByAttr::CXX11_clang_lifetime_capture_by_this:
+    return "this";
+  case LifetimeCaptureByAttr::GNU_lifetime_capture_by_global:
+  case LifetimeCaptureByAttr::CXX11_clang_lifetime_capture_by_global:
+    return "global";
+  case LifetimeCaptureByAttr::GNU_lifetime_capture_by_unknown:
+  case LifetimeCaptureByAttr::CXX11_clang_lifetime_capture_by_unknown:
+    return "unknown";
+  default:
+    return "";
+  }
+}
+
 LifetimeCaptureByAttr *Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL,
                                                         StringRef ParamName) {
-  StringRef AttrName = AL.getAttrName()->getName();
-  StringRef SpecialEntity;
-  if (AttrName == "lifetime_capture_by_this")
-    SpecialEntity = "this";
-  else if (AttrName == "lifetime_capture_by_global")
-    SpecialEntity = "global";
-  else if (AttrName == "lifetime_capture_by_unknown")
-    SpecialEntity = "unknown";
-  bool IsStandaloneSpecial = !SpecialEntity.empty();
-
-  if (IsStandaloneSpecial && AL.getNumArgs() != 0) {
+  StringRef SpecialEntity = getLifetimeCaptureBySpecialEntity(AL);
+
+  if (!SpecialEntity.empty() && AL.getNumArgs() != 0) {
     Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 0;
     return nullptr;
   }
 
   // Atleast one capture by is required.
-  if (!IsStandaloneSpecial && AL.getNumArgs() == 0) {
+  if (SpecialEntity.empty() && AL.getNumArgs() == 0) {
     Diag(AL.getLoc(), diag::err_capture_by_attribute_no_entity)
         << AL.getRange();
     return nullptr;
   }
-  unsigned N = IsStandaloneSpecial ? 1 : AL.getNumArgs();
+  unsigned N = SpecialEntity.empty() ? AL.getNumArgs() : 1;
   auto ParamIdents =
       MutableArrayRef<IdentifierInfo *>(new (Context) IdentifierInfo *[N], N);
   auto ParamLocs =
       MutableArrayRef<SourceLocation>(new (Context) SourceLocation[N], N);
-  if (IsStandaloneSpecial) {
+  if (!SpecialEntity.empty()) {
     ParamIdents[0] = &Context.Idents.get(SpecialEntity);
     ParamLocs[0] = AL.getRange().getEnd();
-    SmallVector<int> FakeParamIndices(N, LifetimeCaptureByAttr::Invalid);
-    auto *CapturedBy = LifetimeCaptureByAttr::Create(
-        Context, FakeParamIndices.data(), N, IsStandaloneSpecial, AL);
+    int FakeParamIndices[] = {LifetimeCaptureByAttr::Invalid};
+    auto *CapturedBy =
+        LifetimeCaptureByAttr::Create(Context, FakeParamIndices, 1, AL);
     CapturedBy->setArgs(ParamIdents, ParamLocs);
     return CapturedBy;
   }
@@ -4474,8 +4482,8 @@ LifetimeCaptureByAttr 
*Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL,
   if (!IsValid)
     return nullptr;
   SmallVector<int> FakeParamIndices(N, LifetimeCaptureByAttr::Invalid);
-  auto *CapturedBy = LifetimeCaptureByAttr::Create(
-      Context, FakeParamIndices.data(), N, IsStandaloneSpecial, AL);
+  auto *CapturedBy =
+      LifetimeCaptureByAttr::Create(Context, FakeParamIndices.data(), N, AL);
   CapturedBy->setArgs(ParamIdents, ParamLocs);
   return CapturedBy;
 }
@@ -4534,7 +4542,7 @@ void 
Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
         auto Loc = CapturedBy->getArgLocs()[I];
         if (!HasImplicitThisParam && Name == "this") {
           unsigned DiagID =
-              CapturedBy->getIsStandaloneSpecial()
+              CapturedBy->isStandaloneSpecial()
                   ? diag::err_capture_by_this_attr_without_implicit_this
                   : diag::err_capture_by_implicit_this_not_available;
           Diag(Loc, DiagID) << Loc;
@@ -4544,7 +4552,7 @@ void 
Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
         continue;
       }
       if ((Name == "unknown" || Name == "global") &&
-          !CapturedBy->getIsStandaloneSpecial())
+          !CapturedBy->isStandaloneSpecial())
         DisallowReservedParams(Name);
       CapturedBy->setParamIdx(I, It->second);
     }
diff --git a/clang/test/SemaCXX/attr-lifetime-capture-by.cpp 
b/clang/test/SemaCXX/attr-lifetime-capture-by.cpp
index d31fa4503b644..4e699c07740be 100644
--- a/clang/test/SemaCXX/attr-lifetime-capture-by.cpp
+++ b/clang/test/SemaCXX/attr-lifetime-capture-by.cpp
@@ -22,6 +22,7 @@ void nonMember(
                                                 x7)]], // expected-error 
{{'lifetime_capture_by' argument references itself}}
     const int &x8 [[clang::lifetime_capture_by(global)]], // expected-warning 
{{'lifetime_capture_by(global)' is deprecated; use 'lifetime_capture_by_global' 
instead}}
     const int &x9 [[clang::lifetime_capture_by(unknown)]], // expected-warning 
{{'lifetime_capture_by(unknown)' is deprecated; use 
'lifetime_capture_by_unknown' instead}}
+    const int &x10 [[clang::lifetime_capture_by_global(s)]], // expected-error 
{{'clang::lifetime_capture_by_global' attribute takes no arguments}}
     const int &test_memory_leak[[clang::lifetime_capture_by(x1,x2, x3, x4, x5, 
x6, x7, x8, x9)]],
     const S& u
   )

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to