================
@@ -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