Skip to content

Sema: add support for __attribute__((__swift_newtype__)) #1833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2144,15 +2144,6 @@ def Regparm : TypeAttr {
let ASTNode = 0;
}

def SwiftNewtype : InheritableAttr {
let Spellings = [GNU<"swift_newtype">, GNU<"swift_wrapper">];
let Subjects = SubjectList<[TypedefName], ErrorDiag, "ExpectedType">;
let Args = [EnumArgument<"NewtypeKind", "NewtypeKind",
["struct", "enum"],
["NK_Struct", "NK_Enum"]>];
let Documentation = [SwiftNewtypeDocs];
}

def SwiftPrivate : InheritableAttr {
let Spellings = [GCC<"swift_private">];
let Documentation = [Undocumented];
Expand Down Expand Up @@ -2236,6 +2227,15 @@ def SwiftName : InheritableAttr {
let Documentation = [SwiftNameDocs];
}

def SwiftNewType : InheritableAttr {
let Spellings = [GNU<"swift_newtype">, GNU<"swift_wrapper">];
let Args = [EnumArgument<"NewtypeKind", "NewtypeKind",
["struct", "enum"], ["NK_Struct", "NK_Enum"]>];
let Subjects = SubjectList<[TypedefName], ErrorDiag>;
let Documentation = [SwiftNewTypeDocs];
let HasCustomParsing = 1;
}

def NoDeref : TypeAttr {
let Spellings = [Clang<"noderef">];
let Documentation = [NoDerefDocs];
Expand Down
41 changes: 30 additions & 11 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -3755,6 +3755,36 @@ must be a simple or qualified identifier.
}];
}

def SwiftNewTypeDocs : Documentation {
let Category = SwiftDocs;
let Heading = "swift_newtype";
let Content = [{
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.
Previously, the attribute was spelt ``swift_wrapper``. While the behaviour of
the attribute is identical with either spelling, ``swift_wrapper`` is
deprecated, only exists for compatibility purposes, and should not be used in
new code.

* ``swift_newtype(struct)`` means that a Swift struct will be created for this
typedef.

* ``swift_newtype(enum)`` means that a Swift enum will be created for this
ypedef.

.. code-block:: c

// Import UIFontTextStyle as an enum type, with enumerated values being
// constants.
typedef NSString * UIFontTextStyle __attribute__((__swift_newtype__(enum)));

// Import UIFontDescriptorFeatureKey as a structure type, with enumerated
// values being members of the type structure.
typedef NSString * UIFontDescriptorFeatureKey __attribute__((__swift_newtype__(struct)));

}];
}

def OMPDeclareSimdDocs : Documentation {
let Category = DocCatFunction;
let Heading = "#pragma omp declare simd";
Expand Down Expand Up @@ -3790,17 +3820,6 @@ where clause is one of the following:
}];
}

def SwiftNewtypeDocs : Documentation {
let Category = SwiftDocs;
let Heading = "swift_newtype";
let Content = [{
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.
* ``swift_newtype(struct)`` means that a Swift struct will be created for this typedef.
* ``swift_newtype(enum)`` means that a Swift enum will be created for this typedef.
}];
}


def OMPDeclareTargetDocs : Documentation {
let Category = DocCatFunction;
let Heading = "#pragma omp declare target";
Expand Down
16 changes: 8 additions & 8 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -2804,6 +2804,14 @@ class Parser : public CodeCompletionHandler {
SourceLocation ScopeLoc,
ParsedAttr::Syntax Syntax);

void ParseSwiftNewTypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
SourceLocation *EndLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
ParsedAttr::Syntax Syntax);

void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
Expand All @@ -2812,14 +2820,6 @@ class Parser : public CodeCompletionHandler {
SourceLocation ScopeLoc,
ParsedAttr::Syntax Syntax);

void ParseSwiftNewtypeAttribute(IdentifierInfo &SwiftNewtype,
SourceLocation SwiftNewtypeLoc,
ParsedAttributes &attrs,
SourceLocation *endLoc,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
ParsedAttr::Syntax Syntax);

void
ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc, ParsedAttributes &Attrs,
Expand Down
87 changes: 51 additions & 36 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,38 +299,6 @@ IdentifierLoc *Parser::ParseIdentifierLoc() {
return IL;
}

void Parser::ParseSwiftNewtypeAttribute(
IdentifierInfo &SwiftNewtype, SourceLocation SwiftNewtypeLoc,
ParsedAttributes &attrs, SourceLocation *endLoc, IdentifierInfo *ScopeName,
SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {

BalancedDelimiterTracker Parens(*this, tok::l_paren);
Parens.consumeOpen();

if (Tok.is(tok::r_paren)) {
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
Parens.consumeClose();
return;
}
if (Tok.isNot(tok::kw_struct) && Tok.isNot(tok::kw_enum)) {
Diag(Tok.getLocation(), diag::warn_attribute_type_not_supported)
<< &SwiftNewtype << Tok.getIdentifierInfo();
if (!isTokenSpecial())
ConsumeToken();
Parens.consumeClose();
return;
}
auto IL = IdentifierLoc::create(Actions.Context, Tok.getLocation(),
Tok.getIdentifierInfo());
ConsumeToken();
auto identLoc = ArgsUnion(IL);

attrs.addNew(&SwiftNewtype,
SourceRange(SwiftNewtypeLoc, Parens.getCloseLocation()),
ScopeName, ScopeLoc, &identLoc, 1, Syntax);
Parens.consumeClose();
}

void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
Expand Down Expand Up @@ -485,14 +453,14 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
return;
} else if (AttrKind == ParsedAttr::AT_SwiftNewType) {
ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
ScopeLoc, Syntax);
return;
} else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) {
ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
return;
} else if (AttrKind == ParsedAttr::AT_SwiftNewtype) {
ParseSwiftNewtypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
return;
} else if (attributeIsTypeArgAttr(*AttrName)) {
ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
ScopeLoc, Syntax);
Expand Down Expand Up @@ -543,6 +511,10 @@ unsigned Parser::ParseClangAttributeArgs(
ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
break;
case ParsedAttr::AT_SwiftNewType:
ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
ScopeLoc, Syntax);
break;
case ParsedAttr::AT_TypeTagForDatatype:
ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
Expand Down Expand Up @@ -1446,6 +1418,49 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
Syntax);
}


void Parser::ParseSwiftNewTypeAttribute(
IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
BalancedDelimiterTracker T(*this, tok::l_paren);

// Opening '('
if (T.consumeOpen()) {
Diag(Tok, diag::err_expected) << tok::l_paren;
return;
}

if (Tok.is(tok::r_paren)) {
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
T.consumeClose();
return;
}
if (Tok.isNot(tok::kw_struct) && Tok.isNot(tok::kw_enum)) {
Diag(Tok, diag::warn_attribute_type_not_supported)
<< &AttrName << Tok.getIdentifierInfo();
if (!isTokenSpecial())
ConsumeToken();
T.consumeClose();
return;
}

auto *SwiftType = IdentifierLoc::create(Actions.Context, Tok.getLocation(),
Tok.getIdentifierInfo());
ConsumeToken();

// Closing ')'
if (T.consumeClose())
return;
if (EndLoc)
*EndLoc = T.getCloseLocation();

ArgsUnion Args[] = {SwiftType};
Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, T.getCloseLocation()),
ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax);
}


void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
Expand Down
14 changes: 7 additions & 7 deletions clang/lib/Sema/SemaAPINotes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -680,27 +680,27 @@ static void ProcessAPINotes(Sema &S, TypedefNameDecl *D,
using SwiftWrapperKind = api_notes::SwiftWrapperKind;

if (auto swiftWrapper = info.SwiftWrapper) {
handleAPINotedAttribute<SwiftNewtypeAttr>(S, D,
handleAPINotedAttribute<SwiftNewTypeAttr>(S, D,
*swiftWrapper != SwiftWrapperKind::None, metadata,
[&] {
SwiftNewtypeAttr::NewtypeKind kind;
SwiftNewTypeAttr::NewtypeKind kind;
switch (*swiftWrapper) {
case SwiftWrapperKind::None:
llvm_unreachable("Shouldn't build an attribute");

case SwiftWrapperKind::Struct:
kind = SwiftNewtypeAttr::NK_Struct;
kind = SwiftNewTypeAttr::NK_Struct;
break;

case SwiftWrapperKind::Enum:
kind = SwiftNewtypeAttr::NK_Enum;
kind = SwiftNewTypeAttr::NK_Enum;
break;
}
AttributeCommonInfo syntaxInfo{SourceRange(),
AttributeCommonInfo::AT_SwiftNewtype,
AttributeCommonInfo::AT_SwiftNewType,
AttributeCommonInfo::AS_GNU,
SwiftNewtypeAttr::GNU_swift_wrapper};
return new (S.Context) SwiftNewtypeAttr(S.Context, syntaxInfo, kind);
SwiftNewTypeAttr::GNU_swift_wrapper};
return new (S.Context) SwiftNewTypeAttr(S.Context, syntaxInfo, kind);
});
}

Expand Down
70 changes: 30 additions & 40 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5578,43 +5578,6 @@ static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT));
}

static void handleSwiftNewtypeAttr(Sema &S, Decl *D, const ParsedAttr &Attr) {
// Make sure that there is an identifier as the annotation's single
// argument.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
<< Attr.getAttrName() << 1;
Attr.setInvalid();
return;
}
if (!Attr.isArgIdent(0)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
<< Attr.getAttrName() << AANT_ArgumentIdentifier;
Attr.setInvalid();
return;
}

IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
SwiftNewtypeAttr::NewtypeKind Kind;
if (II->isStr("struct"))
Kind = SwiftNewtypeAttr::NK_Struct;
else if (II->isStr("enum"))
Kind = SwiftNewtypeAttr::NK_Enum;
else {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
<< Attr.getAttrName() << II;
Attr.setInvalid();
return;
}

if (!isa<TypedefNameDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_swift_newtype_attribute_non_typedef);
return;
}

D->addAttr(::new (S.Context) SwiftNewtypeAttr(S.Context, Attr, Kind));
}

static bool isErrorParameter(Sema &S, QualType QT) {
const auto *PT = QT->getAs<PointerType>();
if (!PT)
Expand Down Expand Up @@ -5998,6 +5961,33 @@ static void handleSwiftName(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (S.Context) SwiftNameAttr(S.Context, AL, Name));
}

static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) {
// Make sure that there is an identifier as the annotation's single argument.
if (!checkAttributeNumArgs(S, AL, 1))
return;

if (!AL.isArgIdent(0)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
<< AL << AANT_ArgumentIdentifier;
return;
}

SwiftNewTypeAttr::NewtypeKind Kind;
IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
return;
}

if (!isa<TypedefNameDecl>(D)) {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
<< AL << "typedefs";
return;
}

D->addAttr(::new (S.Context) SwiftNewTypeAttr(S.Context, AL, Kind));
}

//===----------------------------------------------------------------------===//
// Microsoft specific attribute handlers.
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -7923,15 +7913,15 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_SwiftBridgedTypedef:
handleSimpleAttribute<SwiftBridgedTypedefAttr>(S, D, AL);
break;
case ParsedAttr::AT_SwiftNewtype:
handleSwiftNewtypeAttr(S, D, AL);
break;
case ParsedAttr::AT_SwiftError:
handleSwiftError(S, D, AL);
break;
case ParsedAttr::AT_SwiftName:
handleSwiftName(S, D, AL);
break;
case ParsedAttr::AT_SwiftNewType:
handleSwiftNewType(S, D, AL);
break;
case ParsedAttr::AT_SwiftObjCMembers:
handleSimpleAttribute<SwiftObjCMembersAttr>(S, D, AL);
break;
Expand Down
19 changes: 19 additions & 0 deletions clang/test/AST/attr-swift_newtype.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %clang_cc1 -ast-dump %s | FileCheck %s

typedef int T1 __attribute__((__swift_newtype__(struct)));
typedef int T2 __attribute__((__swift_newtype__(enum)));

typedef int T3 __attribute__((__swift_wrapper__(struct)));
typedef int T4 __attribute__((__swift_wrapper__(enum)));

typedef int T5;
typedef int T5 __attribute__((__swift_wrapper__(struct)));
typedef int T5;
// CHECK-LABEL: TypedefDecl {{.+}} T5 'int'
// CHECK-NEXT: BuiltinType {{.+}} 'int'
// CHECK-NEXT: TypedefDecl {{.+}} T5 'int'
// CHECK-NEXT: BuiltinType {{.+}} 'int'
// CHECK-NEXT: SwiftNewTypeAttr {{.+}} NK_Struct
// CHECK-NEXT: TypedefDecl {{.+}} T5 'int'
// CHECK-NEXT: BuiltinType {{.+}} 'int'
// CHECK-NEXT: SwiftNewTypeAttr {{.+}} NK_Struct
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
// CHECK-NEXT: SwiftError (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: SwiftErrorResult (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: SwiftIndirectResult (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: SwiftNewtype (SubjectMatchRule_type_alias)
// CHECK-NEXT: SwiftNewType (SubjectMatchRule_type_alias)
// CHECK-NEXT: SwiftObjCMembers (SubjectMatchRule_objc_interface)
// CHECK-NEXT: TLSModel (SubjectMatchRule_variable_is_thread_local)
// CHECK-NEXT: Target (SubjectMatchRule_function)
Expand Down
Loading