From: David Majnemer Date: Thu, 1 Aug 2013 06:13:59 +0000 (+0000) Subject: Sema: Diagnose explicitly bound unresolved member expressions decaying into pointers... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=576a9af150e4ddb34fd9cbede6eb5e3cf2bae9c8;p=clang Sema: Diagnose explicitly bound unresolved member expressions decaying into pointers to function type We would disallow the case where the overloaded member expression is coming from an address-of operator but we wouldn't issue any diagnostics when the overloaded member expression comes by way of a function to pointer decay cast. Clang's implementation of DR61 is now seemingly complete. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187559 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7241551893..1a9b82962b 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -9282,6 +9282,7 @@ class AddressOfFunctionResolver bool TargetTypeIsNonStaticMemberFunction; bool FoundNonTemplateFunction; + bool StaticMemberFunctionFromBoundPointer; OverloadExpr::FindResult OvlExprInfo; OverloadExpr *OvlExpr; @@ -9297,33 +9298,35 @@ public: TargetTypeIsNonStaticMemberFunction( !!TargetType->getAs()), FoundNonTemplateFunction(false), + StaticMemberFunctionFromBoundPointer(false), OvlExprInfo(OverloadExpr::find(SourceExpr)), OvlExpr(OvlExprInfo.Expression), FailedCandidates(OvlExpr->getNameLoc()) { ExtractUnqualifiedFunctionTypeFromTargetType(); - - if (!TargetFunctionType->isFunctionType()) { - if (OvlExpr->hasExplicitTemplateArgs()) { - DeclAccessPair dap; - if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( - OvlExpr, false, &dap) ) { - - if (CXXMethodDecl *Method = dyn_cast(Fn)) { - if (!Method->isStatic()) { - // If the target type is a non-function type and the function - // found is a non-static member function, pretend as if that was - // the target, it's the only possible type to end up with. - TargetTypeIsNonStaticMemberFunction = true; - - // And skip adding the function if its not in the proper form. - // We'll diagnose this due to an empty set of functions. - if (!OvlExprInfo.HasFormOfMemberPointer) - return; - } + + if (TargetFunctionType->isFunctionType()) { + if (UnresolvedMemberExpr *UME = dyn_cast(OvlExpr)) + if (!UME->isImplicitAccess() && + !S.ResolveSingleFunctionTemplateSpecialization(UME)) + StaticMemberFunctionFromBoundPointer = true; + } else if (OvlExpr->hasExplicitTemplateArgs()) { + DeclAccessPair dap; + if (FunctionDecl *Fn = S.ResolveSingleFunctionTemplateSpecialization( + OvlExpr, false, &dap)) { + if (CXXMethodDecl *Method = dyn_cast(Fn)) + if (!Method->isStatic()) { + // If the target type is a non-function type and the function found + // is a non-static member function, pretend as if that was the + // target, it's the only possible type to end up with. + TargetTypeIsNonStaticMemberFunction = true; + + // And skip adding the function if its not in the proper form. + // We'll diagnose this due to an empty set of functions. + if (!OvlExprInfo.HasFormOfMemberPointer) + return; } - Matches.push_back(std::make_pair(dap,Fn)); - } + Matches.push_back(std::make_pair(dap, Fn)); } return; } @@ -9536,7 +9539,7 @@ public: return TargetTypeIsNonStaticMemberFunction && !OvlExprInfo.HasFormOfMemberPointer; } - + void ComplainIsInvalidFormOfPointerToMemberFunction() const { // TODO: Should we condition this on whether any functions might // have matched, or is it more appropriate to do that in callers? @@ -9544,7 +9547,17 @@ public: S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier) << TargetType << OvlExpr->getSourceRange(); } - + + bool IsStaticMemberFunctionFromBoundPointer() const { + return StaticMemberFunctionFromBoundPointer; + } + + void ComplainIsStaticMemberFunctionFromBoundPointer() const { + S.Diag(OvlExpr->getLocStart(), + diag::err_invalid_form_pointer_member_function) + << OvlExpr->getSourceRange(); + } + void ComplainOfInvalidConversion() const { S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref) << OvlExpr->getName() << TargetType; @@ -9612,8 +9625,12 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, Fn = Resolver.getMatchingFunctionDecl(); assert(Fn); FoundResult = *Resolver.getMatchingFunctionAccessPair(); - if (Complain) - CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); + if (Complain) { + if (Resolver.IsStaticMemberFunctionFromBoundPointer()) + Resolver.ComplainIsStaticMemberFunctionFromBoundPointer(); + else + CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); + } } if (pHadMultipleCandidates) diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp index e00264102e..f8ac57f13f 100644 --- a/test/CXX/drs/dr0xx.cpp +++ b/test/CXX/drs/dr0xx.cpp @@ -659,6 +659,7 @@ namespace dr61 { // dr61: yes // function name. void (*p)() = &x.f; void (*q)() = &y.f; // expected-error {{cannot create a non-constant pointer to member function}} + void (*r)() = y.f; // expected-error {{cannot create a non-constant pointer to member function}} } namespace dr62 { // dr62: yes