diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2161,6 +2161,12 @@ let Documentation = [SwiftErrorDocs]; } +def SwiftName : InheritableAttr { + let Spellings = [GNU<"swift_name">]; + let Args = [StringArgument<"Name">]; + let Documentation = [SwiftNameDocs]; +} + def NoDeref : TypeAttr { let Spellings = [Clang<"noderef">]; let Documentation = [NoDerefDocs]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3572,6 +3572,28 @@ }]; } +def SwiftNameDocs : Documentation { + let Category = SwiftDocs; + let Heading = "swift_name"; + let Content = [{ +The ``swift_name`` attribute provides the spelling for the transformed name when +the interface is imported into the Swift language. + +The parameter takes the single string representation of the Swift function name. +The name may be a compound Swift name. For a type, enum constant, property, or +variable declaration, the name must be a simple or qualified identifier. + + .. code-block:: c + + @interface I + - (void) methodWithInt:(int)i __attribute__((__swift_name__("I.method(int:)"))) + @end + + void __attribute__((__swift_name__("function()"))) f(void) { + } + }]; +} + def OMPDeclareSimdDocs : Documentation { let Category = DocCatFunction; let Heading = "#pragma omp declare simd"; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -557,6 +557,7 @@ def StringPlusInt : DiagGroup<"string-plus-int">; def StringPlusChar : DiagGroup<"string-plus-char">; def StrncatSize : DiagGroup<"strncat-size">; +def SwiftNameAttribute : DiagGroup<"swift-name-attribute">; def IntInBoolContext : DiagGroup<"int-in-bool-context">; def TautologicalTypeLimitCompare : DiagGroup<"tautological-type-limit-compare">; def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3974,6 +3974,53 @@ def err_objc_attr_protocol_requires_definition : Error< "attribute %0 can only be applied to @protocol definitions, not forward declarations">; +// Swift attributes. +def warn_attr_swift_name_function + : Warning<"parameter of %0 attribute must be a Swift function name string">, + InGroup; +def warn_attr_swift_name_invalid_identifier + : Warning<"%0 attribute has invalid identifier for %select{base|context|parameter}1 name">, + InGroup; +def warn_attr_swift_name_decl_kind + : Warning<"%0 attribute cannot be applied to this declaration">, + InGroup; +def warn_attr_swift_name_subscript_not_accessor + : Warning<"%0 attribute for 'subscript' must be a getter or setter">, + InGroup; +def warn_attr_swift_name_missing_parameters + : Warning<"%0 attribute is missing parameter label clause">, + InGroup; +def warn_attr_swift_name_subscript_no_parameter + : Warning<"%0 attribute for 'subscript' must take at least one parameter">, + InGroup; +def warn_attr_swift_name_setter_parameters + : Warning<"%0 attribute for setter must take one parameter for new value">, + InGroup; +def warn_attr_swift_name_multiple_selfs + : Warning<"%0 attribute cannot specify more than one 'self:' parameter">, + InGroup; +def warn_attr_swift_name_static_subscript + : Warning<"%0 attribute for 'subscript' must take a 'self:' parameter">, + InGroup; +def warn_attr_swift_name_getter_parameters + : Warning<"%0 attribute for getter must not take any parameters besides 'self:'">, + InGroup; +def warn_attr_swift_name_subscript_setter_no_newValue + : Warning<"%0 attribute for 'subscript' setter must take a 'newValue:' parameter">, + InGroup; +def warn_attr_swift_name_subscript_setter_multiple_newValues + : Warning<"%0 attribute for 'subscript' setter cannot take multiple 'newValue:' parameters">, + InGroup; +def warn_attr_swift_name_subscript_getter_newValue + : Warning<"%0 attribute for 'subscript' getter cannot take a 'newValue:' parameter">, + InGroup; +def warn_attr_swift_name_function_no_prototype + : Warning<"%0 attribute can only be applied to function declarations with prototypes">, + InGroup; +def warn_attr_swift_name_num_params + : Warning<"too %select{few|many}0 parameters in %1 attribute (expected %2; got %3)">, + InGroup; + def err_attr_swift_error_no_error_parameter : Error< "%0 attribute can only be applied to a %select{function|method}1 with an " "error parameter">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1834,6 +1834,25 @@ } }; + /// Do a check to make sure \p Name looks like a legal swift_name + /// attribute for the decl \p D. Raise a diagnostic if the name is invalid + /// for the given declaration. + /// + /// For a function, this will validate a compound Swift name, + /// e.g. init(foo:bar:baz:) or controllerForName(_:), + /// and the function will output the number of parameter names, and whether + /// this is a single-arg initializer. + /// + /// For a type, enum constant, property, or variable declaration, this will + /// validate either a simple identifier, or a qualified + /// context.identifier name. + /// + /// \p AL is used to provide caret diagnostics in case of a malformed name. + /// + /// \returns true if the name is a valid swift name for \p D, false otherwise. + bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc, + const ParsedAttr &AL); + /// A derivative of BoundTypeDiagnoser for which the diagnostic's type /// parameter is preceded by a 0/1 enum that is 1 if the type is sizeless. /// For example, a diagnostic with no other parameters would generally have @@ -3059,6 +3078,8 @@ SpeculativeLoadHardeningAttr * mergeSpeculativeLoadHardeningAttr(Decl *D, const SpeculativeLoadHardeningAttr &AL); + SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const AttributeCommonInfo &CI, + StringRef Name, bool Override); OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, const AttributeCommonInfo &CI); InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2607,6 +2607,9 @@ return false; } else if (const auto *MA = dyn_cast(Attr)) NewAttr = S.mergeMinSizeAttr(D, *MA); + else if (const auto *SNA = dyn_cast(Attr)) + NewAttr = S.mergeSwiftNameAttr(D, *SNA, + SNA->getName(), AMK == Sema::AMK_Override); else if (const auto *OA = dyn_cast(Attr)) NewAttr = S.mergeOptimizeNoneAttr(D, *OA); else if (const auto *InternalLinkageA = dyn_cast(Attr)) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4277,6 +4277,24 @@ return ::new (Context) NoSpeculativeLoadHardeningAttr(Context, AL); } +SwiftNameAttr *Sema::mergeSwiftNameAttr(Decl *D, const AttributeCommonInfo &CI, + StringRef Name, bool Override) { + if (const auto *Inline = D->getAttr()) { + if (Override) { + // FIXME: warn about incompatible override + return nullptr; + } + + if (Inline->getName() != Name && !Inline->isImplicit()) { + Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline; + Diag(CI.getLoc(), diag::note_conflicting_attribute); + } + + D->dropAttr(); + } + return ::new (Context) SwiftNameAttr(Context, CI, Name); +} + OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, const AttributeCommonInfo &CI) { if (AlwaysInlineAttr *Inline = D->getAttr()) { @@ -5636,6 +5654,279 @@ D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention)); } +static bool +validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc, + StringRef Name, unsigned &SwiftParamCount, + bool &IsSingleParamInit) { + SwiftParamCount = 0; + IsSingleParamInit = false; + + // Check whether this will be mapped to a getter or setter of a property. + bool IsGetter = false, IsSetter = false; + if (Name.startswith("getter:")) { + IsGetter = true; + Name = Name.substr(7); + } else if (Name.startswith("setter:")) { + IsSetter = true; + Name = Name.substr(7); + } + + if (Name.back() != ')') { + S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; + return false; + } + + bool IsMember = false; + StringRef ContextName, BaseName, Parameters; + + std::tie(BaseName, Parameters) = Name.split('('); + + // Split at the first '.', if it exists, which separates the context name + // from the base name. + std::tie(ContextName, BaseName) = BaseName.split('.'); + if (BaseName.empty()) { + BaseName = ContextName; + ContextName = StringRef(); + } else if (ContextName.empty() || !isValidIdentifier(ContextName)) { + S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL + << /*context*/ 1; + return false; + } else { + IsMember = true; + } + + if (!isValidIdentifier(BaseName) || BaseName == "_") { + S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL + << /*basename*/ 0; + return false; + } + + bool IsSubscript = BaseName == "subscript"; + // A subscript accessor must be a getter or setter. + if (IsSubscript && !IsGetter && !IsSetter) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_not_accessor) << AL; + return false; + } + + if (Parameters.empty()) { + S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL; + return false; + } + Parameters = Parameters.drop_back(); // ')' + + if (Parameters.empty()) { + // Setters and subscripts must have at least one parameter. + if (IsSubscript) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_no_parameter) << AL; + return false; + } + + if (IsSetter) { + S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL; + return false; + } + + return true; + } + + if (Parameters.back() != ':') { + S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; + return false; + } + + StringRef CurrentParam; + llvm::Optional SelfLocation; + unsigned NewValueCount = 0; + llvm::Optional NewValueLocation; + do { + std::tie(CurrentParam, Parameters) = Parameters.split(':'); + + if (!isValidIdentifier(CurrentParam)) { + S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL + << /*parameter*/2; + return false; + } + + if (IsMember && CurrentParam == "self") { + // "self" indicates the "self" argument for a member. + + // More than one "self"? + if (SelfLocation) { + S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL; + return false; + } + + // The "self" location is the current parameter. + SelfLocation = SwiftParamCount; + } else if (CurrentParam == "newValue") { + // "newValue" indicates the "newValue" argument for a setter. + + // There should only be one 'newValue', but it's only significant for + // subscript accessors, so don't error right away. + ++NewValueCount; + + NewValueLocation = SwiftParamCount; + } + + ++SwiftParamCount; + } while (!Parameters.empty()); + + // Only instance subscripts are currently supported. + if (IsSubscript && !SelfLocation) { + S.Diag(Loc, diag::warn_attr_swift_name_static_subscript) << AL; + return false; + } + + IsSingleParamInit = + SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_"; + + // Check the number of parameters for a getter/setter. + if (IsGetter || IsSetter) { + // Setters have one parameter for the new value. + unsigned NumExpectedParams = IsGetter ? 0 : 1; + unsigned ParamDiag = + IsGetter ? diag::warn_attr_swift_name_getter_parameters + : diag::warn_attr_swift_name_setter_parameters; + + // Instance methods have one parameter for "self". + if (SelfLocation) + ++NumExpectedParams; + + // Subscripts may have additional parameters beyond the expected params for + // the index. + if (IsSubscript) { + if (SwiftParamCount < NumExpectedParams) { + S.Diag(Loc, ParamDiag) << AL; + return false; + } + + // A subscript setter must explicitly label its newValue parameter to + // distinguish it from index parameters. + if (IsSetter) { + if (!NewValueLocation) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue) + << AL; + return false; + } + if (NewValueCount > 1) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_multiple_newValues) + << AL; + return false; + } + } else { + // Subscript getters should have no 'newValue:' parameter. + if (NewValueLocation) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue) + << AL; + return false; + } + } + } else { + // Property accessors must have exactly the number of expected params. + if (SwiftParamCount != NumExpectedParams) { + S.Diag(Loc, ParamDiag) << AL; + return false; + } + } + } + + return true; +} + +bool Sema::DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc, + const ParsedAttr &AL) { + if (isa(D) || isa(D)) { + ArrayRef Params; + unsigned ParamCount; + + if (const auto *Method = dyn_cast(D)) { + ParamCount = Method->getSelector().getNumArgs(); + Params = Method->parameters().slice(0, ParamCount); + } else { + const auto *F = cast(D); + + ParamCount = F->getNumParams(); + Params = F->parameters(); + + if (!F->hasWrittenPrototype()) { + Diag(Loc, diag::warn_attr_swift_name_function_no_prototype) << AL; + return false; + } + } + + unsigned SwiftParamCount; + bool IsSingleParamInit; + if (!validateSwiftFunctionName(*this, AL, Loc, Name, + SwiftParamCount, IsSingleParamInit)) + return false; + + bool ParamCountValid; + if (SwiftParamCount == ParamCount) { + ParamCountValid = true; + } else if (SwiftParamCount > ParamCount) { + ParamCountValid = IsSingleParamInit && ParamCount == 0; + } else { + // We have fewer Swift parameters than Objective-C parameters, but that + // might be because we've transformed some of them. Check for potential + // "out" parameters and err on the side of not warning. + unsigned MaybeOutParamCount = + std::count_if(Params.begin(), Params.end(), + [](const ParmVarDecl *Param) -> bool { + QualType ParamTy = Param->getType(); + if (ParamTy->isReferenceType() || ParamTy->isPointerType()) + return !ParamTy->getPointeeType().isConstQualified(); + return false; + }); + + ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount; + } + + if (!ParamCountValid) { + Diag(Loc, diag::warn_attr_swift_name_num_params) + << (SwiftParamCount > ParamCount) << AL << ParamCount + << SwiftParamCount; + return false; + } + } else if (isa(D) || isa(D) || + isa(D) || isa(D) || + isa(D) || isa(D) || isa(D) || + isa(D) || isa(D)) { + StringRef ContextName, BaseName; + + std::tie(ContextName, BaseName) = Name.split('.'); + if (BaseName.empty()) { + BaseName = ContextName; + ContextName = StringRef(); + } else if (!isValidIdentifier(ContextName)) { + Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL + << /*context*/1; + return false; + } + + if (!isValidIdentifier(BaseName)) { + Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL + << /*basename*/0; + return false; + } + } else { + Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL; + return false; + } + return true; +} + +static void handleSwiftName(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef Name; + SourceLocation Loc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc)) + return; + + if (!S.DiagnoseSwiftName(D, Name, Loc, AL)) + return; + + D->addAttr(::new (S.Context) SwiftNameAttr(S.Context, AL, Name)); +} + //===----------------------------------------------------------------------===// // Microsoft specific attribute handlers. //===----------------------------------------------------------------------===// @@ -7558,6 +7849,9 @@ case ParsedAttr::AT_SwiftError: handleSwiftError(S, D, AL); break; + case ParsedAttr::AT_SwiftName: + handleSwiftName(S, D, AL); + break; case ParsedAttr::AT_SwiftObjCMembers: handleSimpleAttribute(S, D, AL); break; diff --git a/clang/test/SemaObjC/attr-swift_name.m b/clang/test/SemaObjC/attr-swift_name.m new file mode 100644 --- /dev/null +++ b/clang/test/SemaObjC/attr-swift_name.m @@ -0,0 +1,170 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -fobjc-arc %s + +#define SWIFT_NAME(name) __attribute__((__swift_name__(name))) + +typedef struct { + float x, y, z; +} Point3D; + +__attribute__((__swift_name__("PType"))) +@protocol P +@end + +__attribute__((__swift_name__("IClass"))) +@interface I

+- (instancetype)init SWIFT_NAME("init()"); +- (instancetype)initWithValue:(int)value SWIFT_NAME("iWithValue(_:)"); + ++ (void)refresh SWIFT_NAME("refresh()"); + +- (instancetype)i SWIFT_NAME("i()"); + +- (I *)iWithValue:(int)value SWIFT_NAME("i(value:)"); +- (I *)iWithValue:(int)value value:(int)value2 SWIFT_NAME("i(value:extra:)"); +- (I *)iWithValueConvertingValue:(int)value value:(int)value2 SWIFT_NAME("i(_:extra:)"); + ++ (I *)iWithOtheValue:(int)value SWIFT_NAME("init"); +// expected-warning@-1 {{parameter of '__swift_name__' attribute must be a Swift function name string}} + ++ (I *)iWithAnotherValue:(int)value SWIFT_NAME("i()"); +// expected-warning@-1 {{too few parameters in '__swift_name__' attribute (expected 1; got 0)}} + ++ (I *)iWithYetAnotherValue:(int)value SWIFT_NAME("i(value:extra:)"); +// expected-warning@-1 {{too many parameters in '__swift_name__' attribute (expected 1; got 2}} + ++ (I *)iAndReturnErrorCode:(int *)errorCode SWIFT_NAME("i()"); // no-warning ++ (I *)iWithValue:(int)value andReturnErrorCode:(int *)errorCode SWIFT_NAME("i(value:)"); // no-warning + ++ (I *)iFromErrorCode:(const int *)errorCode SWIFT_NAME("i()"); +// expected-warning@-1 {{too few parameters in '__swift_name__' attribute (expected 1; got 0)}} + ++ (I *)iWithPointerA:(int *)value andReturnErrorCode:(int *)errorCode SWIFT_NAME("i()"); // no-warning ++ (I *)iWithPointerB:(int *)value andReturnErrorCode:(int *)errorCode SWIFT_NAME("i(pointer:)"); // no-warning ++ (I *)iWithPointerC:(int *)value andReturnErrorCode:(int *)errorCode SWIFT_NAME("i(pointer:errorCode:)"); // no-warning + ++ (I *)iWithOtherI:(I *)other SWIFT_NAME("i()"); +// expected-warning@-1 {{too few parameters in '__swift_name__' attribute (expected 1; got 0)}} + ++ (instancetype)specialI SWIFT_NAME("init(options:)"); ++ (instancetype)specialJ SWIFT_NAME("init(options:extra:)"); +// expected-warning@-1 {{too many parameters in '__swift_name__' attribute (expected 0; got 2)}} ++ (instancetype)specialK SWIFT_NAME("init(_:)"); +// expected-warning@-1 {{too many parameters in '__swift_name__' attribute (expected 0; got 1)}} ++ (instancetype)specialL SWIFT_NAME("i(options:)"); +// expected-warning@-1 {{too many parameters in '__swift_name__' attribute (expected 0; got 1)}} + ++ (instancetype)trailingParen SWIFT_NAME("foo("); +// expected-warning@-1 {{parameter of '__swift_name__' attribute must be a Swift function name string}} ++ (instancetype)trailingColon SWIFT_NAME("foo:"); +// expected-warning@-1 {{parameter of '__swift_name__' attribute must be a Swift function name string}} ++ (instancetype)initialIgnore:(int)value SWIFT_NAME("_(value:)"); +// expected-warning@-1 {{'__swift_name__' attribute has invalid identifier for base name}} ++ (instancetype)middleOmitted:(int)value SWIFT_NAME("i(:)"); +// expected-warning@-1 {{'__swift_name__' attribute has invalid identifier for parameter name}} + +@property(strong) id someProp SWIFT_NAME("prop"); +@end + +enum SWIFT_NAME("E") E { + value1, + value2, + value3 SWIFT_NAME("three"), + value4 SWIFT_NAME("four()"), // expected-warning {{'__swift_name__' attribute has invalid identifier for base name}} +}; + +struct SWIFT_NAME("TStruct") SStruct { + int i, j, k SWIFT_NAME("kay"); +}; + +int i SWIFT_NAME("g_i"); + +void f0(int i) SWIFT_NAME("f_0"); +// expected-warning@-1 {{parameter of '__swift_name__' attribute must be a Swift function name string}} + +void f1(int i) SWIFT_NAME("f_1()"); +// expected-warning@-1 {{too few parameters in '__swift_name__' attribute (expected 1; got 0)}} + +void f2(int i) SWIFT_NAME("f_2(a:b:)"); +// expected-warning@-1 {{too many parameters in '__swift_name__' attribute (expected 1; got 2)}} + +void f3(int x, int y) SWIFT_NAME("fWithX(_:y:)"); +void f4(int x, int *error) SWIFT_NAME("fWithX(_:)"); + +typedef int int_t SWIFT_NAME("IntType"); + +struct Point3D createPoint3D(float x, float y, float z) SWIFT_NAME("Point3D.init(x:y:z:)"); +struct Point3D rotatePoint3D(Point3D point, float radians) SWIFT_NAME("Point3D.rotate(self:radians:)"); +struct Point3D badRotatePoint3D(Point3D point, float radians) SWIFT_NAME("Point3D.rotate(radians:)"); +// expected-warning@-1 {{too few parameters in '__swift_name__' attribute (expected 2; got 1)}} + +extern struct Point3D identityPoint SWIFT_NAME("Point3D.identity"); + +float Point3DGetMagnitude(Point3D point) SWIFT_NAME("getter:Point3D.magnitude(self:)"); +float Point3DGetMagnitudeAndSomethingElse(Point3D point, float f) SWIFT_NAME("getter:Point3D.magnitude(self:f:)"); +// expected-warning@-1 {{'__swift_name__' attribute for getter must not take any parameters besides 'self:'}} + +float Point3DGetRadius(Point3D point) SWIFT_NAME("getter:Point3D.radius(self:)"); +void Point3DSetRadius(Point3D point, float radius) SWIFT_NAME("setter:Point3D.radius(self:newValue:)"); + +float Point3DPreGetRadius(Point3D point) SWIFT_NAME("getter:Point3D.preRadius(self:)"); +void Point3DPreSetRadius(float radius, Point3D point) SWIFT_NAME("setter:Point3D.preRadius(newValue:self:)"); + +void Point3DSetRadiusAndSomethingElse(Point3D point, float radius, float f) SWIFT_NAME("setter:Point3D.radius(self:newValue:f:)"); +// expected-warning@-1 {{'__swift_name__' attribute for setter must take one parameter for new value}} + +float Point3DGetComponent(Point3D point, unsigned index) SWIFT_NAME("getter:Point3D.subscript(self:_:)"); +float Point3DSetComponent(Point3D point, unsigned index, float value) SWIFT_NAME("setter:Point3D.subscript(self:_:newValue:)"); + +float Point3DGetMatrixComponent(Point3D point, unsigned x, unsigned y) SWIFT_NAME("getter:Point3D.subscript(self:x:y:)"); +void Point3DSetMatrixComponent(Point3D point, unsigned x, float value, unsigned y) SWIFT_NAME("setter:Point3D.subscript(self:x:newValue:y:)"); + +float Point3DSetWithoutNewValue(Point3D point, unsigned x, unsigned y) SWIFT_NAME("setter:Point3D.subscript(self:x:y:)"); +// expected-warning@-1 {{'__swift_name__' attribute for 'subscript' setter must take a 'newValue:' parameter}} + +float Point3DSubscriptButNotGetterSetter(Point3D point, unsigned x) SWIFT_NAME("Point3D.subscript(self:_:)"); +// expected-warning@-1 {{'__swift_name__' attribute for 'subscript' must be a getter or setter}} + +void Point3DSubscriptSetterTwoNewValues(Point3D point, unsigned x, float a, float b) SWIFT_NAME("setter:Point3D.subscript(self:_:newValue:newValue:)"); +// expected-warning@-1 {{'__swift_name__' attribute for 'subscript' setter cannot take multiple 'newValue:' parameters}} + +float Point3DSubscriptGetterNewValue(Point3D point, unsigned x, float a, float b) SWIFT_NAME("getter:Point3D.subscript(self:_:newValue:newValue:)"); +// expected-warning@-1 {{'__swift_name__' attribute for 'subscript' getter cannot take a 'newValue:' parameter}} + +void Point3DMethodWithNewValue(Point3D point, float newValue) SWIFT_NAME("Point3D.method(self:newValue:)"); +void Point3DMethodWithNewValues(Point3D point, float newValue, float newValueB) SWIFT_NAME("Point3D.method(self:newValue:newValue:)"); + +float Point3DStaticSubscript(unsigned x) SWIFT_NAME("getter:Point3D.subscript(_:)"); +// expected-warning@-1 {{'__swift_name__' attribute for 'subscript' must take a 'self:' parameter}} + +float Point3DStaticSubscriptNoArgs(void) SWIFT_NAME("getter:Point3D.subscript()"); +// expected-warning@-1 {{'__swift_name__' attribute for 'subscript' must take at least one parameter}} + +float Point3DPreGetComponent(Point3D point, unsigned index) SWIFT_NAME("getter:Point3D.subscript(self:_:)"); + +Point3D getCurrentPoint3D(void) SWIFT_NAME("getter:currentPoint3D()"); + +void setCurrentPoint3D(Point3D point) SWIFT_NAME("setter:currentPoint3D(newValue:)"); + +Point3D getLastPoint3D(void) SWIFT_NAME("getter:lastPoint3D()"); + +void setLastPoint3D(Point3D point) SWIFT_NAME("setter:lastPoint3D(newValue:)"); + +Point3D getZeroPoint(void) SWIFT_NAME("getter:Point3D.zero()"); +void setZeroPoint(Point3D point) SWIFT_NAME("setter:Point3D.zero(newValue:)"); +Point3D getZeroPointNoPrototype() SWIFT_NAME("getter:Point3D.zeroNoPrototype()"); +// expected-warning@-1 {{'__swift_name__' attribute can only be applied to function declarations with prototypes}} + +Point3D badGetter1(int x) SWIFT_NAME("getter:bad1(_:)"); +// expected-warning@-1 {{'__swift_name__' attribute for getter must not take any parameters besides 'self:'}} + +void badSetter1(void) SWIFT_NAME("getter:bad1())"); +// expected-warning@-1 {{parameter of '__swift_name__' attribute must be a Swift function name string}} + +Point3D badGetter2(Point3D point) SWIFT_NAME("getter:bad2(_:))"); +// expected-warning@-1 {{parameter of '__swift_name__' attribute must be a Swift function name string}} + +void badSetter2(Point3D point) SWIFT_NAME("setter:bad2(self:))"); +// expected-warning@-1 {{parameter of '__swift_name__' attribute must be a Swift function name string}} + +void f() SWIFT_NAME("function()"); +// expected-warning@-1 {{'__swift_name__' attribute can only be applied to function declarations with prototypes}}