"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<
"declaration of %0 shadows template parameter">;
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<
bool WasOverloadedFunction = false;
DeclAccessPair FoundOverload;
- if (FunctionDecl *Fn
- = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false,
- FoundOverload)) {
- CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
- SrcType = Self.Context.getMemberPointerType(Fn->getType(),
- Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
- WasOverloadedFunction = true;
+ if (SrcExpr->getType() == Self.Context.OverloadTy) {
+ if (FunctionDecl *Fn
+ = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false,
+ FoundOverload)) {
+ CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
+ SrcType = Self.Context.getMemberPointerType(Fn->getType(),
+ Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
+ WasOverloadedFunction = true;
+ }
}
-
+
const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>();
if (!SrcMemPtr) {
msg = diag::err_bad_static_cast_member_pointer_nonmp;
// type "pointer to T." The result is a pointer to the
// function. (C++ 4.3p1).
FromType = Context.getPointerType(FromType);
- } else if (FunctionDecl *Fn
- = ResolveAddressOfOverloadedFunction(From, ToType, false,
- AccessPair)) {
- // Address of overloaded function (C++ [over.over]).
- SCS.First = ICK_Function_To_Pointer;
-
- // We were able to resolve the address of the overloaded function,
- // so we can convert to the type of that function.
- FromType = Fn->getType();
- if (ToType->isLValueReferenceType())
- FromType = Context.getLValueReferenceType(FromType);
- else if (ToType->isRValueReferenceType())
- FromType = Context.getRValueReferenceType(FromType);
- else if (ToType->isMemberPointerType()) {
- // Resolve address only succeeds if both sides are member pointers,
- // but it doesn't have to be the same class. See DR 247.
- // Note that this means that the type of &Derived::fn can be
- // Ret (Base::*)(Args) if the fn overload actually found is from the
- // base class, even if it was brought into the derived class via a
- // using declaration. The standard isn't clear on this issue at all.
- CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
- FromType = Context.getMemberPointerType(FromType,
- Context.getTypeDeclType(M->getParent()).getTypePtr());
- } else
- FromType = Context.getPointerType(FromType);
+ } else if (From->getType() == Context.OverloadTy) {
+ if (FunctionDecl *Fn
+ = ResolveAddressOfOverloadedFunction(From, ToType, false,
+ AccessPair)) {
+ // Address of overloaded function (C++ [over.over]).
+ SCS.First = ICK_Function_To_Pointer;
+
+ // We were able to resolve the address of the overloaded function,
+ // so we can convert to the type of that function.
+ FromType = Fn->getType();
+ if (ToType->isLValueReferenceType())
+ FromType = Context.getLValueReferenceType(FromType);
+ else if (ToType->isRValueReferenceType())
+ FromType = Context.getRValueReferenceType(FromType);
+ else if (ToType->isMemberPointerType()) {
+ // Resolve address only succeeds if both sides are member pointers,
+ // but it doesn't have to be the same class. See DR 247.
+ // Note that this means that the type of &Derived::fn can be
+ // Ret (Base::*)(Args) if the fn overload actually found is from the
+ // base class, even if it was brought into the derived class via a
+ // using declaration. The standard isn't clear on this issue at all.
+ CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
+ FromType = Context.getMemberPointerType(FromType,
+ Context.getTypeDeclType(M->getParent()).getTypePtr());
+ } else {
+ FromType = Context.getPointerType(FromType);
+ }
+ } else {
+ return false;
+ }
} else {
// We don't require any conversions for the first step.
SCS.First = ICK_Identity;
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). ]
OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
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.
}
// 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);
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(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
+ << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
ParamType->getAs<MemberPointerType>()->getPointeeType()
->isFunctionType())) {
- if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
- true,
- FoundResult)) {
- if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
- return true;
+ if (Arg->getType() == Context.OverloadTy) {
+ if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
+ true,
+ FoundResult)) {
+ if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+ return true;
- Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
- ArgType = Arg->getType();
+ Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+ ArgType = Arg->getType();
+ } else
+ return true;
}
-
+
if (!ParamType->isMemberPointerType())
return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
ParamType,
assert(ParamRefType->getPointeeType()->isObjectType() &&
"Only object references allowed here");
- if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg,
- ParamRefType->getPointeeType(),
- true,
- FoundResult)) {
- if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
- return true;
+ if (Arg->getType() == Context.OverloadTy) {
+ if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg,
+ ParamRefType->getPointeeType(),
+ true,
+ FoundResult)) {
+ if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+ return true;
- Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
- ArgType = Arg->getType();
+ Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+ ArgType = Arg->getType();
+ } else
+ return true;
}
-
+
return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
ParamType,
Arg, Converted);
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 ()'}}
+ }
+};
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;
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);