Commit 03dcd57e authored by Alex Lorenz's avatar Alex Lorenz
Browse files

[clang] add a new `swift_attr` attribute

The swift_attr attribute is a generic annotation attribute that's not used by clang,
but is used by the Swift compiler. The Swift compiler can use these annotations to provide
various syntactic and semantic sugars for the imported Objective-C API declarations.

Differential Revision: https://reviews.llvm.org/D92354
parent 99f79cbf
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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">];
+13 −0
Original line number Diff line number Diff line
@@ -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";
+13 −0
Original line number Diff line number Diff line
@@ -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;
+8 −0
Original line number Diff line number Diff line
// RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s

__attribute__((swift_attr("@actor")))
@interface View
@end

// CHECK: InterfaceDecl {{.*}} View
// CHECK-NEXT: SwiftAttrAttr {{.*}} "@actor"
+11 −0
Original line number Diff line number Diff line
// 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