diff options
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 90 |
1 files changed, 54 insertions, 36 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index e039669257..53e05eed60 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/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; - - // 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; @@ -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<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); |