Skip to content

Commit 05dbe9c

Browse files
committed
Sema: add support for __attribute__((__swift_newtype__))
Add the `swift_newtype` attribute which allows a type definition to be imported into Swift as a new type. The imported type must be either an enumerated type (enum) or an object type (struct). This is based on the work of the original changes in 8afaf3a Pre-apply upstream patch for `swift_newtype`.
1 parent a100794 commit 05dbe9c

File tree

10 files changed

+168
-144
lines changed

10 files changed

+168
-144
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2144,15 +2144,6 @@ def Regparm : TypeAttr {
21442144
let ASTNode = 0;
21452145
}
21462146

2147-
def SwiftNewtype : InheritableAttr {
2148-
let Spellings = [GNU<"swift_newtype">, GNU<"swift_wrapper">];
2149-
let Subjects = SubjectList<[TypedefName], ErrorDiag, "ExpectedType">;
2150-
let Args = [EnumArgument<"NewtypeKind", "NewtypeKind",
2151-
["struct", "enum"],
2152-
["NK_Struct", "NK_Enum"]>];
2153-
let Documentation = [SwiftNewtypeDocs];
2154-
}
2155-
21562147
def SwiftPrivate : InheritableAttr {
21572148
let Spellings = [GCC<"swift_private">];
21582149
let Documentation = [Undocumented];
@@ -2236,6 +2227,15 @@ def SwiftName : InheritableAttr {
22362227
let Documentation = [SwiftNameDocs];
22372228
}
22382229

2230+
def SwiftNewType : InheritableAttr {
2231+
let Spellings = [GNU<"swift_newtype">, GNU<"swift_wrapper">];
2232+
let Args = [EnumArgument<"NewtypeKind", "NewtypeKind",
2233+
["struct", "enum"], ["NK_Struct", "NK_Enum"]>];
2234+
let Subjects = SubjectList<[TypedefName], ErrorDiag>;
2235+
let Documentation = [SwiftNewTypeDocs];
2236+
let HasCustomParsing = 1;
2237+
}
2238+
22392239
def NoDeref : TypeAttr {
22402240
let Spellings = [Clang<"noderef">];
22412241
let Documentation = [NoDerefDocs];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3755,6 +3755,36 @@ must be a simple or qualified identifier.
37553755
}];
37563756
}
37573757

3758+
def SwiftNewTypeDocs : Documentation {
3759+
let Category = SwiftDocs;
3760+
let Heading = "swift_newtype";
3761+
let Content = [{
3762+
The ``swift_newtype`` attribute indicates that the typedef to which the
3763+
attribute appertains is imported as a new Swift type of the typedef's name.
3764+
Previously, the attribute was spelt ``swift_wrapper``. While the behaviour of
3765+
the attribute is identical with either spelling, ``swift_wrapper`` is
3766+
deprecated, only exists for compatibility purposes, and should not be used in
3767+
new code.
3768+
3769+
* ``swift_newtype(struct)`` means that a Swift struct will be created for this
3770+
typedef.
3771+
3772+
* ``swift_newtype(enum)`` means that a Swift enum will be created for this
3773+
ypedef.
3774+
3775+
.. code-block:: c
3776+
3777+
// Import UIFontTextStyle as an enum type, with enumerated values being
3778+
// constants.
3779+
typedef NSString * UIFontTextStyle __attribute__((__swift_newtype__(enum)));
3780+
3781+
// Import UIFontDescriptorFeatureKey as a structure type, with enumerated
3782+
// values being members of the type structure.
3783+
typedef NSString * UIFontDescriptorFeatureKey __attribute__((__swift_newtype__(struct)));
3784+
3785+
}];
3786+
}
3787+
37583788
def OMPDeclareSimdDocs : Documentation {
37593789
let Category = DocCatFunction;
37603790
let Heading = "#pragma omp declare simd";
@@ -3790,17 +3820,6 @@ where clause is one of the following:
37903820
}];
37913821
}
37923822

3793-
def SwiftNewtypeDocs : Documentation {
3794-
let Category = SwiftDocs;
3795-
let Heading = "swift_newtype";
3796-
let Content = [{
3797-
The ``swift_newtype`` attribute indicates that the typedef to which the attribute appertains is imported as a new Swift type of the typedef's name.
3798-
* ``swift_newtype(struct)`` means that a Swift struct will be created for this typedef.
3799-
* ``swift_newtype(enum)`` means that a Swift enum will be created for this typedef.
3800-
}];
3801-
}
3802-
3803-
38043823
def OMPDeclareTargetDocs : Documentation {
38053824
let Category = DocCatFunction;
38063825
let Heading = "#pragma omp declare target";

clang/include/clang/Parse/Parser.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,6 +2804,14 @@ class Parser : public CodeCompletionHandler {
28042804
SourceLocation ScopeLoc,
28052805
ParsedAttr::Syntax Syntax);
28062806

2807+
void ParseSwiftNewTypeAttribute(IdentifierInfo &AttrName,
2808+
SourceLocation AttrNameLoc,
2809+
ParsedAttributes &Attrs,
2810+
SourceLocation *EndLoc,
2811+
IdentifierInfo *ScopeName,
2812+
SourceLocation ScopeLoc,
2813+
ParsedAttr::Syntax Syntax);
2814+
28072815
void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
28082816
SourceLocation AttrNameLoc,
28092817
ParsedAttributes &Attrs,
@@ -2812,14 +2820,6 @@ class Parser : public CodeCompletionHandler {
28122820
SourceLocation ScopeLoc,
28132821
ParsedAttr::Syntax Syntax);
28142822

2815-
void ParseSwiftNewtypeAttribute(IdentifierInfo &SwiftNewtype,
2816-
SourceLocation SwiftNewtypeLoc,
2817-
ParsedAttributes &attrs,
2818-
SourceLocation *endLoc,
2819-
IdentifierInfo *ScopeName,
2820-
SourceLocation ScopeLoc,
2821-
ParsedAttr::Syntax Syntax);
2822-
28232823
void
28242824
ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
28252825
SourceLocation AttrNameLoc, ParsedAttributes &Attrs,

clang/lib/Parse/ParseDecl.cpp

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -299,38 +299,6 @@ IdentifierLoc *Parser::ParseIdentifierLoc() {
299299
return IL;
300300
}
301301

302-
void Parser::ParseSwiftNewtypeAttribute(
303-
IdentifierInfo &SwiftNewtype, SourceLocation SwiftNewtypeLoc,
304-
ParsedAttributes &attrs, SourceLocation *endLoc, IdentifierInfo *ScopeName,
305-
SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
306-
307-
BalancedDelimiterTracker Parens(*this, tok::l_paren);
308-
Parens.consumeOpen();
309-
310-
if (Tok.is(tok::r_paren)) {
311-
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
312-
Parens.consumeClose();
313-
return;
314-
}
315-
if (Tok.isNot(tok::kw_struct) && Tok.isNot(tok::kw_enum)) {
316-
Diag(Tok.getLocation(), diag::warn_attribute_type_not_supported)
317-
<< &SwiftNewtype << Tok.getIdentifierInfo();
318-
if (!isTokenSpecial())
319-
ConsumeToken();
320-
Parens.consumeClose();
321-
return;
322-
}
323-
auto IL = IdentifierLoc::create(Actions.Context, Tok.getLocation(),
324-
Tok.getIdentifierInfo());
325-
ConsumeToken();
326-
auto identLoc = ArgsUnion(IL);
327-
328-
attrs.addNew(&SwiftNewtype,
329-
SourceRange(SwiftNewtypeLoc, Parens.getCloseLocation()),
330-
ScopeName, ScopeLoc, &identLoc, 1, Syntax);
331-
Parens.consumeClose();
332-
}
333-
334302
void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
335303
SourceLocation AttrNameLoc,
336304
ParsedAttributes &Attrs,
@@ -485,14 +453,14 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
485453
ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
486454
ScopeName, ScopeLoc, Syntax);
487455
return;
456+
} else if (AttrKind == ParsedAttr::AT_SwiftNewType) {
457+
ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
458+
ScopeLoc, Syntax);
459+
return;
488460
} else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) {
489461
ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
490462
ScopeName, ScopeLoc, Syntax);
491463
return;
492-
} else if (AttrKind == ParsedAttr::AT_SwiftNewtype) {
493-
ParseSwiftNewtypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
494-
ScopeName, ScopeLoc, Syntax);
495-
return;
496464
} else if (attributeIsTypeArgAttr(*AttrName)) {
497465
ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
498466
ScopeLoc, Syntax);
@@ -543,6 +511,10 @@ unsigned Parser::ParseClangAttributeArgs(
543511
ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
544512
ScopeName, ScopeLoc, Syntax);
545513
break;
514+
case ParsedAttr::AT_SwiftNewType:
515+
ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
516+
ScopeLoc, Syntax);
517+
break;
546518
case ParsedAttr::AT_TypeTagForDatatype:
547519
ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
548520
ScopeName, ScopeLoc, Syntax);
@@ -1446,6 +1418,49 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
14461418
Syntax);
14471419
}
14481420

1421+
1422+
void Parser::ParseSwiftNewTypeAttribute(
1423+
IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
1424+
ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
1425+
SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
1426+
BalancedDelimiterTracker T(*this, tok::l_paren);
1427+
1428+
// Opening '('
1429+
if (T.consumeOpen()) {
1430+
Diag(Tok, diag::err_expected) << tok::l_paren;
1431+
return;
1432+
}
1433+
1434+
if (Tok.is(tok::r_paren)) {
1435+
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
1436+
T.consumeClose();
1437+
return;
1438+
}
1439+
if (Tok.isNot(tok::kw_struct) && Tok.isNot(tok::kw_enum)) {
1440+
Diag(Tok, diag::warn_attribute_type_not_supported)
1441+
<< &AttrName << Tok.getIdentifierInfo();
1442+
if (!isTokenSpecial())
1443+
ConsumeToken();
1444+
T.consumeClose();
1445+
return;
1446+
}
1447+
1448+
auto *SwiftType = IdentifierLoc::create(Actions.Context, Tok.getLocation(),
1449+
Tok.getIdentifierInfo());
1450+
ConsumeToken();
1451+
1452+
// Closing ')'
1453+
if (T.consumeClose())
1454+
return;
1455+
if (EndLoc)
1456+
*EndLoc = T.getCloseLocation();
1457+
1458+
ArgsUnion Args[] = {SwiftType};
1459+
Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, T.getCloseLocation()),
1460+
ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax);
1461+
}
1462+
1463+
14491464
void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
14501465
SourceLocation AttrNameLoc,
14511466
ParsedAttributes &Attrs,

clang/lib/Sema/SemaAPINotes.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -680,27 +680,27 @@ static void ProcessAPINotes(Sema &S, TypedefNameDecl *D,
680680
using SwiftWrapperKind = api_notes::SwiftWrapperKind;
681681

682682
if (auto swiftWrapper = info.SwiftWrapper) {
683-
handleAPINotedAttribute<SwiftNewtypeAttr>(S, D,
683+
handleAPINotedAttribute<SwiftNewTypeAttr>(S, D,
684684
*swiftWrapper != SwiftWrapperKind::None, metadata,
685685
[&] {
686-
SwiftNewtypeAttr::NewtypeKind kind;
686+
SwiftNewTypeAttr::NewtypeKind kind;
687687
switch (*swiftWrapper) {
688688
case SwiftWrapperKind::None:
689689
llvm_unreachable("Shouldn't build an attribute");
690690

691691
case SwiftWrapperKind::Struct:
692-
kind = SwiftNewtypeAttr::NK_Struct;
692+
kind = SwiftNewTypeAttr::NK_Struct;
693693
break;
694694

695695
case SwiftWrapperKind::Enum:
696-
kind = SwiftNewtypeAttr::NK_Enum;
696+
kind = SwiftNewTypeAttr::NK_Enum;
697697
break;
698698
}
699699
AttributeCommonInfo syntaxInfo{SourceRange(),
700-
AttributeCommonInfo::AT_SwiftNewtype,
700+
AttributeCommonInfo::AT_SwiftNewType,
701701
AttributeCommonInfo::AS_GNU,
702-
SwiftNewtypeAttr::GNU_swift_wrapper};
703-
return new (S.Context) SwiftNewtypeAttr(S.Context, syntaxInfo, kind);
702+
SwiftNewTypeAttr::GNU_swift_wrapper};
703+
return new (S.Context) SwiftNewTypeAttr(S.Context, syntaxInfo, kind);
704704
});
705705
}
706706

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5578,43 +5578,6 @@ static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) {
55785578
D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT));
55795579
}
55805580

5581-
static void handleSwiftNewtypeAttr(Sema &S, Decl *D, const ParsedAttr &Attr) {
5582-
// Make sure that there is an identifier as the annotation's single
5583-
// argument.
5584-
if (Attr.getNumArgs() != 1) {
5585-
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
5586-
<< Attr.getAttrName() << 1;
5587-
Attr.setInvalid();
5588-
return;
5589-
}
5590-
if (!Attr.isArgIdent(0)) {
5591-
S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
5592-
<< Attr.getAttrName() << AANT_ArgumentIdentifier;
5593-
Attr.setInvalid();
5594-
return;
5595-
}
5596-
5597-
IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
5598-
SwiftNewtypeAttr::NewtypeKind Kind;
5599-
if (II->isStr("struct"))
5600-
Kind = SwiftNewtypeAttr::NK_Struct;
5601-
else if (II->isStr("enum"))
5602-
Kind = SwiftNewtypeAttr::NK_Enum;
5603-
else {
5604-
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
5605-
<< Attr.getAttrName() << II;
5606-
Attr.setInvalid();
5607-
return;
5608-
}
5609-
5610-
if (!isa<TypedefNameDecl>(D)) {
5611-
S.Diag(Attr.getLoc(), diag::warn_swift_newtype_attribute_non_typedef);
5612-
return;
5613-
}
5614-
5615-
D->addAttr(::new (S.Context) SwiftNewtypeAttr(S.Context, Attr, Kind));
5616-
}
5617-
56185581
static bool isErrorParameter(Sema &S, QualType QT) {
56195582
const auto *PT = QT->getAs<PointerType>();
56205583
if (!PT)
@@ -5998,6 +5961,33 @@ static void handleSwiftName(Sema &S, Decl *D, const ParsedAttr &AL) {
59985961
D->addAttr(::new (S.Context) SwiftNameAttr(S.Context, AL, Name));
59995962
}
60005963

5964+
static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) {
5965+
// Make sure that there is an identifier as the annotation's single argument.
5966+
if (!checkAttributeNumArgs(S, AL, 1))
5967+
return;
5968+
5969+
if (!AL.isArgIdent(0)) {
5970+
S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
5971+
<< AL << AANT_ArgumentIdentifier;
5972+
return;
5973+
}
5974+
5975+
SwiftNewTypeAttr::NewtypeKind Kind;
5976+
IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
5977+
if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
5978+
S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
5979+
return;
5980+
}
5981+
5982+
if (!isa<TypedefNameDecl>(D)) {
5983+
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
5984+
<< AL << "typedefs";
5985+
return;
5986+
}
5987+
5988+
D->addAttr(::new (S.Context) SwiftNewTypeAttr(S.Context, AL, Kind));
5989+
}
5990+
60015991
//===----------------------------------------------------------------------===//
60025992
// Microsoft specific attribute handlers.
60035993
//===----------------------------------------------------------------------===//
@@ -7923,15 +7913,15 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
79237913
case ParsedAttr::AT_SwiftBridgedTypedef:
79247914
handleSimpleAttribute<SwiftBridgedTypedefAttr>(S, D, AL);
79257915
break;
7926-
case ParsedAttr::AT_SwiftNewtype:
7927-
handleSwiftNewtypeAttr(S, D, AL);
7928-
break;
79297916
case ParsedAttr::AT_SwiftError:
79307917
handleSwiftError(S, D, AL);
79317918
break;
79327919
case ParsedAttr::AT_SwiftName:
79337920
handleSwiftName(S, D, AL);
79347921
break;
7922+
case ParsedAttr::AT_SwiftNewType:
7923+
handleSwiftNewType(S, D, AL);
7924+
break;
79357925
case ParsedAttr::AT_SwiftObjCMembers:
79367926
handleSimpleAttribute<SwiftObjCMembersAttr>(S, D, AL);
79377927
break;

clang/test/AST/attr-swift_newtype.m

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -ast-dump %s | FileCheck %s
2+
3+
typedef int T1 __attribute__((__swift_newtype__(struct)));
4+
typedef int T2 __attribute__((__swift_newtype__(enum)));
5+
6+
typedef int T3 __attribute__((__swift_wrapper__(struct)));
7+
typedef int T4 __attribute__((__swift_wrapper__(enum)));
8+
9+
typedef int T5;
10+
typedef int T5 __attribute__((__swift_wrapper__(struct)));
11+
typedef int T5;
12+
// CHECK-LABEL: TypedefDecl {{.+}} T5 'int'
13+
// CHECK-NEXT: BuiltinType {{.+}} 'int'
14+
// CHECK-NEXT: TypedefDecl {{.+}} T5 'int'
15+
// CHECK-NEXT: BuiltinType {{.+}} 'int'
16+
// CHECK-NEXT: SwiftNewTypeAttr {{.+}} NK_Struct
17+
// CHECK-NEXT: TypedefDecl {{.+}} T5 'int'
18+
// CHECK-NEXT: BuiltinType {{.+}} 'int'
19+
// CHECK-NEXT: SwiftNewTypeAttr {{.+}} NK_Struct

clang/test/Misc/pragma-attribute-supported-attributes-list.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
// CHECK-NEXT: SwiftError (SubjectMatchRule_function, SubjectMatchRule_objc_method)
153153
// CHECK-NEXT: SwiftErrorResult (SubjectMatchRule_variable_is_parameter)
154154
// CHECK-NEXT: SwiftIndirectResult (SubjectMatchRule_variable_is_parameter)
155-
// CHECK-NEXT: SwiftNewtype (SubjectMatchRule_type_alias)
155+
// CHECK-NEXT: SwiftNewType (SubjectMatchRule_type_alias)
156156
// CHECK-NEXT: SwiftObjCMembers (SubjectMatchRule_objc_interface)
157157
// CHECK-NEXT: TLSModel (SubjectMatchRule_variable_is_thread_local)
158158
// CHECK-NEXT: Target (SubjectMatchRule_function)

0 commit comments

Comments
 (0)