Skip to content

Commit 0b295a1

Browse files
author
Artem Gindinson
committed
Merge from 'master' to 'sycl-web' (#1)
2 parents 8af8f82 + f5ab5b2 commit 0b295a1

File tree

6 files changed

+259
-0
lines changed

6 files changed

+259
-0
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,6 +2619,17 @@ def Regparm : TypeAttr {
26192619
let ASTNode = 0;
26202620
}
26212621

2622+
def SwiftError : InheritableAttr {
2623+
let Spellings = [GNU<"swift_error">];
2624+
let Args = [
2625+
EnumArgument<"Convention", "ConventionKind",
2626+
["none", "nonnull_error", "null_result", "zero_result", "nonzero_result"],
2627+
["None", "NonNullError", "NullResult", "ZeroResult", "NonZeroResult"]>
2628+
];
2629+
let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
2630+
let Documentation = [SwiftErrorDocs];
2631+
}
2632+
26222633
def NoDeref : TypeAttr {
26232634
let Spellings = [Clang<"noderef">];
26242635
let Documentation = [NoDerefDocs];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3932,6 +3932,53 @@ For example:
39323932
}];
39333933
}
39343934

3935+
def SwiftDocs : DocumentationCategory<"Customizing Swift Import"> {
3936+
let Content = [{
3937+
Clang supports additional attributes for customizing how APIs are imported into
3938+
Swift.
3939+
}];
3940+
}
3941+
3942+
def SwiftErrorDocs : Documentation {
3943+
let Category = SwiftDocs;
3944+
let Heading = "swift_error";
3945+
let Content = [{
3946+
The ``swift_error`` attribute controls whether a particular function (or
3947+
Objective-C method) is imported into Swift as a throwing function, and if so,
3948+
which dynamic convention it uses.
3949+
3950+
All of these conventions except ``none`` require the function to have an error
3951+
parameter. Currently, the error parameter is always the last parameter of type
3952+
``NSError**`` or ``CFErrorRef*``. Swift will remove the error parameter from
3953+
the imported API. When calling the API, Swift will always pass a valid address
3954+
initialized to a null pointer.
3955+
3956+
* ``swift_error(none)`` means that the function should not be imported as
3957+
throwing. The error parameter and result type will be imported normally.
3958+
3959+
* ``swift_error(null_result)`` means that calls to the function should be
3960+
considered to have thrown if they return a null value. The return type must be
3961+
a pointer type, and it will be imported into Swift with a non-optional type.
3962+
This is the default error convention for Objective-C methods that return
3963+
pointers.
3964+
3965+
* ``swift_error(zero_result)`` means that calls to the function should be
3966+
considered to have thrown if they return a zero result. The return type must be
3967+
an integral type. If the return type would have been imported as ``Bool``, it
3968+
is instead imported as ``Void``. This is the default error convention for
3969+
Objective-C methods that return a type that would be imported as ``Bool``.
3970+
3971+
* ``swift_error(nonzero_result)`` means that calls to the function should be
3972+
considered to have thrown if they return a non-zero result. The return type must
3973+
be an integral type. If the return type would have been imported as ``Bool``,
3974+
it is instead imported as ``Void``.
3975+
3976+
* ``swift_error(nonnull_error)`` means that calls to the function should be
3977+
considered to have thrown if they leave a non-null error in the error parameter.
3978+
The return type is left unmodified.
3979+
}];
3980+
}
3981+
39353982
def OMPDeclareSimdDocs : Documentation {
39363983
let Category = DocCatFunction;
39373984
let Heading = "#pragma omp declare simd";

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4015,6 +4015,13 @@ def err_objc_bridged_related_known_method : Error<
40154015
def err_objc_attr_protocol_requires_definition : Error<
40164016
"attribute %0 can only be applied to @protocol definitions, not forward declarations">;
40174017

4018+
def err_attr_swift_error_no_error_parameter : Error<
4019+
"%0 attribute can only be applied to a %select{function|method}1 with an "
4020+
"error parameter">;
4021+
def err_attr_swift_error_return_type : Error<
4022+
"%0 attribute with '%1' convention can only be applied to a "
4023+
"%select{function|method}2 returning %select{an integral type|a pointer}3">;
4024+
40184025
def warn_ignored_objc_externally_retained : Warning<
40194026
"'objc_externally_retained' can only be applied to local variables "
40204027
"%select{of retainable type|with strong ownership}0">,

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6129,6 +6129,102 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
61296129
D->addAttr(::new (S.Context) ObjCPreciseLifetimeAttr(S.Context, AL));
61306130
}
61316131

6132+
static bool isErrorParameter(Sema &S, QualType QT) {
6133+
const auto *PT = QT->getAs<PointerType>();
6134+
if (!PT)
6135+
return false;
6136+
6137+
QualType Pointee = PT->getPointeeType();
6138+
6139+
// Check for NSError**.
6140+
if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>())
6141+
if (const auto *ID = OPT->getInterfaceDecl())
6142+
if (ID->getIdentifier() == S.getNSErrorIdent())
6143+
return true;
6144+
6145+
// Check for CFError**.
6146+
if (const auto *PT = Pointee->getAs<PointerType>())
6147+
if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())
6148+
if (S.isCFError(RT->getDecl()))
6149+
return true;
6150+
6151+
return false;
6152+
}
6153+
6154+
static void handleSwiftError(Sema &S, Decl *D, const ParsedAttr &AL) {
6155+
auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
6156+
for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
6157+
if (isErrorParameter(S, getFunctionOrMethodParamType(D, I)))
6158+
return true;
6159+
}
6160+
6161+
S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)
6162+
<< AL << isa<ObjCMethodDecl>(D);
6163+
return false;
6164+
};
6165+
6166+
auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
6167+
// - C, ObjC, and block pointers are definitely okay.
6168+
// - References are definitely not okay.
6169+
// - nullptr_t is weird, but acceptable.
6170+
QualType RT = getFunctionOrMethodResultType(D);
6171+
if (RT->hasPointerRepresentation() && !RT->isReferenceType())
6172+
return true;
6173+
6174+
S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
6175+
<< AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
6176+
<< /*pointer*/ 1;
6177+
return false;
6178+
};
6179+
6180+
auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
6181+
QualType RT = getFunctionOrMethodResultType(D);
6182+
if (RT->isIntegralType(S.Context))
6183+
return true;
6184+
6185+
S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
6186+
<< AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
6187+
<< /*integral*/ 0;
6188+
return false;
6189+
};
6190+
6191+
if (D->isInvalidDecl())
6192+
return;
6193+
6194+
IdentifierLoc *Loc = AL.getArgAsIdent(0);
6195+
SwiftErrorAttr::ConventionKind Convention;
6196+
if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(),
6197+
Convention)) {
6198+
S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
6199+
<< AL << Loc->Ident;
6200+
return;
6201+
}
6202+
6203+
switch (Convention) {
6204+
case SwiftErrorAttr::None:
6205+
// No additional validation required.
6206+
break;
6207+
6208+
case SwiftErrorAttr::NonNullError:
6209+
if (!hasErrorParameter(S, D, AL))
6210+
return;
6211+
break;
6212+
6213+
case SwiftErrorAttr::NullResult:
6214+
if (!hasErrorParameter(S, D, AL) || !hasPointerResult(S, D, AL))
6215+
return;
6216+
break;
6217+
6218+
case SwiftErrorAttr::NonZeroResult:
6219+
case SwiftErrorAttr::ZeroResult:
6220+
if (!hasErrorParameter(S, D, AL) || !hasIntegerResult(S, D, AL))
6221+
return;
6222+
break;
6223+
}
6224+
6225+
D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention));
6226+
}
6227+
61326228
//===----------------------------------------------------------------------===//
61336229
// Microsoft specific attribute handlers.
61346230
//===----------------------------------------------------------------------===//
@@ -8118,6 +8214,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
81188214
break;
81198215
case ParsedAttr::AT_SYCLIntelPipeIO:
81208216
handleSYCLIntelPipeIOAttr(S, D, AL);
8217+
8218+
// Swift attributes.
8219+
case ParsedAttr::AT_SwiftError:
8220+
handleSwiftError(S, D, AL);
81218221
break;
81228222

81238223
// XRay attributes.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
// CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member)
147147
// CHECK-NEXT: SpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method)
148148
// CHECK-NEXT: SwiftContext (SubjectMatchRule_variable_is_parameter)
149+
// CHECK-NEXT: SwiftError (SubjectMatchRule_function, SubjectMatchRule_objc_method)
149150
// CHECK-NEXT: SwiftErrorResult (SubjectMatchRule_variable_is_parameter)
150151
// CHECK-NEXT: SwiftIndirectResult (SubjectMatchRule_variable_is_parameter)
151152
// CHECK-NEXT: TLSModel (SubjectMatchRule_variable_is_thread_local)
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// RUN: %clang_cc1 -verify -fsyntax-only -fobjc-arc -fblocks %s
2+
3+
@class NSError;
4+
5+
#if __SIZEOF_POINTER__ == 4
6+
typedef unsigned char BOOL;
7+
#else
8+
typedef _Bool BOOL;
9+
#endif
10+
11+
typedef struct __attribute__((__objc_bridge__(NSError))) __CFError *CFErrorRef;
12+
13+
extern int f0(void) __attribute__((__swift_error__));
14+
// expected-error@-1 {{'__swift_error__' attribute takes one argument}}
15+
extern int f1(void) __attribute__((__swift_error__(invalid)));
16+
// expected-warning@-1 {{'__swift_error__' attribute argument not supported: 'invalid'}}
17+
extern int f2(void) __attribute__((__swift_error__(none,zero_result)));
18+
// expected-error@-1 {{use of undeclared identifier 'zero_result'}}
19+
20+
@interface Erroneous
21+
- (BOOL)m0:(NSError **)error __attribute__((__swift_error__(none)));
22+
- (BOOL)m1:(NSError **)error __attribute__((__swift_error__(nonnull_error)));
23+
- (BOOL)m2:(NSError **)error __attribute__((__swift_error__(null_result)));
24+
// expected-error@-1 {{'__swift_error__' attribute with 'null_result' convention can only be applied to a method returning a pointer}}
25+
- (BOOL)m3:(NSError **)error __attribute__((__swift_error__(nonzero_result)));
26+
- (BOOL)m4:(NSError **)error __attribute__((__swift_error__(zero_result)));
27+
28+
- (Undeclared)n0:(NSError **)error __attribute__((__swift_error__(none)));
29+
// expected-error@-1 {{expected a type}}
30+
- (Undeclared)n1:(NSError **)error __attribute__((__swift_error__(nonnull_error)));
31+
// expected-error@-1 {{expected a type}}
32+
- (Undeclared)n2:(NSError **)error __attribute__((__swift_error__(null_result)));
33+
// expected-error@-1 {{expected a type}}
34+
- (Undeclared)n3:(NSError **)error __attribute__((__swift_error__(nonzero_result)));
35+
// expected-error@-1 {{expected a type}}
36+
// FIXME: the follow-on warning should really be suppressed, but apparently
37+
// having an ill-formed return type doesn't mark anything as invalid.
38+
// expected-error@-4 {{can only be applied}}
39+
- (Undeclared)n4:(NSError **)error __attribute__((__swift_error__(zero_result)));
40+
// expected-error@-1 {{expected a type}}
41+
// FIXME: the follow-on warning should really be suppressed, but apparently
42+
// having an ill-formed return type doesn't mark anything as invalid.
43+
// expected-error@-4 {{can only be applied}}
44+
45+
- (instancetype)o0 __attribute__((__swift_error__(none)));
46+
- (instancetype)o1 __attribute__((__swift_error__(nonnull_error)));
47+
// expected-error@-1 {{'__swift_error__' attribute can only be applied to a method with an error parameter}}
48+
- (instancetype)o2 __attribute__((__swift_error__(null_result)));
49+
// expected-error@-1 {{'__swift_error__' attribute can only be applied to a method with an error parameter}}
50+
- (instancetype)o3 __attribute__((__swift_error__(nonzero_result)));
51+
// expected-error@-1 {{'__swift_error__' attribute can only be applied to a method with an error parameter}}
52+
- (instancetype)o4 __attribute__((__swift_error__(zero_result)));
53+
// expected-error@-1 {{'__swift_error__' attribute can only be applied to a method with an error parameter}}
54+
@end
55+
56+
extern BOOL m0(CFErrorRef *) __attribute__((__swift_error__(none)));
57+
extern BOOL m1(CFErrorRef *) __attribute__((__swift_error__(nonnull_error)));
58+
extern BOOL m2(CFErrorRef *) __attribute__((__swift_error__(null_result)));
59+
// expected-error@-1 {{'__swift_error__' attribute with 'null_result' convention can only be applied to a function returning a pointer}}
60+
extern BOOL m3(CFErrorRef *) __attribute__((__swift_error__(nonzero_result)));
61+
extern BOOL m4(CFErrorRef *) __attribute__((__swift_error__(zero_result)));
62+
63+
extern Undeclared n0(CFErrorRef *) __attribute__((__swift_error__(none)));
64+
// expected-error@-1 {{unknown type name 'Undeclared'}}
65+
extern Undeclared n1(CFErrorRef *) __attribute__((__swift_error__(nonnull_error)));
66+
// expected-error@-1 {{unknown type name 'Undeclared'}}
67+
extern Undeclared n2(CFErrorRef *) __attribute__((__swift_error__(null_result)));
68+
// expected-error@-1 {{unknown type name 'Undeclared'}}
69+
extern Undeclared n3(CFErrorRef *) __attribute__((__swift_error__(nonzero_result)));
70+
// expected-error@-1 {{unknown type name 'Undeclared'}}
71+
extern Undeclared n4(CFErrorRef *) __attribute__((__swift_error__(zero_result)));
72+
// expected-error@-1 {{unknown type name 'Undeclared'}}
73+
74+
extern void *o0(CFErrorRef *) __attribute__((__swift_error__(none)));
75+
extern void *o1(CFErrorRef *) __attribute__((__swift_error__(nonnull_error)));
76+
extern void *o2(CFErrorRef *) __attribute__((__swift_error__(null_result)));
77+
extern void *o3(CFErrorRef *) __attribute__((__swift_error__(nonzero_result)));
78+
// expected-error@-1 {{'__swift_error__' attribute with 'nonzero_result' convention can only be applied to a function returning an integral type}}
79+
extern void *o4(CFErrorRef *) __attribute__((__swift_error__(zero_result)));
80+
// expected-error@-1 {{'__swift_error__' attribute with 'zero_result' convention can only be applied to a function returning an integral type}}
81+
82+
extern void *p0(void) __attribute__((__swift_error__(none)));
83+
extern void *p1(void) __attribute__((__swift_error__(nonnull_error)));
84+
// expected-error@-1 {{'__swift_error__' attribute can only be applied to a function with an error parameter}}
85+
extern void *p2(void) __attribute__((__swift_error__(null_result)));
86+
// expected-error@-1 {{'__swift_error__' attribute can only be applied to a function with an error parameter}}
87+
extern void *p3(void) __attribute__((__swift_error__(nonzero_result)));
88+
// expected-error@-1 {{'__swift_error__' attribute can only be applied to a function with an error parameter}}
89+
extern void *p4(void) __attribute__((__swift_error__(zero_result)));
90+
// expected-error@-1 {{'__swift_error__' attribute can only be applied to a function with an error parameter}}
91+
92+
extern BOOL b __attribute__((__swift_error__(none)));
93+
// expected-error@-1 {{attribute only applies to functions and Objective-C methods}}

0 commit comments

Comments
 (0)