diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 308f6b4dc0..82526119e2 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1345,6 +1345,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { case PredefinedExprClass: return LV_Valid; case UnresolvedLookupExprClass: + case UnresolvedMemberExprClass: return LV_Valid; case CXXDefaultArgExprClass: return cast(this)->getExpr()->isLvalue(Ctx); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 7c324235ca..60ced725e9 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1660,6 +1660,21 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, return false; } + // Resolve overloaded function references. + if (Context.hasSameType(FromType, Context.OverloadTy)) { + DeclAccessPair Found; + FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, + true, Found); + if (!Fn) + return true; + + if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) + return true; + + From = FixOverloadedFunctionReference(From, Found, Fn); + FromType = From->getType(); + } + // Perform the first implicit conversion. switch (SCS.First) { case ICK_Identity: @@ -1673,25 +1688,6 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; case ICK_Function_To_Pointer: - if (Context.getCanonicalType(FromType) == Context.OverloadTy) { - DeclAccessPair Found; - FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, - true, Found); - if (!Fn) - return true; - - if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) - return true; - - From = FixOverloadedFunctionReference(From, Found, Fn); - FromType = From->getType(); - - // If there's already an address-of operator in the expression, we have - // the right type already, and the code below would just introduce an - // invalid additional pointer level. - if (FromType->isPointerType() || FromType->isMemberFunctionPointerType()) - break; - } FromType = Context.getPointerType(FromType); ImpCastExprToType(From, FromType, CastExpr::CK_FunctionToPointerDecay); break; diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 06b5fcb318..2a2521a32c 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -622,8 +622,36 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // array-to-pointer conversion, or function-to-pointer conversion // (C++ 4p1). - DeclAccessPair AccessPair; - + if (FromType == Context.OverloadTy) { + DeclAccessPair AccessPair; + if (FunctionDecl *Fn + = ResolveAddressOfOverloadedFunction(From, ToType, false, + AccessPair)) { + // 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 (CXXMethodDecl *Method = dyn_cast(Fn)) { + if (!Method->isStatic()) { + Type *ClassType + = Context.getTypeDeclType(Method->getParent()).getTypePtr(); + FromType = Context.getMemberPointerType(FromType, ClassType); + } + } + + // If the "from" expression takes the address of the overloaded + // function, update the type of the resulting expression accordingly. + if (FromType->getAs()) + if (UnaryOperator *UnOp = dyn_cast(From->IgnoreParens())) + if (UnOp->getOpcode() == UnaryOperator::AddrOf) + FromType = Context.getPointerType(FromType); + + // Check that we've computed the proper type after overload resolution. + assert(Context.hasSameType(FromType, + FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); + } else { + return false; + } + } // Lvalue-to-rvalue conversion (C++ 4.1): // An lvalue (3.10) of a non-function, non-array type T can be // converted to an rvalue. @@ -668,36 +696,6 @@ 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 (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); - } - } else { - return false; - } } else { // We don't require any conversions for the first step. SCS.First = ICK_Identity; diff --git a/test/CodeGenCXX/address-of-fntemplate.cpp b/test/CodeGenCXX/address-of-fntemplate.cpp index c5fa89d86d..162c6e5754 100644 --- a/test/CodeGenCXX/address-of-fntemplate.cpp +++ b/test/CodeGenCXX/address-of-fntemplate.cpp @@ -11,3 +11,17 @@ void test() { } // CHECK: define linkonce_odr void @_Z1fIiEvT_ // CHECK: define linkonce_odr void @_Z1fIiEvv + +namespace PR6973 { + template + struct X { + void f(const T&); + }; + + template + int g(); + + void h(X xf) { + xf.f(&g); + } +}