================
@@ -4469,6 +4469,52 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, 
NamedDecl *&OldD, Scope *S,
   return true;
 }
 
+/// Check if a function has a lifetimebound attribute on its function type
+/// (which represents the implicit 'this' parameter for methods).
+/// Returns the attribute if found, nullptr otherwise.
+static const LifetimeBoundAttr *
+getLifetimeBoundAttrFromType(const TypeSourceInfo *TSI) {
+  if (!TSI)
+    return nullptr;
+
+  for (TypeLoc TL = TSI->getTypeLoc();;) {
+    auto ATL = TL.getAsAdjusted<AttributedTypeLoc>();
+    if (!ATL)
+      break;
+    if (auto *LBAttr = ATL.getAttrAs<LifetimeBoundAttr>())
+      return LBAttr;
+    TL = ATL.getModifiedLoc();
+  }
+  return nullptr;
+}
+
+/// Merge lifetimebound attribute on function type (implicit 'this')
+/// from Old to New method declaration.
+static void mergeLifetimeBoundAttrOnMethod(Sema &S, CXXMethodDecl *New,
+                                           const CXXMethodDecl *Old) {
+  const TypeSourceInfo *OldTSI = Old->getTypeSourceInfo();
+  const TypeSourceInfo *NewTSI = New->getTypeSourceInfo();
+
+  if (!OldTSI || !NewTSI)
+    return;
+
+  const LifetimeBoundAttr *OldLBAttr = getLifetimeBoundAttrFromType(OldTSI);
+  const LifetimeBoundAttr *NewLBAttr = getLifetimeBoundAttrFromType(NewTSI);
+
+  // If Old has lifetimebound but New doesn't, add it to New
+  if (OldLBAttr && !NewLBAttr) {
+    QualType NewMethodType = New->getType();
+    QualType AttributedType =
+        S.Context.getAttributedType(OldLBAttr, NewMethodType, NewMethodType);
+    TypeLocBuilder TLB;
+    TLB.pushFullCopy(NewTSI->getTypeLoc());
+    AttributedTypeLoc TyLoc = TLB.push<AttributedTypeLoc>(AttributedType);
+    TyLoc.setAttr(OldLBAttr);
+    New->setType(AttributedType);
+    New->setTypeSourceInfo(TLB.getTypeSourceInfo(S.Context, AttributedType));
+  }
+}
----------------
usx95 wrote:

As far as merging declarations are concerned, it looks like this is the way 
that it has been done historically. Merging old decl into the new decl. E.g. 
docs for `MergeCompatibleFunctionDecls`

```
  /// Completes the merge of two function declarations that are
  /// known to be compatible.
  ///
  /// This routine handles the merging of attributes and other
  /// properties of function declarations from the old declaration to
  /// the new declaration, once we know that New is in fact a
  /// redeclaration of Old.
  ///
  /// \returns false
  bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
                                    Scope *S, bool MergeTypeWithOld);
```

IIUC `mostRecentDecl` is the default decl that is retrieved:

```

/// Represents a function declaration or definition.
///
/// Since a given function can be declared several times in a program,
/// there may be several FunctionDecls that correspond to that
/// function. Only one of those FunctionDecls will be found when
/// traversing the list of declarations in the context of the
/// FunctionDecl (e.g., the translation unit); this FunctionDecl
/// contains all of the information known about the function. Other,
/// previous declarations of the function are available via the
/// getPreviousDecl() chain.
class FunctionDecl : public DeclaratorDecl,
                     public DeclContext,
                     public Redeclarable<FunctionDecl> {
```

 I would be inclined to keep the same behaviour here and always use the 
mostRecentDecl (which should also be the default) to read the annotations.

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

Reply via email to