diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 8555bd35174760..3beef7b892437f 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2149,6 +2149,12 @@ def Regparm : TypeAttr { let ASTNode = 0; } +def SwiftAttr : InheritableAttr { + let Spellings = [GNU<"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 index 1781543cc4f327..673c9553c83dce 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3628,6 +3628,19 @@ Swift. }]; } +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. It can be used on any declaration +in Clang. 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 index d31d18eac47409..e0aa6d1f119c41 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5607,6 +5607,16 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, 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 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, 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 index 00000000000000..3cd51b81e349f2 --- /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 index 00000000000000..4ff434d179725d --- /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