Author: aaronballman Date: Thu Apr 12 09:41:55 2018 New Revision: 329924 URL: http://llvm.org/viewvc/llvm-project?rev=329924&view=rev Log: Correctly diagnose when a conversion function is declared with a type qualifier in the declaration specifiers rather than in the conversion type id. Fixes PR30595.
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/test/SemaCXX/conversion-function.cpp Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=329924&r1=329923&r2=329924&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Apr 12 09:41:55 2018 @@ -8319,7 +8319,8 @@ void Sema::CheckConversionDeclarator(Dec QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI); - if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { + const DeclSpec &DS = D.getDeclSpec(); + if (DS.hasTypeSpecifier() && !D.isInvalidType()) { // Conversion functions don't have return types, but the parser will // happily parse something like: // @@ -8329,9 +8330,18 @@ void Sema::CheckConversionDeclarator(Dec // // The return type will be changed later anyway. Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type) - << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(DS.getTypeSpecTypeLoc()) << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); + } else if (DS.getTypeQualifiers() && !D.isInvalidType()) { + // It's also plausible that the user writes type qualifiers in the wrong + // place, such as: + // struct S { const operator int(); }; + // FIXME: we could provide a fixit to move the qualifiers onto the + // conversion type. + Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl) + << SourceRange(D.getIdentifierLoc()) << 0; + D.setInvalidType(); } const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); @@ -8444,12 +8454,12 @@ void Sema::CheckConversionDeclarator(Dec R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo()); // C++0x explicit conversion operators. - if (D.getDeclSpec().isExplicitSpecified()) - Diag(D.getDeclSpec().getExplicitSpecLoc(), - getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_explicit_conversion_functions : - diag::ext_explicit_conversion_functions) - << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); + if (DS.isExplicitSpecified()) + Diag(DS.getExplicitSpecLoc(), + getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_explicit_conversion_functions + : diag::ext_explicit_conversion_functions) + << SourceRange(DS.getExplicitSpecLoc()); } /// ActOnConversionDeclarator - Called by ActOnDeclarator to complete Modified: cfe/trunk/test/SemaCXX/conversion-function.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-function.cpp?rev=329924&r1=329923&r2=329924&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/conversion-function.cpp (original) +++ cfe/trunk/test/SemaCXX/conversion-function.cpp Thu Apr 12 09:41:55 2018 @@ -444,3 +444,13 @@ namespace PR18234 { bool k1 = e == A::e; // expected-error {{no member named 'e'}} bool k2 = e.n == 0; } + +namespace PR30595 { +struct S { + const operator int(); // expected-error {{cannot specify any part of a return type in the declaration of a conversion function; put the complete type after 'operator'}} + const operator int() const; // expected-error {{cannot specify any part of a return type}} + volatile const operator int(); // expected-error {{cannot specify any part of a return type}} + + operator const int() const; +}; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits