diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4b4780e09b49..231031829fc0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1122,9 +1122,13 @@ 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< "declaration of %0 shadows template parameter">; @@ -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< diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index 11c8e6ddab5c..37df2a60005f 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -809,15 +809,17 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, bool WasOverloadedFunction = false; DeclAccessPair FoundOverload; - if (FunctionDecl *Fn - = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false, - FoundOverload)) { - CXXMethodDecl *M = cast(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(Fn); + SrcType = Self.Context.getMemberPointerType(Fn->getType(), + Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); + WasOverloadedFunction = true; + } } - + const MemberPointerType *SrcMemPtr = SrcType->getAs(); if (!SrcMemPtr) { msg = diag::err_bad_static_cast_member_pointer_nonmp; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index e039669257ba..53e05eed60a1 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -613,31 +613,36 @@ 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 - = ResolveAddressOfOverloadedFunction(From, ToType, false, - AccessPair)) { - // Address of overloaded function (C++ [over.over]). - SCS.First = ICK_Function_To_Pointer; + } 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(Fn); - FromType = Context.getMemberPointerType(FromType, - Context.getTypeDeclType(M->getParent()).getTypePtr()); - } else - FromType = Context.getPointerType(FromType); + // 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(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; @@ -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). ] @@ -5316,6 +5312,18 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, 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. @@ -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((*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); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 28d6f0a40aa8..65e0e5e95e89 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2368,14 +2368,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, DRE = dyn_cast(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; } @@ -2848,16 +2842,19 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, ParamType->getAs()->getPointeeType() ->isFunctionType())) { - if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, - true, - FoundResult)) { - if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) + 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(); + } else return true; - - Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); - ArgType = Arg->getType(); } - + if (!ParamType->isMemberPointerType()) return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, ParamType, @@ -2902,17 +2899,20 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, assert(ParamRefType->getPointeeType()->isObjectType() && "Only object references allowed here"); - if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, - ParamRefType->getPointeeType(), - true, - FoundResult)) { - if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) + 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(); + } else return true; - - Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); - ArgType = Arg->getType(); } - + return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, ParamType, Arg, Converted); diff --git a/clang/test/SemaCXX/addr-of-overloaded-function.cpp b/clang/test/SemaCXX/addr-of-overloaded-function.cpp index 3b06119393d0..391fc3095986 100644 --- a/clang/test/SemaCXX/addr-of-overloaded-function.cpp +++ b/clang/test/SemaCXX/addr-of-overloaded-function.cpp @@ -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 ()'}} + } +}; diff --git a/clang/test/SemaTemplate/temp_arg_nontype.cpp b/clang/test/SemaTemplate/temp_arg_nontype.cpp index 6e4f751d47d1..1d23c3df0847 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype.cpp @@ -36,19 +36,19 @@ A *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 struct A3; // expected-note 2{{template parameter is declared here}} +template struct A3; // expected-note 1{{template parameter is declared here}} A3 *a14_1; A3<&h> *a14_2; A3 *a14_3; A3<&f> *a14_4; A3

*a14_6; // expected-error{{non-type template argument of type 'float (float)' cannot be converted to a value of type 'int (*)(int)'}} -A3 *a14_7; // expected-error{{overloaded function cannot be resolved to a non-type template parameter of type 'int (*)(int)'}} +A3 *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 *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 struct A5; // expected-note 2{{template parameter is declared here}} +template struct A5; // expected-note{{template parameter is declared here}} A5 *a16_1; A5 *a16_3; A5

*a16_6; // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'float (float)'}} -A5 *a14_7; // expected-error{{overloaded function cannot be resolved to a non-type template parameter of type 'int (&)(int)'}} +A5 *a14_7; // expected-error{{address of overloaded function 'g' does not match required type 'int (int)'}} struct Z { int foo(int);