From 10c854a489eec1e22fbafb306d9e8b45656d9fde Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Tue, 17 May 2016 18:24:56 -0700 Subject: [PATCH 1/4] Tighten up validation of swift_name for properties and subscripts. Fix a logic bug that turned our check for parameter counts on getters and setters into a no-op. Add support for subscript getters and setters, and validate that they're imported as instance methods, and that subscript setters have a 'newValue:' labeled argument. Improve QoI by producing more specific diagnostics for problems with swift names. --- include/clang/Basic/DiagnosticIDs.h | 2 +- include/clang/Basic/DiagnosticSemaKinds.td | 26 ++++++ lib/Sema/SemaDeclAttr.cpp | 96 +++++++++++++++++----- test/SemaObjC/attr-swift.m | 40 +++++++-- 4 files changed, 137 insertions(+), 27 deletions(-) diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index 312b71f4064..d13ae4c95a5 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -36,7 +36,7 @@ namespace clang { DIAG_START_AST = DIAG_START_PARSE + 500, DIAG_START_COMMENT = DIAG_START_AST + 110, DIAG_START_SEMA = DIAG_START_COMMENT + 100, - DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000, + DIAG_START_ANALYSIS = DIAG_START_SEMA + 4000, DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 }; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4278e45a2ab..ce52d8b2dd3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3015,6 +3015,32 @@ def err_attr_swift_name_identifier : Error< "parameter of %0 attribute must be an ASCII identifier string">; def err_attr_swift_name_function : Error< "parameter of %0 attribute must be a Swift function name string">; +def err_attr_swift_name_context_name_invalid_identifier : Error< + "%0 attribute has invalid identifier for context name">; +def err_attr_swift_name_basename_invalid_identifier : Error< + "%0 attribute has invalid identifier for base name">; +def err_attr_swift_name_parameter_invalid_identifier : Error< + "%0 attribute has invalid identifier for parameter name">; +def err_attr_swift_name_missing_parameters : Error< + "%0 attribute is missing parameter label clause">; +def err_attr_swift_name_subscript_not_accessor : Error< + "%0 attribute for 'subscript' must be a getter or setter">; +def err_attr_swift_name_subscript_no_parameter : Error< + "%0 attribute for 'subscript' must take at least one parameter">; +def err_attr_swift_name_subscript_getter_newValue : Error< + "%0 attribute for 'subscript' getter cannot take a 'newValue:' parameter">; +def err_attr_swift_name_subscript_setter_no_newValue : Error< + "%0 attribute for 'subscript' setter must take a 'newValue:' parameter">; +def err_attr_swift_name_subscript_setter_multiple_newValues : Error< + "%0 attribute for 'subscript' setter cannot take multiple 'newValue:' parameters">; +def err_attr_swift_name_getter_parameters : Error< + "%0 attribute for getter must not take any parameters besides 'self:'">; +def err_attr_swift_name_setter_parameters : Error< + "%0 attribute for setter must take one parameter for new value">; +def err_attr_swift_name_multiple_selfs : Error< + "%0 attribute cannot specify more than one 'self:' parameter">; +def err_attr_swift_name_static_subscript : Error< + "%0 attribute for 'subscript' must take a 'self:' parameter">; def warn_attr_swift_name_num_params : Warning< "too %select{few|many}0 parameters in %1 attribute (expected %2; got %3)">, InGroup>; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 31a5694d816..01846d0fd0d 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4587,8 +4587,10 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, /// Do a very rough check to make sure \p Name looks like a Swift function name, /// e.g. init(foo:bar:baz:) or controllerForName(_:), -/// and return the number of parameter names. -static bool validateSwiftFunctionName(StringRef Name, +/// and output the number of parameter names, whether this is a single-arg +/// initializer. Returns None if the name is valid, otherwise returns a +/// one-parameter diagnostic ID describing the problem. +static Optional validateSwiftFunctionName(StringRef Name, unsigned &ParamCount, bool &IsSingleParamInit) { ParamCount = 0; @@ -4606,7 +4608,7 @@ static bool validateSwiftFunctionName(StringRef Name, } if (Name.back() != ')') - return false; + return diag::err_attr_swift_name_function; StringRef BaseName, Parameters; std::tie(BaseName, Parameters) = Name.split('('); @@ -4620,63 +4622,116 @@ static bool validateSwiftFunctionName(StringRef Name, BaseName = ContextName; ContextName = StringRef(); } else if (ContextName.empty() || !isValidIdentifier(ContextName)) { - return false; + return diag::err_attr_swift_name_context_name_invalid_identifier; } else { IsMember = true; } if (!isValidIdentifier(BaseName) || BaseName == "_") - return false; + return diag::err_attr_swift_name_basename_invalid_identifier; + bool IsSubscript = BaseName == "subscript"; + // A subscript accessor must be a getter or setter. + if (IsSubscript && !isGetter && !isSetter) + return diag::err_attr_swift_name_subscript_not_accessor; + if (Parameters.empty()) - return false; + return diag::err_attr_swift_name_missing_parameters; Parameters = Parameters.drop_back(); // ')' if (Parameters.empty()) { - // Setters must have at least one parameter. - if (isSetter) return false; - - return true; + // Setters and subscripts must have at least one parameter. + if (IsSubscript) + return diag::err_attr_swift_name_subscript_no_parameter; + if (isSetter) + return diag::err_attr_swift_name_setter_parameters; + + return None; } if (Parameters.back() != ':') - return false; + return diag::err_attr_swift_name_function; Optional SelfLocation; + Optional NewValueLocation; + unsigned NewValueCount = 0; StringRef NextParam; do { std::tie(NextParam, Parameters) = Parameters.split(':'); if (!isValidIdentifier(NextParam)) - return false; + return diag::err_attr_swift_name_parameter_invalid_identifier; // "self" indicates the "self" argument for a member. if (IsMember && NextParam == "self") { // More than one "self"? - if (SelfLocation) return false; + if (SelfLocation) return diag::err_attr_swift_name_multiple_selfs; // The "self" location is the current parameter. SelfLocation = ParamCount; } - + + // "newValue" indicates the "newValue" argument for a setter. + if (NextParam == "newValue") { + // There should only be one 'newValue', but it's only significant for + // subscript accessors, so don't error right away. + ++NewValueCount; + + NewValueLocation = ParamCount; + } ++ParamCount; } while (!Parameters.empty()); + // Only instance subscripts are currently supported. + if (IsSubscript && !SelfLocation) + return diag::err_attr_swift_name_static_subscript; + IsSingleParamInit = (ParamCount == 1 && BaseName == "init" && NextParam != "_"); // Check the number of parameters for a getter/setter. if (isGetter || isSetter) { // Setters have one parameter for the new value. - unsigned NumExpectedParams = isSetter ? 1 : 0; + unsigned NumExpectedParams; + unsigned ParamDiag; + + if (isSetter) { + NumExpectedParams = 1; + ParamDiag = diag::err_attr_swift_name_setter_parameters; + } else { + NumExpectedParams = 0; + ParamDiag = diag::err_attr_swift_name_getter_parameters; + } // Instance methods have one parameter for "self". if (SelfLocation) ++NumExpectedParams; - - if (ParamCount != NumExpectedParams) return true; + + // Subscripts may have additional parameters beyond the expected params for + // the index. + if (IsSubscript) { + if (ParamCount < NumExpectedParams) + return ParamDiag; + // A subscript setter must explicitly label its newValue parameter to + // distinguish it from index parameters. + if (isSetter) { + if (!NewValueLocation) + return diag::err_attr_swift_name_subscript_setter_no_newValue; + // There can only be one. + if (NewValueCount > 1) + return diag::err_attr_swift_name_subscript_setter_multiple_newValues; + } else { + // Subscript getters should have no 'newValue:' parameter. + if (NewValueLocation) + return diag::err_attr_swift_name_subscript_getter_newValue; + } + } else { + // Property accessors must have exactly the number of expected params. + if (ParamCount != NumExpectedParams) + return ParamDiag; + } } - return true; + return None; } static void handleSwiftName(Sema &S, Decl *D, const AttributeList &Attr) { @@ -4700,8 +4755,9 @@ static void handleSwiftName(Sema &S, Decl *D, const AttributeList &Attr) { bool IsSingleParamInit; unsigned SwiftParamCount; - if (!validateSwiftFunctionName(Name, SwiftParamCount, IsSingleParamInit)) { - S.Diag(ArgLoc, diag::err_attr_swift_name_function) << Attr.getName(); + if (auto diagID + = validateSwiftFunctionName(Name, SwiftParamCount, IsSingleParamInit)){ + S.Diag(ArgLoc, *diagID) << Attr.getName(); return; } diff --git a/test/SemaObjC/attr-swift.m b/test/SemaObjC/attr-swift.m index effcfefff2f..d28430dd1d4 100644 --- a/test/SemaObjC/attr-swift.m +++ b/test/SemaObjC/attr-swift.m @@ -70,8 +70,8 @@ + (instancetype)specialGarply __attribute__((swift_name("foo(options:)"))); // e + (instancetype)trailingParen __attribute__((swift_name("foo("))); // expected-error {{parameter of 'swift_name' attribute must be a Swift function name string}} + (instancetype)trailingColon:(int)value __attribute__((swift_name("foo(value)"))); // expected-error {{parameter of 'swift_name' attribute must be a Swift function name string}} -+ (instancetype)initialIgnore:(int)value __attribute__((swift_name("_(value:)"))); // expected-error {{parameter of 'swift_name' attribute must be a Swift function name string}} -+ (instancetype)middleOmitted:(int)value __attribute__((swift_name("foo(:)"))); // expected-error {{parameter of 'swift_name' attribute must be a Swift function name string}} ++ (instancetype)initialIgnore:(int)value __attribute__((swift_name("_(value:)"))); // expected-error {{'swift_name' attribute has invalid identifier for base name}} ++ (instancetype)middleOmitted:(int)value __attribute__((swift_name("foo(:)"))); // expected-error {{'swift_name' attribute has invalid identifier for parameter name}} @property(strong) id someProp __attribute__((swift_name("prop"))); @end @@ -106,19 +106,47 @@ struct __attribute__((swift_name("FooStruct"))) BarStruct { // Getters and setters. float Point3DGetMagnitude(Point3D point) __attribute__((swift_name("getter:Point3D.magnitude(self:)"))); +float Point3DGetMagnitudeAndSomethingElse(Point3D point, float wat) __attribute__((swift_name("getter:Point3D.magnitude(self:wat:)"))); // expected-error {{'swift_name' attribute for getter must not take any parameters besides 'self:'}} + float Point3DGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.radius(self:)"))); -void Point3DSetRadius(Point3D point, float radius) __attribute__((swift_name("setter:Point3D.radius(self:_:)"))); +void Point3DSetRadius(Point3D point, float radius) __attribute__((swift_name("setter:Point3D.radius(self:newValue:)"))); + +float Point3DPreGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.preRadius(self:)"))); +void Point3DPreSetRadius(float radius, Point3D point) __attribute__((swift_name("setter:Point3D.preRadius(newValue:self:)"))); + +void Point3DSetRadiusAndSomethingElse(Point3D point, float radius, float wat) __attribute__((swift_name("setter:Point3D.radius(self:newValue:wat:)"))); // expected-error {{'swift_name' attribute for setter must take one parameter for new value}} + +float Point3DGetComponent(Point3D point, unsigned index) __attribute__((swift_name("getter:Point3D.subscript(self:_:)"))); +float Point3DSetComponent(Point3D point, unsigned index, float value) __attribute__((swift_name("setter:Point3D.subscript(self:_:newValue:)"))); + +float Point3DGetMatrixComponent(Point3D point, unsigned x, unsigned y) __attribute__((swift_name("getter:Point3D.subscript(self:x:y:)"))); +void Point3DSetMatrixComponent(Point3D point, unsigned x, float value, unsigned y) __attribute__((swift_name("setter:Point3D.subscript(self:x:newValue:y:)"))); + +float Point3DSetWithoutNewValue(Point3D point, unsigned x, unsigned y) __attribute__((swift_name("setter:Point3D.subscript(self:x:y:)"))); // expected-error {{'swift_name' attribute for 'subscript' setter must take a 'newValue:' parameter}} + +float Point3DSubscriptButNotGetterSetter(Point3D point, unsigned x) __attribute__((swift_name("Point3D.subscript(self:_:)"))); // expected-error {{'swift_name' attribute for 'subscript' must be a getter or setter}} + +void Point3DSubscriptSetterTwoNewValues(Point3D point, unsigned x, float a, float b) __attribute__((swift_name("setter:Point3D.subscript(self:_:newValue:newValue:)"))); // expected-error {{'swift_name' attribute for 'subscript' setter cannot take multiple 'newValue:' parameters}} +float Point3DSubscriptGetterNewValue(Point3D point, unsigned x, float a, float b) __attribute__((swift_name("getter:Point3D.subscript(self:_:newValue:newValue:)"))); // expected-error {{'swift_name' attribute for 'subscript' getter cannot take a 'newValue:' parameter}} + +void Point3DMethodWithNewValue(Point3D point, float newValue) __attribute__((swift_name("Point3D.method(self:newValue:)"))); +void Point3DMethodWithNewValues(Point3D point, float newValue, float newValueB) __attribute__((swift_name("Point3D.method(self:newValue:newValue:)"))); + +float Point3DStaticSubscript(unsigned x) __attribute__((swift_name("getter:Point3D.subscript(_:)"))); // expected-error {{'swift_name' attribute for 'subscript' must take a 'self:' parameter}} +float Point3DStaticSubscriptNoArgs(void) __attribute__((swift_name("getter:Point3D.subscript()"))); // expected-error {{'swift_name' attribute for 'subscript' must take at least one parameter}} + +float Point3DPreGetComponent(Point3D point, unsigned index) __attribute__((swift_name("getter:Point3D.subscript(self:_:)"))); Point3D getCurrentPoint3D(void) __attribute__((swift_name("getter:currentPoint3D()"))); -void setCurrentPoint3D(Point3D point) __attribute__((swift_name("setter:currentPoint3D(_:)"))); +void setCurrentPoint3D(Point3D point) __attribute__((swift_name("setter:currentPoint3D(newValue:)"))); Point3D getLastPoint3D(void) __attribute__((swift_name("getter:lastPoint3D()"))); -void setLastPoint3D(Point3D point) __attribute__((swift_name("setter:lastPoint3D(_:)"))); +void setLastPoint3D(Point3D point) __attribute__((swift_name("setter:lastPoint3D(newValue:)"))); Point3D getZeroPoint() __attribute__((swift_name("getter:Point3D.zero()"))); -void setZeroPoint(Point3D point) __attribute__((swift_name("setter:Point3D.zero(_:)"))); +void setZeroPoint(Point3D point) __attribute__((swift_name("setter:Point3D.zero(newValue:)"))); Point3D badGetter1(int x) __attribute__((swift_name("getter:bad1(_:))"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} void badSetter1() __attribute__((swift_name("getter:bad1())"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} From 247d1ec514cd3d6fe388d62579d77646ec7ee8d2 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Wed, 18 May 2016 11:33:32 -0700 Subject: [PATCH 2/4] Only allow swift_name attributes on prototyped declarations. --- include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ lib/Sema/SemaDeclAttr.cpp | 4 ++++ test/SemaObjC/attr-swift.m | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index ce52d8b2dd3..16cc16cdd29 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3015,6 +3015,8 @@ def err_attr_swift_name_identifier : Error< "parameter of %0 attribute must be an ASCII identifier string">; def err_attr_swift_name_function : Error< "parameter of %0 attribute must be a Swift function name string">; +def err_attr_swift_name_function_no_prototype : Error< + "%0 attribute can only be applied to function declarations with prototypes">; def err_attr_swift_name_context_name_invalid_identifier : Error< "%0 attribute has invalid identifier for context name">; def err_attr_swift_name_basename_invalid_identifier : Error< diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 01846d0fd0d..540413bb8e3 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4751,6 +4751,10 @@ static void handleSwiftName(Sema &S, Decl *D, const AttributeList &Attr) { const auto *Function = cast(D); ParamCount = Function->getNumParams(); Params = Function->parameters(); + + if (!Function->hasWrittenPrototype()) + S.Diag(ArgLoc, diag::err_attr_swift_name_function_no_prototype) + << Attr.getName(); } bool IsSingleParamInit; diff --git a/test/SemaObjC/attr-swift.m b/test/SemaObjC/attr-swift.m index d28430dd1d4..c8b316cbe94 100644 --- a/test/SemaObjC/attr-swift.m +++ b/test/SemaObjC/attr-swift.m @@ -145,11 +145,12 @@ struct __attribute__((swift_name("FooStruct"))) BarStruct { void setLastPoint3D(Point3D point) __attribute__((swift_name("setter:lastPoint3D(newValue:)"))); -Point3D getZeroPoint() __attribute__((swift_name("getter:Point3D.zero()"))); +Point3D getZeroPoint(void) __attribute__((swift_name("getter:Point3D.zero()"))); +Point3D getZeroPointNoPrototype() __attribute__((swift_name("getter:Point3D.zeroNoPrototype()"))); // expected-error{{'swift_name' attribute can only be applied to function declarations with prototypes}} void setZeroPoint(Point3D point) __attribute__((swift_name("setter:Point3D.zero(newValue:)"))); Point3D badGetter1(int x) __attribute__((swift_name("getter:bad1(_:))"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} -void badSetter1() __attribute__((swift_name("getter:bad1())"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} +void badSetter1(void) __attribute__((swift_name("getter:bad1())"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} Point3D badGetter2(Point3D point) __attribute__((swift_name("getter:bad2(_:))"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} From 151224d09a657759fb0fb1692675d1b7161d0fc8 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Thu, 19 May 2016 12:56:16 -0700 Subject: [PATCH 3/4] Validate swift_names that come from API notes. And relax swift_name validation errors into warnings, so that SDKs don't break when we change or tighten the rules. --- include/clang/Basic/DiagnosticSemaKinds.td | 34 +++-- include/clang/Sema/Sema.h | 18 +++ lib/Sema/SemaAPINotes.cpp | 11 +- lib/Sema/SemaDeclAttr.cpp | 138 ++++++++++++--------- test/SemaObjC/attr-swift.m | 40 +++--- 5 files changed, 141 insertions(+), 100 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 16cc16cdd29..7fad1b650e0 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3009,39 +3009,37 @@ def err_objc_attr_protocol_requires_definition : Error< "attribute %0 can only be applied to @protocol definitions, not forward declarations">; // Swift attributes -def err_attr_swift_name_decl_kind : Error< +def warn_attr_swift_name_decl_kind : Warning< "%0 attribute cannot be applied to this declaration">; -def err_attr_swift_name_identifier : Error< - "parameter of %0 attribute must be an ASCII identifier string">; -def err_attr_swift_name_function : Error< +def warn_attr_swift_name_function : Warning< "parameter of %0 attribute must be a Swift function name string">; -def err_attr_swift_name_function_no_prototype : Error< +def warn_attr_swift_name_function_no_prototype : Warning< "%0 attribute can only be applied to function declarations with prototypes">; -def err_attr_swift_name_context_name_invalid_identifier : Error< +def warn_attr_swift_name_context_name_invalid_identifier : Warning< "%0 attribute has invalid identifier for context name">; -def err_attr_swift_name_basename_invalid_identifier : Error< +def warn_attr_swift_name_basename_invalid_identifier : Warning< "%0 attribute has invalid identifier for base name">; -def err_attr_swift_name_parameter_invalid_identifier : Error< +def warn_attr_swift_name_parameter_invalid_identifier : Warning< "%0 attribute has invalid identifier for parameter name">; -def err_attr_swift_name_missing_parameters : Error< +def warn_attr_swift_name_missing_parameters : Warning< "%0 attribute is missing parameter label clause">; -def err_attr_swift_name_subscript_not_accessor : Error< +def warn_attr_swift_name_subscript_not_accessor : Warning< "%0 attribute for 'subscript' must be a getter or setter">; -def err_attr_swift_name_subscript_no_parameter : Error< +def warn_attr_swift_name_subscript_no_parameter : Warning< "%0 attribute for 'subscript' must take at least one parameter">; -def err_attr_swift_name_subscript_getter_newValue : Error< +def warn_attr_swift_name_subscript_getter_newValue : Warning< "%0 attribute for 'subscript' getter cannot take a 'newValue:' parameter">; -def err_attr_swift_name_subscript_setter_no_newValue : Error< +def warn_attr_swift_name_subscript_setter_no_newValue : Warning< "%0 attribute for 'subscript' setter must take a 'newValue:' parameter">; -def err_attr_swift_name_subscript_setter_multiple_newValues : Error< +def warn_attr_swift_name_subscript_setter_multiple_newValues : Warning< "%0 attribute for 'subscript' setter cannot take multiple 'newValue:' parameters">; -def err_attr_swift_name_getter_parameters : Error< +def warn_attr_swift_name_getter_parameters : Warning< "%0 attribute for getter must not take any parameters besides 'self:'">; -def err_attr_swift_name_setter_parameters : Error< +def warn_attr_swift_name_setter_parameters : Warning< "%0 attribute for setter must take one parameter for new value">; -def err_attr_swift_name_multiple_selfs : Error< +def warn_attr_swift_name_multiple_selfs : Warning< "%0 attribute cannot specify more than one 'self:' parameter">; -def err_attr_swift_name_static_subscript : Error< +def warn_attr_swift_name_static_subscript : Warning< "%0 attribute for 'subscript' must take a 'self:' parameter">; def warn_attr_swift_name_num_params : Warning< "too %select{few|many}0 parameters in %1 attribute (expected %2; got %3)">, diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 005309a5197..5c868f0c848 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1368,6 +1368,24 @@ class Sema { } }; + /// 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. + /// + /// \returns true if the name is a valid swift name for \p D, false otherwise. + bool DiagnoseSwiftName(Decl *D, StringRef Name, + SourceLocation ArgLoc, + IdentifierInfo *AttrName); + private: bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T, TypeDiagnoser *Diagnoser); diff --git a/lib/Sema/SemaAPINotes.cpp b/lib/Sema/SemaAPINotes.cpp index 5072824313e..4468d22f30a 100644 --- a/lib/Sema/SemaAPINotes.cpp +++ b/lib/Sema/SemaAPINotes.cpp @@ -111,7 +111,7 @@ static void ProcessAPINotes(Sema &S, Decl *D, if (Info.UnavailableInSwift) { D->addAttr(AvailabilityAttr::CreateImplicit( - S.Context, + S.Context, &S.Context.Idents.get("swift"), VersionTuple(), VersionTuple(), @@ -129,9 +129,14 @@ static void ProcessAPINotes(Sema &S, Decl *D, // swift_name if (!Info.SwiftName.empty() && !D->hasAttr()) { + auto &APINoteName = S.getASTContext().Idents.get("SwiftName API Note"); + + if (!S.DiagnoseSwiftName(D, Info.SwiftName, D->getLocation(), + &APINoteName)) { + return; + } D->addAttr(SwiftNameAttr::CreateImplicit(S.Context, - CopyString(S.Context, - Info.SwiftName))); + CopyString(S.Context, Info.SwiftName))); } } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 540413bb8e3..ec2b8256b06 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4585,15 +4585,11 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -/// Do a very rough check to make sure \p Name looks like a Swift function name, -/// e.g. init(foo:bar:baz:) or controllerForName(_:), -/// and output the number of parameter names, whether this is a single-arg -/// initializer. Returns None if the name is valid, otherwise returns a -/// one-parameter diagnostic ID describing the problem. -static Optional validateSwiftFunctionName(StringRef Name, - unsigned &ParamCount, - bool &IsSingleParamInit) { - ParamCount = 0; +static Optional +validateSwiftFunctionName(StringRef Name, + unsigned &SwiftParamCount, + bool &IsSingleParamInit) { + SwiftParamCount = 0; // Check whether this will be mapped to a getter or setter of a // property. @@ -4608,7 +4604,7 @@ static Optional validateSwiftFunctionName(StringRef Name, } if (Name.back() != ')') - return diag::err_attr_swift_name_function; + return diag::warn_attr_swift_name_function; StringRef BaseName, Parameters; std::tie(BaseName, Parameters) = Name.split('('); @@ -4622,35 +4618,35 @@ static Optional validateSwiftFunctionName(StringRef Name, BaseName = ContextName; ContextName = StringRef(); } else if (ContextName.empty() || !isValidIdentifier(ContextName)) { - return diag::err_attr_swift_name_context_name_invalid_identifier; + return diag::warn_attr_swift_name_context_name_invalid_identifier; } else { IsMember = true; } if (!isValidIdentifier(BaseName) || BaseName == "_") - return diag::err_attr_swift_name_basename_invalid_identifier; + return diag::warn_attr_swift_name_basename_invalid_identifier; bool IsSubscript = BaseName == "subscript"; // A subscript accessor must be a getter or setter. if (IsSubscript && !isGetter && !isSetter) - return diag::err_attr_swift_name_subscript_not_accessor; + return diag::warn_attr_swift_name_subscript_not_accessor; if (Parameters.empty()) - return diag::err_attr_swift_name_missing_parameters; + return diag::warn_attr_swift_name_missing_parameters; Parameters = Parameters.drop_back(); // ')' if (Parameters.empty()) { // Setters and subscripts must have at least one parameter. if (IsSubscript) - return diag::err_attr_swift_name_subscript_no_parameter; + return diag::warn_attr_swift_name_subscript_no_parameter; if (isSetter) - return diag::err_attr_swift_name_setter_parameters; + return diag::warn_attr_swift_name_setter_parameters; return None; } if (Parameters.back() != ':') - return diag::err_attr_swift_name_function; + return diag::warn_attr_swift_name_function; Optional SelfLocation; Optional NewValueLocation; @@ -4660,15 +4656,15 @@ static Optional validateSwiftFunctionName(StringRef Name, std::tie(NextParam, Parameters) = Parameters.split(':'); if (!isValidIdentifier(NextParam)) - return diag::err_attr_swift_name_parameter_invalid_identifier; + return diag::warn_attr_swift_name_parameter_invalid_identifier; // "self" indicates the "self" argument for a member. if (IsMember && NextParam == "self") { // More than one "self"? - if (SelfLocation) return diag::err_attr_swift_name_multiple_selfs; + if (SelfLocation) return diag::warn_attr_swift_name_multiple_selfs; // The "self" location is the current parameter. - SelfLocation = ParamCount; + SelfLocation = SwiftParamCount; } // "newValue" indicates the "newValue" argument for a setter. @@ -4677,17 +4673,17 @@ static Optional validateSwiftFunctionName(StringRef Name, // subscript accessors, so don't error right away. ++NewValueCount; - NewValueLocation = ParamCount; + NewValueLocation = SwiftParamCount; } - ++ParamCount; + ++SwiftParamCount; } while (!Parameters.empty()); // Only instance subscripts are currently supported. if (IsSubscript && !SelfLocation) - return diag::err_attr_swift_name_static_subscript; + return diag::warn_attr_swift_name_static_subscript; IsSingleParamInit = - (ParamCount == 1 && BaseName == "init" && NextParam != "_"); + (SwiftParamCount == 1 && BaseName == "init" && NextParam != "_"); // Check the number of parameters for a getter/setter. if (isGetter || isSetter) { @@ -4697,10 +4693,10 @@ static Optional validateSwiftFunctionName(StringRef Name, if (isSetter) { NumExpectedParams = 1; - ParamDiag = diag::err_attr_swift_name_setter_parameters; + ParamDiag = diag::warn_attr_swift_name_setter_parameters; } else { NumExpectedParams = 0; - ParamDiag = diag::err_attr_swift_name_getter_parameters; + ParamDiag = diag::warn_attr_swift_name_getter_parameters; } // Instance methods have one parameter for "self". @@ -4709,24 +4705,24 @@ static Optional validateSwiftFunctionName(StringRef Name, // Subscripts may have additional parameters beyond the expected params for // the index. if (IsSubscript) { - if (ParamCount < NumExpectedParams) + if (SwiftParamCount < NumExpectedParams) return ParamDiag; // A subscript setter must explicitly label its newValue parameter to // distinguish it from index parameters. if (isSetter) { if (!NewValueLocation) - return diag::err_attr_swift_name_subscript_setter_no_newValue; + return diag::warn_attr_swift_name_subscript_setter_no_newValue; // There can only be one. if (NewValueCount > 1) - return diag::err_attr_swift_name_subscript_setter_multiple_newValues; + return diag::warn_attr_swift_name_subscript_setter_multiple_newValues; } else { // Subscript getters should have no 'newValue:' parameter. if (NewValueLocation) - return diag::err_attr_swift_name_subscript_getter_newValue; + return diag::warn_attr_swift_name_subscript_getter_newValue; } } else { // Property accessors must have exactly the number of expected params. - if (ParamCount != NumExpectedParams) + if (SwiftParamCount != NumExpectedParams) return ParamDiag; } } @@ -4734,12 +4730,23 @@ static Optional validateSwiftFunctionName(StringRef Name, return None; } -static void handleSwiftName(Sema &S, Decl *D, const AttributeList &Attr) { - StringRef Name; - SourceLocation ArgLoc; - if (!S.checkStringLiteralArgumentAttr(Attr, 0, Name, &ArgLoc)) - return; - +/// 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. +/// +/// \returns true if the name is a valid swift name for \p D, false otherwise. +bool Sema::DiagnoseSwiftName(Decl *D, StringRef Name, + SourceLocation ArgLoc, + IdentifierInfo *AttrName) { if (isa(D) || isa(D)) { ArrayRef Params; unsigned ParamCount; @@ -4752,19 +4759,21 @@ static void handleSwiftName(Sema &S, Decl *D, const AttributeList &Attr) { ParamCount = Function->getNumParams(); Params = Function->parameters(); - if (!Function->hasWrittenPrototype()) - S.Diag(ArgLoc, diag::err_attr_swift_name_function_no_prototype) - << Attr.getName(); + if (!Function->hasWrittenPrototype()) { + Diag(ArgLoc, diag::warn_attr_swift_name_function_no_prototype) + << AttrName; + return false; + } } - bool IsSingleParamInit; unsigned SwiftParamCount; - if (auto diagID - = validateSwiftFunctionName(Name, SwiftParamCount, IsSingleParamInit)){ - S.Diag(ArgLoc, *diagID) << Attr.getName(); - return; + bool IsSingleParamInit; + if (auto diagID = validateSwiftFunctionName(Name, SwiftParamCount, + IsSingleParamInit)) { + Diag(ArgLoc, *diagID) << AttrName; + return false; } - + bool ParamsOK; if (SwiftParamCount == ParamCount) { ParamsOK = true; @@ -4786,10 +4795,10 @@ static void handleSwiftName(Sema &S, Decl *D, const AttributeList &Attr) { } if (!ParamsOK) { - S.Diag(ArgLoc, diag::warn_attr_swift_name_num_params) - << (SwiftParamCount > ParamCount) << Attr.getName() + Diag(ArgLoc, diag::warn_attr_swift_name_num_params) + << (SwiftParamCount > ParamCount) << AttrName << ParamCount << SwiftParamCount; - return; + return false; } } else if (isa(D) || isa(D) || @@ -4802,24 +4811,35 @@ static void handleSwiftName(Sema &S, Decl *D, const AttributeList &Attr) { BaseName = ContextName; ContextName = StringRef(); } else if (!isValidIdentifier(ContextName)) { - S.Diag(ArgLoc, diag::err_attr_swift_name_identifier) << Attr.getName(); - return; + Diag(ArgLoc, diag::warn_attr_swift_name_context_name_invalid_identifier) + << AttrName; + return false; } if (!isValidIdentifier(BaseName)) { - S.Diag(ArgLoc, diag::err_attr_swift_name_identifier) << Attr.getName(); - return; + Diag(ArgLoc, diag::warn_attr_swift_name_basename_invalid_identifier) + << AttrName; + return false; } } else { - S.Diag(Attr.getLoc(), diag::err_attr_swift_name_decl_kind) - << Attr.getName(); - return; + Diag(ArgLoc, diag::warn_attr_swift_name_decl_kind) << AttrName; + return false; } + return true; +} - D->addAttr(::new (S.Context) - SwiftNameAttr(Attr.getRange(), S.Context, Name, - Attr.getAttributeSpellingListIndex())); +static void handleSwiftName(Sema &S, Decl *D, const AttributeList &Attr) { + StringRef Name; + SourceLocation ArgLoc; + if (!S.checkStringLiteralArgumentAttr(Attr, 0, Name, &ArgLoc)) + return; + + if (!S.DiagnoseSwiftName(D, Name, ArgLoc, Attr.getName())) + return; + + D->addAttr(::new (S.Context) SwiftNameAttr(Attr.getRange(), S.Context, Name, + Attr.getAttributeSpellingListIndex())); } static bool isErrorParameter(Sema &S, QualType paramType) { diff --git a/test/SemaObjC/attr-swift.m b/test/SemaObjC/attr-swift.m index c8b316cbe94..bdcbbd0ace6 100644 --- a/test/SemaObjC/attr-swift.m +++ b/test/SemaObjC/attr-swift.m @@ -50,7 +50,7 @@ + (SNFoo *)fooWithValue:(int)value __attribute__((swift_name("foo(value:)"))); + (SNFoo *)fooWithValue:(int)value value:(int)value2 __attribute__((swift_name("foo(value:extra:)"))); + (SNFoo *)fooWithConvertingValue:(int)value value:(int)value2 __attribute__((swift_name("init(_:extra:)"))); -+ (SNFoo *)fooWithOtherValue:(int)value __attribute__((swift_name("init"))); // expected-error {{parameter of 'swift_name' attribute must be a Swift function name string}} ++ (SNFoo *)fooWithOtherValue:(int)value __attribute__((swift_name("init"))); // expected-warning {{parameter of 'swift_name' attribute must be a Swift function name string}} + (SNFoo *)fooWithAnotherValue:(int)value __attribute__((swift_name("foo()"))); // expected-warning {{too few parameters in 'swift_name' attribute (expected 1; got 0)}} + (SNFoo *)fooWithYetAnotherValue:(int)value __attribute__((swift_name("foo(value:extra:)"))); // expected-warning {{too many parameters in 'swift_name' attribute (expected 1; got 2)}} @@ -68,10 +68,10 @@ + (instancetype)specialBar __attribute__((swift_name("init(options:extra:)"))); + (instancetype)specialBaz __attribute__((swift_name("init(_:)"))); // expected-warning {{too many parameters in 'swift_name' attribute (expected 0; got 1)}} + (instancetype)specialGarply __attribute__((swift_name("foo(options:)"))); // expected-warning {{too many parameters in 'swift_name' attribute (expected 0; got 1)}} -+ (instancetype)trailingParen __attribute__((swift_name("foo("))); // expected-error {{parameter of 'swift_name' attribute must be a Swift function name string}} -+ (instancetype)trailingColon:(int)value __attribute__((swift_name("foo(value)"))); // expected-error {{parameter of 'swift_name' attribute must be a Swift function name string}} -+ (instancetype)initialIgnore:(int)value __attribute__((swift_name("_(value:)"))); // expected-error {{'swift_name' attribute has invalid identifier for base name}} -+ (instancetype)middleOmitted:(int)value __attribute__((swift_name("foo(:)"))); // expected-error {{'swift_name' attribute has invalid identifier for parameter name}} ++ (instancetype)trailingParen __attribute__((swift_name("foo("))); // expected-warning {{parameter of 'swift_name' attribute must be a Swift function name string}} ++ (instancetype)trailingColon:(int)value __attribute__((swift_name("foo(value)"))); // expected-warning {{parameter of 'swift_name' attribute must be a Swift function name string}} ++ (instancetype)initialIgnore:(int)value __attribute__((swift_name("_(value:)"))); // expected-warning {{'swift_name' attribute has invalid identifier for base name}} ++ (instancetype)middleOmitted:(int)value __attribute__((swift_name("foo(:)"))); // expected-warning {{'swift_name' attribute has invalid identifier for parameter name}} @property(strong) id someProp __attribute__((swift_name("prop"))); @end @@ -80,7 +80,7 @@ enum __attribute__((swift_name("MoreColors"))) MoreColors { Cyan, Magenta, Yellow __attribute__((swift_name("RoseGold"))), - Black __attribute__((swift_name("SpaceGrey()"))) // expected-error {{parameter of 'swift_name' attribute must be an ASCII identifier string}} + Black __attribute__((swift_name("SpaceGrey()"))) // expected-warning {{'swift_name' attribute has invalid identifier for base name}} }; struct __attribute__((swift_name("FooStruct"))) BarStruct { @@ -89,7 +89,7 @@ struct __attribute__((swift_name("FooStruct"))) BarStruct { int global_int __attribute__((swift_name("GlobalInt"))); -void foo1(int i) __attribute__((swift_name("foo"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} +void foo1(int i) __attribute__((swift_name("foo"))); // expected-warning{{parameter of 'swift_name' attribute must be a Swift function name string}} void foo2(int i) __attribute__((swift_name("foo()"))); // expected-warning{{too few parameters in 'swift_name' attribute (expected 1; got 0)}} void foo2(int i) __attribute__((swift_name("foo(a:b:)"))); // expected-warning{{too many parameters in 'swift_name' attribute (expected 1; got 2)}} void foo3(int i, int j) __attribute__((swift_name("fooWithX(_:y:)"))); // okay @@ -106,7 +106,7 @@ struct __attribute__((swift_name("FooStruct"))) BarStruct { // Getters and setters. float Point3DGetMagnitude(Point3D point) __attribute__((swift_name("getter:Point3D.magnitude(self:)"))); -float Point3DGetMagnitudeAndSomethingElse(Point3D point, float wat) __attribute__((swift_name("getter:Point3D.magnitude(self:wat:)"))); // expected-error {{'swift_name' attribute for getter must not take any parameters besides 'self:'}} +float Point3DGetMagnitudeAndSomethingElse(Point3D point, float wat) __attribute__((swift_name("getter:Point3D.magnitude(self:wat:)"))); // expected-warning {{'swift_name' attribute for getter must not take any parameters besides 'self:'}} float Point3DGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.radius(self:)"))); void Point3DSetRadius(Point3D point, float radius) __attribute__((swift_name("setter:Point3D.radius(self:newValue:)"))); @@ -114,7 +114,7 @@ struct __attribute__((swift_name("FooStruct"))) BarStruct { float Point3DPreGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.preRadius(self:)"))); void Point3DPreSetRadius(float radius, Point3D point) __attribute__((swift_name("setter:Point3D.preRadius(newValue:self:)"))); -void Point3DSetRadiusAndSomethingElse(Point3D point, float radius, float wat) __attribute__((swift_name("setter:Point3D.radius(self:newValue:wat:)"))); // expected-error {{'swift_name' attribute for setter must take one parameter for new value}} +void Point3DSetRadiusAndSomethingElse(Point3D point, float radius, float wat) __attribute__((swift_name("setter:Point3D.radius(self:newValue:wat:)"))); // expected-warning {{'swift_name' attribute for setter must take one parameter for new value}} float Point3DGetComponent(Point3D point, unsigned index) __attribute__((swift_name("getter:Point3D.subscript(self:_:)"))); float Point3DSetComponent(Point3D point, unsigned index, float value) __attribute__((swift_name("setter:Point3D.subscript(self:_:newValue:)"))); @@ -122,18 +122,18 @@ struct __attribute__((swift_name("FooStruct"))) BarStruct { float Point3DGetMatrixComponent(Point3D point, unsigned x, unsigned y) __attribute__((swift_name("getter:Point3D.subscript(self:x:y:)"))); void Point3DSetMatrixComponent(Point3D point, unsigned x, float value, unsigned y) __attribute__((swift_name("setter:Point3D.subscript(self:x:newValue:y:)"))); -float Point3DSetWithoutNewValue(Point3D point, unsigned x, unsigned y) __attribute__((swift_name("setter:Point3D.subscript(self:x:y:)"))); // expected-error {{'swift_name' attribute for 'subscript' setter must take a 'newValue:' parameter}} +float Point3DSetWithoutNewValue(Point3D point, unsigned x, unsigned y) __attribute__((swift_name("setter:Point3D.subscript(self:x:y:)"))); // expected-warning {{'swift_name' attribute for 'subscript' setter must take a 'newValue:' parameter}} -float Point3DSubscriptButNotGetterSetter(Point3D point, unsigned x) __attribute__((swift_name("Point3D.subscript(self:_:)"))); // expected-error {{'swift_name' attribute for 'subscript' must be a getter or setter}} +float Point3DSubscriptButNotGetterSetter(Point3D point, unsigned x) __attribute__((swift_name("Point3D.subscript(self:_:)"))); // expected-warning {{'swift_name' attribute for 'subscript' must be a getter or setter}} -void Point3DSubscriptSetterTwoNewValues(Point3D point, unsigned x, float a, float b) __attribute__((swift_name("setter:Point3D.subscript(self:_:newValue:newValue:)"))); // expected-error {{'swift_name' attribute for 'subscript' setter cannot take multiple 'newValue:' parameters}} -float Point3DSubscriptGetterNewValue(Point3D point, unsigned x, float a, float b) __attribute__((swift_name("getter:Point3D.subscript(self:_:newValue:newValue:)"))); // expected-error {{'swift_name' attribute for 'subscript' getter cannot take a 'newValue:' parameter}} +void Point3DSubscriptSetterTwoNewValues(Point3D point, unsigned x, float a, float b) __attribute__((swift_name("setter:Point3D.subscript(self:_:newValue:newValue:)"))); // expected-warning {{'swift_name' attribute for 'subscript' setter cannot take multiple 'newValue:' parameters}} +float Point3DSubscriptGetterNewValue(Point3D point, unsigned x, float a, float b) __attribute__((swift_name("getter:Point3D.subscript(self:_:newValue:newValue:)"))); // expected-warning {{'swift_name' attribute for 'subscript' getter cannot take a 'newValue:' parameter}} void Point3DMethodWithNewValue(Point3D point, float newValue) __attribute__((swift_name("Point3D.method(self:newValue:)"))); void Point3DMethodWithNewValues(Point3D point, float newValue, float newValueB) __attribute__((swift_name("Point3D.method(self:newValue:newValue:)"))); -float Point3DStaticSubscript(unsigned x) __attribute__((swift_name("getter:Point3D.subscript(_:)"))); // expected-error {{'swift_name' attribute for 'subscript' must take a 'self:' parameter}} -float Point3DStaticSubscriptNoArgs(void) __attribute__((swift_name("getter:Point3D.subscript()"))); // expected-error {{'swift_name' attribute for 'subscript' must take at least one parameter}} +float Point3DStaticSubscript(unsigned x) __attribute__((swift_name("getter:Point3D.subscript(_:)"))); // expected-warning {{'swift_name' attribute for 'subscript' must take a 'self:' parameter}} +float Point3DStaticSubscriptNoArgs(void) __attribute__((swift_name("getter:Point3D.subscript()"))); // expected-warning {{'swift_name' attribute for 'subscript' must take at least one parameter}} float Point3DPreGetComponent(Point3D point, unsigned index) __attribute__((swift_name("getter:Point3D.subscript(self:_:)"))); @@ -146,15 +146,15 @@ struct __attribute__((swift_name("FooStruct"))) BarStruct { void setLastPoint3D(Point3D point) __attribute__((swift_name("setter:lastPoint3D(newValue:)"))); Point3D getZeroPoint(void) __attribute__((swift_name("getter:Point3D.zero()"))); -Point3D getZeroPointNoPrototype() __attribute__((swift_name("getter:Point3D.zeroNoPrototype()"))); // expected-error{{'swift_name' attribute can only be applied to function declarations with prototypes}} +Point3D getZeroPointNoPrototype() __attribute__((swift_name("getter:Point3D.zeroNoPrototype()"))); // expected-warning{{'swift_name' attribute can only be applied to function declarations with prototypes}} void setZeroPoint(Point3D point) __attribute__((swift_name("setter:Point3D.zero(newValue:)"))); -Point3D badGetter1(int x) __attribute__((swift_name("getter:bad1(_:))"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} -void badSetter1(void) __attribute__((swift_name("getter:bad1())"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} +Point3D badGetter1(int x) __attribute__((swift_name("getter:bad1(_:))"))); // expected-warning{{parameter of 'swift_name' attribute must be a Swift function name string}} +void badSetter1(void) __attribute__((swift_name("getter:bad1())"))); // expected-warning{{parameter of 'swift_name' attribute must be a Swift function name string}} -Point3D badGetter2(Point3D point) __attribute__((swift_name("getter:bad2(_:))"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} +Point3D badGetter2(Point3D point) __attribute__((swift_name("getter:bad2(_:))"))); // expected-warning{{parameter of 'swift_name' attribute must be a Swift function name string}} -void badSetter2(Point3D point) __attribute__((swift_name("setter:bad2(self:))"))); // expected-error{{parameter of 'swift_name' attribute must be a Swift function name string}} +void badSetter2(Point3D point) __attribute__((swift_name("setter:bad2(self:))"))); // expected-warning{{parameter of 'swift_name' attribute must be a Swift function name string}} // --- swift_error --- From 6a04995c4cf751c0c9d395535f03ff8716864e73 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Thu, 19 May 2016 14:47:39 -0700 Subject: [PATCH 4/4] Collect swift_name warnings under a swift-name-attribute warning group. --- include/clang/Basic/DiagnosticGroups.td | 3 ++ include/clang/Basic/DiagnosticSemaKinds.td | 50 ++++++++++++++-------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index c97ae75329c..6084a1e4ef1 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -347,6 +347,9 @@ def StringCompare : DiagGroup<"string-compare">; def StringPlusInt : DiagGroup<"string-plus-int">; def StringPlusChar : DiagGroup<"string-plus-char">; def StrncatSize : DiagGroup<"strncat-size">; + +def SwiftNameAttribute : DiagGroup<"swift-name-attribute">; + def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">; def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">; def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7fad1b650e0..33a473c3b85 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3010,40 +3010,56 @@ def err_objc_attr_protocol_requires_definition : Error< // Swift attributes def warn_attr_swift_name_decl_kind : Warning< - "%0 attribute cannot be applied to this declaration">; + "%0 attribute cannot be applied to this declaration">, + InGroup; def warn_attr_swift_name_function : Warning< - "parameter of %0 attribute must be a Swift function name string">; + "parameter of %0 attribute must be a Swift function name string">, + InGroup; def warn_attr_swift_name_function_no_prototype : Warning< - "%0 attribute can only be applied to function declarations with prototypes">; + "%0 attribute can only be applied to function declarations with prototypes">, + InGroup; def warn_attr_swift_name_context_name_invalid_identifier : Warning< - "%0 attribute has invalid identifier for context name">; + "%0 attribute has invalid identifier for context name">, + InGroup; def warn_attr_swift_name_basename_invalid_identifier : Warning< - "%0 attribute has invalid identifier for base name">; + "%0 attribute has invalid identifier for base name">, + InGroup; def warn_attr_swift_name_parameter_invalid_identifier : Warning< - "%0 attribute has invalid identifier for parameter name">; + "%0 attribute has invalid identifier for parameter name">, + InGroup; def warn_attr_swift_name_missing_parameters : Warning< - "%0 attribute is missing parameter label clause">; + "%0 attribute is missing parameter label clause">, + InGroup; def warn_attr_swift_name_subscript_not_accessor : Warning< - "%0 attribute for 'subscript' must be a getter or setter">; + "%0 attribute for 'subscript' must be a getter or setter">, + InGroup; def warn_attr_swift_name_subscript_no_parameter : Warning< - "%0 attribute for 'subscript' must take at least one parameter">; + "%0 attribute for 'subscript' must take at least one parameter">, + InGroup; def warn_attr_swift_name_subscript_getter_newValue : Warning< - "%0 attribute for 'subscript' getter cannot take a 'newValue:' parameter">; + "%0 attribute for 'subscript' getter cannot take a 'newValue:' parameter">, + InGroup; def warn_attr_swift_name_subscript_setter_no_newValue : Warning< - "%0 attribute for 'subscript' setter must take a 'newValue:' parameter">; + "%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">; + "%0 attribute for 'subscript' setter cannot take multiple 'newValue:' parameters">, + InGroup; def warn_attr_swift_name_getter_parameters : Warning< - "%0 attribute for getter must not take any parameters besides 'self:'">; + "%0 attribute for getter must not take any parameters besides 'self:'">, + InGroup; def warn_attr_swift_name_setter_parameters : Warning< - "%0 attribute for setter must take one parameter for new value">; + "%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">; + "%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">; + "%0 attribute for 'subscript' must take a 'self:' parameter">, + InGroup; def warn_attr_swift_name_num_params : Warning< "too %select{few|many}0 parameters in %1 attribute (expected %2; got %3)">, - InGroup>; + 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">;