diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaCXXCast.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 90 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 50 |
3 files changed, 89 insertions, 69 deletions
diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index 11c8e6ddab5..37df2a60005 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<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; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index e039669257b..53e05eed60a 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; - - // 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); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 28d6f0a40aa..65e0e5e95e8 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -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(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<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, @@ -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())) - 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); |

