summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp26
-rw-r--r--clang/test/SemaCXX/conversion-function.cpp10
2 files changed, 28 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 08d3bc21a24..8bf4b5a0499 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -8319,7 +8319,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
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(Declarator &D, QualType &R,
//
// 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(Declarator &D, QualType &R,
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
diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp
index 531de818b68..1d3593d8ed1 100644
--- a/clang/test/SemaCXX/conversion-function.cpp
+++ b/clang/test/SemaCXX/conversion-function.cpp
@@ -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;
+};
+}
OpenPOWER on IntegriCloud