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 @@ -2149,6 +2149,12 @@ let ASTNode = 0; } +def SwiftAttr : InheritableAttr { + let Spellings = [Clang<"swift_attr">]; + let Args = [StringArgument<"Attribute">]; + let Documentation = [SwiftAttrDocs]; +} + def SwiftBridge : InheritableAttr { let Spellings = [GNU<"swift_bridge">]; let Args = [StringArgument<"SwiftType">]; 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 @@ -3628,6 +3628,18 @@ }]; } +def SwiftAttrDocs : Documentation { + let Category = SwiftDocs; + let Heading = "swift_attr"; + let Content = [{ +The ``swift_attr`` provides a Swift-specific annotation for the declaration +to which the attribute appertains to. This kind of annotation is ignored by +clang as it doesn't have any semantic meaning in languages supported by clang. +The Swift compiler can interpret these annotations according to its own rules +when importing C or Objective-C declarations. +}]; +} + def SwiftBridgeDocs : Documentation { let Category = SwiftDocs; let Heading = "swift_bridge"; 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 @@ -5607,6 +5607,16 @@ D->addAttr(::new (S.Context) ObjCPreciseLifetimeAttr(S.Context, AL)); } +static void handleSwiftAttrAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // Make sure that there is a string literal as the annotation's single + // argument. + StringRef Str; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) + return; + + D->addAttr(::new (S.Context) SwiftAttrAttr(S.Context, AL, Str)); +} + static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) { // Make sure that there is a string literal as the annotation's single // argument. @@ -7941,6 +7951,9 @@ break; // Swift attributes. + case ParsedAttr::AT_SwiftAttr: + handleSwiftAttrAttr(S, D, AL); + break; case ParsedAttr::AT_SwiftBridge: handleSwiftBridge(S, D, AL); break; diff --git a/clang/test/AST/attr-swift_attr.m b/clang/test/AST/attr-swift_attr.m new file mode 100644 --- /dev/null +++ b/clang/test/AST/attr-swift_attr.m @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s + +__attribute__((swift_attr("@actor"))) +@interface View +@end + +// CHECK: InterfaceDecl {{.*}} View +// CHECK-NEXT: SwiftAttrAttr {{.*}} "@actor" diff --git a/clang/test/SemaObjC/validate-attr-swift_attr.m b/clang/test/SemaObjC/validate-attr-swift_attr.m new file mode 100644 --- /dev/null +++ b/clang/test/SemaObjC/validate-attr-swift_attr.m @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s + +// expected-error@+1 {{'swift_attr' attribute takes one argument}} +__attribute__((swift_attr)) +@interface I +@end + +// expected-error@+1 {{'swift_attr' attribute requires a string}} +__attribute__((swift_attr(1))) +@interface J +@end