Always diagnose and complain about problems in

ResolveAddressOfOverloadedFunction when asked to complain. Previously,
we had some weird handshake where ResolveAddressOfOverloadedFunction
expected its caller to handle some of the diagnostics but not others,
and yet there was no way for the caller to know which case we were
in. Eliminate this madness, fixing <rdar://problem/7765884>.

llvm-svn: 101312
This commit is contained in:
Douglas Gregor 2010-04-14 23:11:21 +00:00
parent 1deb972b55
commit 064fdb2fe8
6 changed files with 115 additions and 78 deletions

View File

@ -1122,8 +1122,12 @@ def err_member_call_without_object : Error<
"call to non-static member function without an object argument">;
// C++ Address of Overloaded Function
def err_addr_ovl_no_viable : Error<
"address of overloaded function %0 does not match required type %1">;
def err_addr_ovl_ambiguous : Error<
"address of overloaded function %0 is ambiguous">;
def err_addr_ovl_not_func_ptrref : Error<
"address of overloaded function %0 cannot be converted to type %1">;
// C++ Template Declarations
def err_template_param_shadow : Error<
@ -1239,9 +1243,6 @@ def err_template_arg_no_ref_bind : Error<
def err_template_arg_ref_bind_ignores_quals : Error<
"reference binding of non-type template parameter of type %0 to template "
"argument of type %1 ignores qualifiers">;
def err_template_arg_unresolved_overloaded_function : Error<
"overloaded function cannot be resolved to a non-type template parameter of "
"type %0">;
def err_template_arg_not_decl_ref : Error<
"non-type template argument does not refer to any declaration">;
def err_template_arg_not_object_or_func_form : Error<

View File

@ -809,6 +809,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
bool WasOverloadedFunction = false;
DeclAccessPair FoundOverload;
if (SrcExpr->getType() == Self.Context.OverloadTy) {
if (FunctionDecl *Fn
= Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false,
FoundOverload)) {
@ -817,6 +818,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
WasOverloadedFunction = true;
}
}
const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>();
if (!SrcMemPtr) {

View File

@ -613,7 +613,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// type "pointer to T." The result is a pointer to the
// function. (C++ 4.3p1).
FromType = Context.getPointerType(FromType);
} else if (FunctionDecl *Fn
} else if (From->getType() == Context.OverloadTy) {
if (FunctionDecl *Fn
= ResolveAddressOfOverloadedFunction(From, ToType, false,
AccessPair)) {
// Address of overloaded function (C++ [over.over]).
@ -636,8 +637,12 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
FromType = Context.getMemberPointerType(FromType,
Context.getTypeDeclType(M->getParent()).getTypePtr());
} else
} else {
FromType = Context.getPointerType(FromType);
}
} else {
return false;
}
} else {
// We don't require any conversions for the first step.
SCS.First = ICK_Identity;
@ -5295,15 +5300,6 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
IsMember = true;
}
// We only look at pointers or references to functions.
FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
if (!FunctionType->isFunctionType())
return 0;
// Find the actual overloaded function declaration.
if (From->getType() != Context.OverloadTy)
return 0;
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
// overloaded function name is ignored (5.1). ]
@ -5317,6 +5313,18 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
ExplicitTemplateArgs = &ETABuffer;
}
// We expect a pointer or reference to function, or a function pointer.
FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
if (!FunctionType->isFunctionType()) {
if (Complain)
Diag(From->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
<< OvlExpr->getName() << ToType;
return 0;
}
assert(From->getType() == Context.OverloadTy);
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
@ -5397,9 +5405,19 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
}
// If there were 0 or 1 matches, we're done.
if (Matches.empty())
if (Matches.empty()) {
if (Complain) {
Diag(From->getLocStart(), diag::err_addr_ovl_no_viable)
<< OvlExpr->getName() << FunctionType;
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
E = OvlExpr->decls_end();
I != E; ++I)
if (FunctionDecl *F = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
NoteOverloadCandidate(F);
}
return 0;
else if (Matches.size() == 1) {
} else if (Matches.size() == 1) {
FunctionDecl *Result = Matches[0].second;
FoundResult = Matches[0].first;
MarkDeclarationReferenced(From->getLocStart(), Result);

View File

@ -2368,14 +2368,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
DRE = dyn_cast<DeclRefExpr>(Arg);
if (!DRE) {
if (S.Context.hasSameUnqualifiedType(ArgType, S.Context.OverloadTy)) {
S.Diag(Arg->getLocStart(),
diag::err_template_arg_unresolved_overloaded_function)
<< ParamType << Arg->getSourceRange();
} else {
S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
<< Arg->getSourceRange();
}
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
@ -2848,6 +2842,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ParamType->getAs<MemberPointerType>()->getPointeeType()
->isFunctionType())) {
if (Arg->getType() == Context.OverloadTy) {
if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
true,
FoundResult)) {
@ -2856,6 +2851,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
ArgType = Arg->getType();
} else
return true;
}
if (!ParamType->isMemberPointerType())
@ -2902,6 +2899,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
assert(ParamRefType->getPointeeType()->isObjectType() &&
"Only object references allowed here");
if (Arg->getType() == Context.OverloadTy) {
if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg,
ParamRefType->getPointeeType(),
true,
@ -2911,6 +2909,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
ArgType = Arg->getType();
} else
return true;
}
return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,

View File

@ -54,3 +54,19 @@ struct B
void d(void *);
static void d(A *);
};
struct C {
C &getC() {
return makeAC; // expected-error{{address of overloaded function 'makeAC' cannot be converted to type 'C'}}
}
C &makeAC();
const C &makeAC() const;
static void f(); // expected-note{{candidate function}}
static void f(int); // expected-note{{candidate function}}
void g() {
int (&fp)() = f; // expected-error{{address of overloaded function 'f' does not match required type 'int ()'}}
}
};

View File

@ -36,19 +36,19 @@ A<X(17, 42)> *a11; // expected-error{{non-type template argument of type 'X' mus
float f(float);
float g(float);
double g(double);
float g(float); // expected-note 2{{candidate function}}
double g(double); // expected-note 2{{candidate function}}
int h(int);
float h2(float);
template<int fp(int)> struct A3; // expected-note 2{{template parameter is declared here}}
template<int fp(int)> struct A3; // expected-note 1{{template parameter is declared here}}
A3<h> *a14_1;
A3<&h> *a14_2;
A3<f> *a14_3;
A3<&f> *a14_4;
A3<h2> *a14_6; // expected-error{{non-type template argument of type 'float (float)' cannot be converted to a value of type 'int (*)(int)'}}
A3<g> *a14_7; // expected-error{{overloaded function cannot be resolved to a non-type template parameter of type 'int (*)(int)'}}
A3<g> *a14_7; // expected-error{{address of overloaded function 'g' does not match required type 'int (int)'}}
struct Y { } y;
@ -61,11 +61,11 @@ A4<*X_volatile_ptr> *a15_2; // expected-error{{non-type template argument does n
A4<y> *15_3; // expected-error{{non-type template parameter of reference type 'X const &' cannot bind to template argument of type 'struct Y'}} \
// FIXME: expected-error{{expected unqualified-id}}
template<int (&fr)(int)> struct A5; // expected-note 2{{template parameter is declared here}}
template<int (&fr)(int)> struct A5; // expected-note{{template parameter is declared here}}
A5<h> *a16_1;
A5<f> *a16_3;
A5<h2> *a16_6; // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'float (float)'}}
A5<g> *a14_7; // expected-error{{overloaded function cannot be resolved to a non-type template parameter of type 'int (&)(int)'}}
A5<g> *a14_7; // expected-error{{address of overloaded function 'g' does not match required type 'int (int)'}}
struct Z {
int foo(int);