diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2414,6 +2414,14 @@ let SimpleHandler = 1; } +def CloneAttrsFrom : InheritableAttr { + let Spellings = [GNU<"clone_attrs_from">]; + let Args = [DeclArgument]; + let Subjects = SubjectList<[Tag, TypedefName], + ErrorDiag>; + let Documentation = [CloneAttrsFromDocs]; +} + def NoDeref : TypeAttr { let Spellings = [Clang<"noderef">]; let Documentation = [NoDerefDocs]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4186,6 +4186,15 @@ }]; } +def CloneAttrsFromDocs : Documentation { + let Category = DocCatDecl; + let Heading = "clone_attrs_from"; + let Content = [{ +The ``clone_attrs_from`` attribute indicates that the declaration to which the +attribute appertains contains the same attributes as another named decl. + }]; +} + def OMPDeclareSimdDocs : Documentation { let Category = DocCatFunction; let Heading = "#pragma omp declare simd"; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4091,6 +4091,12 @@ "'sentinel' parameter 1 less than zero">; def err_attribute_sentinel_not_zero_or_one : Error< "'sentinel' parameter 2 not 0 or 1">; +def err_attribute_clone_attrs_from_arg_not_named_decl : Error< + "'clone_attrs_from' argument %select{|%1 |%1 }0is not a %select{||single }0named decl">; +def warn_clone_attrs_from_ext : Warning< + "Clang does not allow the 'clone_attrs_from' attribute argument to be anything other " + "than a simple identifier">, + InGroup; def warn_cleanup_ext : Warning< "GCC does not allow the 'cleanup' attribute argument to be anything other " "than a simple identifier">, diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3300,6 +3300,37 @@ D->addAttr(::new (S.Context) MinVectorWidthAttr(S.Context, AL, VecWidth)); } +static void handleCloneAttrsFrom(Sema &S, Decl *D, const ParsedAttr &AL) { + + if (AL.getNumArgs() != 1) { + S.Diag(D->getLocation(), diag::err_attribute_clone_attrs_from_arg_not_named_decl) << 0; + return; + } + + Expr *E = AL.getArgAsExpr(0); + SourceLocation Loc = E->getExprLoc(); + + auto *DRE = dyn_cast(E); + if (!DRE) { + S.Diag(Loc, diag::err_attribute_clone_attrs_from_arg_not_named_decl) << 0; + return; + } + + if (DRE->hasQualifier()) + S.Diag(Loc, diag::warn_clone_attrs_from_ext); + + NamedDecl *ND = dyn_cast(DRE->getDecl()); + if (!ND) { + DeclarationNameInfo NI = DRE->getNameInfo(); + S.Diag(Loc, diag::err_attribute_clone_attrs_from_arg_not_named_decl) + << 1 << NI.getName(); + return; + } + + ND->addAttr(::new (S.Context) CloneAttrsFromAttr(S.Context, AL, ND)); + D->addAttr(::new (S.Context) CloneAttrsFromAttr(S.Context, AL, ND)); +} + static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) { Expr *E = AL.getArgAsExpr(0); SourceLocation Loc = E->getExprLoc(); @@ -8486,6 +8517,10 @@ handleSwiftAsyncError(S, D, AL); break; + case ParsedAttr::AT_CloneAttrsFrom: + handleCloneAttrsFrom(S, D, AL); + break; + // XRay attributes. case ParsedAttr::AT_XRayLogArgs: handleXRayLogArgsAttr(S, D, AL); diff --git a/clang/test/AST/attr-swift_bridge.m b/clang/test/AST/attr-swift_bridge.m --- a/clang/test/AST/attr-swift_bridge.m +++ b/clang/test/AST/attr-swift_bridge.m @@ -1,11 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s -struct __attribute__((__swift_bridge__("BridgedS"))) S; -// CHECK: RecordDecl {{.*}} struct S -// CHECK: SwiftBridgeAttr {{.*}} "BridgedS" +int XXXX; -struct S { -}; - -// CHECK: RecordDecl {{.*}} struct S definition -// CHECK: SwiftBridgeAttr {{.*}} Inherited "BridgedS" +struct __attribute__((__clone_attrs_from__(XXXX))) S; \ No newline at end of file