Skip to content

Commit 8e505ae

Browse files
authored
Merge pull request #1833 from compnerd/swift_newtype-preapply
Sema: add support for `__attribute__((__swift_newtype__))`
2 parents f648eb9 + 05dbe9c commit 8e505ae

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
@@ -3781,6 +3781,36 @@ must be a simple or qualified identifier.
37813781
}];
37823782
}
37833783

3784+
def SwiftNewTypeDocs : Documentation {
3785+
let Category = SwiftDocs;
3786+
let Heading = "swift_newtype";
3787+
let Content = [{
3788+
The ``swift_newtype`` attribute indicates that the typedef to which the
3789+
attribute appertains is imported as a new Swift type of the typedef's name.
3790+
Previously, the attribute was spelt ``swift_wrapper``. While the behaviour of
3791+
the attribute is identical with either spelling, ``swift_wrapper`` is
3792+
deprecated, only exists for compatibility purposes, and should not be used in
3793+
new code.
3794+
3795+
* ``swift_newtype(struct)`` means that a Swift struct will be created for this
3796+
typedef.
3797+
3798+
* ``swift_newtype(enum)`` means that a Swift enum will be created for this
3799+
ypedef.
3800+
3801+
.. code-block:: c
3802+
3803+
// Import UIFontTextStyle as an enum type, with enumerated values being
3804+
// constants.
3805+
typedef NSString * UIFontTextStyle __attribute__((__swift_newtype__(enum)));
3806+
3807+
// Import UIFontDescriptorFeatureKey as a structure type, with enumerated
3808+
// values being members of the type structure.
3809+
typedef NSString * UIFontDescriptorFeatureKey __attribute__((__swift_newtype__(struct)));
3810+
3811+
}];
3812+
}
3813+
37843814
def OMPDeclareSimdDocs : Documentation {
37853815
let Category = DocCatFunction;
37863816
let Heading = "#pragma omp declare simd";
@@ -3816,17 +3846,6 @@ where clause is one of the following:
38163846
}];
38173847
}
38183848

3819-
def SwiftNewtypeDocs : Documentation {
3820-
let Category = SwiftDocs;
3821-
let Heading = "swift_newtype";
3822-
let Content = [{
3823-
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.
3824-
* ``swift_newtype(struct)`` means that a Swift struct will be created for this typedef.
3825-
* ``swift_newtype(enum)`` means that a Swift enum will be created for this typedef.
3826-
}];
3827-
}
3828-
3829-
38303849
def OMPDeclareTargetDocs : Documentation {
38313850
let Category = DocCatFunction;
38323851
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
@@ -5582,43 +5582,6 @@ static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) {
55825582
D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT));
55835583
}
55845584

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

5968+
static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) {
5969+
// Make sure that there is an identifier as the annotation's single argument.
5970+
if (!checkAttributeNumArgs(S, AL, 1))
5971+
return;
5972+
5973+
if (!AL.isArgIdent(0)) {
5974+
S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
5975+
<< AL << AANT_ArgumentIdentifier;
5976+
return;
5977+
}
5978+
5979+
SwiftNewTypeAttr::NewtypeKind Kind;
5980+
IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
5981+
if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
5982+
S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
5983+
return;
5984+
}
5985+
5986+
if (!isa<TypedefNameDecl>(D)) {
5987+
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
5988+
<< AL << "typedefs";
5989+
return;
5990+
}
5991+
5992+
D->addAttr(::new (S.Context) SwiftNewTypeAttr(S.Context, AL, Kind));
5993+
}
5994+
60055995
//===----------------------------------------------------------------------===//
60065996
// Microsoft specific attribute handlers.
60075997
//===----------------------------------------------------------------------===//
@@ -7927,15 +7917,15 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
79277917
case ParsedAttr::AT_SwiftBridgedTypedef:
79287918
handleSimpleAttribute<SwiftBridgedTypedefAttr>(S, D, AL);
79297919
break;
7930-
case ParsedAttr::AT_SwiftNewtype:
7931-
handleSwiftNewtypeAttr(S, D, AL);
7932-
break;
79337920
case ParsedAttr::AT_SwiftError:
79347921
handleSwiftError(S, D, AL);
79357922
break;
79367923
case ParsedAttr::AT_SwiftName:
79377924
handleSwiftName(S, D, AL);
79387925
break;
7926+
case ParsedAttr::AT_SwiftNewType:
7927+
handleSwiftNewType(S, D, AL);
7928+
break;
79397929
case ParsedAttr::AT_SwiftObjCMembers:
79407930
handleSimpleAttribute<SwiftObjCMembersAttr>(S, D, AL);
79417931
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)