forked from OSchip/llvm-project
Diagnose declarations of conversion functions with declarators other than '()'.
llvm-svn: 101098
This commit is contained in:
parent
5dbefc6697
commit
212fa2efb7
|
@ -2637,6 +2637,8 @@ def err_conv_function_to_array : Error<
|
||||||
"conversion function cannot convert to an array type">;
|
"conversion function cannot convert to an array type">;
|
||||||
def err_conv_function_to_function : Error<
|
def err_conv_function_to_function : Error<
|
||||||
"conversion function cannot convert to a function type">;
|
"conversion function cannot convert to a function type">;
|
||||||
|
def err_conv_function_with_complex_decl : Error<
|
||||||
|
"must use a typedef to declare a conversion to %0">;
|
||||||
def err_conv_function_redeclared : Error<
|
def err_conv_function_redeclared : Error<
|
||||||
"conversion function cannot be redeclared">;
|
"conversion function cannot be redeclared">;
|
||||||
def warn_conv_to_self_not_used : Warning<
|
def warn_conv_to_self_not_used : Warning<
|
||||||
|
|
|
@ -2828,6 +2828,9 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
|
||||||
D.setInvalidType();
|
D.setInvalidType();
|
||||||
SC = FunctionDecl::None;
|
SC = FunctionDecl::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
|
||||||
|
|
||||||
if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
|
if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
|
||||||
// Conversion functions don't have return types, but the parser will
|
// Conversion functions don't have return types, but the parser will
|
||||||
// happily parse something like:
|
// happily parse something like:
|
||||||
|
@ -2840,27 +2843,35 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
|
||||||
Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
|
||||||
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
|
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
|
||||||
<< SourceRange(D.getIdentifierLoc());
|
<< SourceRange(D.getIdentifierLoc());
|
||||||
|
D.setInvalidType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
|
||||||
|
|
||||||
// Make sure we don't have any parameters.
|
// Make sure we don't have any parameters.
|
||||||
if (R->getAs<FunctionProtoType>()->getNumArgs() > 0) {
|
if (Proto->getNumArgs() > 0) {
|
||||||
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
|
||||||
|
|
||||||
// Delete the parameters.
|
// Delete the parameters.
|
||||||
D.getTypeObject(0).Fun.freeArgs();
|
D.getTypeObject(0).Fun.freeArgs();
|
||||||
D.setInvalidType();
|
D.setInvalidType();
|
||||||
}
|
} else if (Proto->isVariadic()) {
|
||||||
|
|
||||||
// Make sure the conversion function isn't variadic.
|
|
||||||
if (R->getAs<FunctionProtoType>()->isVariadic() && !D.isInvalidType()) {
|
|
||||||
Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
|
||||||
D.setInvalidType();
|
D.setInvalidType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Diagnose "&operator bool()" and other such nonsense. This
|
||||||
|
// is actually a gcc extension which we don't support.
|
||||||
|
if (Proto->getResultType() != ConvType) {
|
||||||
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
|
||||||
|
<< Proto->getResultType();
|
||||||
|
D.setInvalidType();
|
||||||
|
ConvType = Proto->getResultType();
|
||||||
|
}
|
||||||
|
|
||||||
// C++ [class.conv.fct]p4:
|
// C++ [class.conv.fct]p4:
|
||||||
// The conversion-type-id shall not represent a function type nor
|
// The conversion-type-id shall not represent a function type nor
|
||||||
// an array type.
|
// an array type.
|
||||||
QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
|
|
||||||
if (ConvType->isArrayType()) {
|
if (ConvType->isArrayType()) {
|
||||||
Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
|
Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
|
||||||
ConvType = Context.getPointerType(ConvType);
|
ConvType = Context.getPointerType(ConvType);
|
||||||
|
@ -2874,7 +2885,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
|
||||||
// Rebuild the function type "R" without any parameters (in case any
|
// Rebuild the function type "R" without any parameters (in case any
|
||||||
// of the errors above fired) and with the conversion type as the
|
// of the errors above fired) and with the conversion type as the
|
||||||
// return type.
|
// return type.
|
||||||
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
|
if (D.isInvalidType()) {
|
||||||
R = Context.getFunctionType(ConvType, 0, 0, false,
|
R = Context.getFunctionType(ConvType, 0, 0, false,
|
||||||
Proto->getTypeQuals(),
|
Proto->getTypeQuals(),
|
||||||
Proto->hasExceptionSpec(),
|
Proto->hasExceptionSpec(),
|
||||||
|
@ -2882,6 +2893,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
|
||||||
Proto->getNumExceptions(),
|
Proto->getNumExceptions(),
|
||||||
Proto->exception_begin(),
|
Proto->exception_begin(),
|
||||||
Proto->getExtInfo());
|
Proto->getExtInfo());
|
||||||
|
}
|
||||||
|
|
||||||
// C++0x explicit conversion operators.
|
// C++0x explicit conversion operators.
|
||||||
if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x)
|
if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x)
|
||||||
|
|
|
@ -165,3 +165,14 @@ namespace source_locations {
|
||||||
|
|
||||||
E2<int&> e2i; // expected-note{{in instantiation}}
|
E2<int&> e2i; // expected-note{{in instantiation}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace crazy_declarators {
|
||||||
|
struct A {
|
||||||
|
(&operator bool())(); // expected-error {{must use a typedef to declare a conversion to 'bool (&)()'}}
|
||||||
|
|
||||||
|
// FIXME: This diagnostic is misleading (the correct spelling
|
||||||
|
// would be 'operator int*'), but it's a corner case of a
|
||||||
|
// rarely-used syntax extension.
|
||||||
|
*operator int(); // expected-error {{must use a typedef to declare a conversion to 'int *'}}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue