george.burgess.iv created this revision. george.burgess.iv added a reviewer: rsmith. george.burgess.iv added a subscriber: cfe-commits.
Given code like the following (stolen from tests): ``` template <typename T1, typename T2> int f(T1 *, const T2 *); template <typename T1, typename T2> int f(const T1 *, T2 *); int (*p)(const int *, const int *) = f; ``` Clang will currently emit two "address of overloaded function f is ambiguous" errors for the same assignment (on line 3). This patch makes us only emit one. http://reviews.llvm.org/D13664 Files: lib/Sema/SemaOverload.cpp test/SemaCXX/addr-of-overloaded-function.cpp Index: test/SemaCXX/addr-of-overloaded-function.cpp =================================================================== --- test/SemaCXX/addr-of-overloaded-function.cpp +++ test/SemaCXX/addr-of-overloaded-function.cpp @@ -125,13 +125,9 @@ } namespace PR8033 { - template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note {{candidate function [with T1 = const int, T2 = int]}} \ - // expected-note{{candidate function}} - template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note {{candidate function [with T1 = int, T2 = const int]}} \ - // expected-note{{candidate function}} - int (*p)(const int *, const int *) = f; // expected-error{{address of overloaded function 'f' is ambiguous}} \ - // expected-error{{address of overloaded function 'f' is ambiguous}} - + template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note {{candidate function [with T1 = const int, T2 = int]}} + template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note {{candidate function [with T1 = int, T2 = const int]}} + int (*p)(const int *, const int *) = f; // expected-error{{address of overloaded function 'f' is ambiguous}} } namespace PR8196 { Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -9911,6 +9911,7 @@ bool TargetTypeIsNonStaticMemberFunction; bool FoundNonTemplateFunction; bool StaticMemberFunctionFromBoundPointer; + bool HasComplained; OverloadExpr::FindResult OvlExprInfo; OverloadExpr *OvlExpr; @@ -9927,6 +9928,7 @@ !!TargetType->getAs<MemberPointerType>()), FoundNonTemplateFunction(false), StaticMemberFunctionFromBoundPointer(false), + HasComplained(false), OvlExprInfo(OverloadExpr::find(SourceExpr)), OvlExpr(OvlExprInfo.Expression), FailedCandidates(OvlExpr->getNameLoc()) { @@ -9977,7 +9979,9 @@ Matches.size() > 1) EliminateSuboptimalCudaMatches(); } - + + bool hasComplained() const { return HasComplained; } + private: bool isTargetTypeAFunction() const { return TargetFunctionType->isFunctionType(); @@ -10056,9 +10060,12 @@ // If any candidate has a placeholder return type, trigger its deduction // now. if (S.getLangOpts().CPlusPlus14 && - FunDecl->getReturnType()->isUndeducedType() && - S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) - return false; + FunDecl->getReturnType()->isUndeducedType()) { + if (S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) { + HasComplained |= Complain; + return false; + } + } QualType ResultTy; if (Context.hasSameUnqualifiedType(TargetFunctionType, @@ -10140,7 +10147,8 @@ Matches[0].first = Matches[Result - MatchesCopy.begin()].first; Matches[0].second = cast<FunctionDecl>(*Result); Matches.resize(1); - } + } else + HasComplained |= Complain; } void EliminateAllTemplateMatches() { @@ -10261,13 +10269,14 @@ Complain); int NumMatches = Resolver.getNumMatches(); FunctionDecl *Fn = nullptr; - if (NumMatches == 0 && Complain) { + bool ShouldComplain = Complain && !Resolver.hasComplained(); + if (NumMatches == 0 && ShouldComplain) { if (Resolver.IsInvalidFormOfPointerToMemberFunction()) Resolver.ComplainIsInvalidFormOfPointerToMemberFunction(); else Resolver.ComplainNoMatchesFound(); } - else if (NumMatches > 1 && Complain) + else if (NumMatches > 1 && ShouldComplain) Resolver.ComplainMultipleMatchesFound(); else if (NumMatches == 1) { Fn = Resolver.getMatchingFunctionDecl();
Index: test/SemaCXX/addr-of-overloaded-function.cpp =================================================================== --- test/SemaCXX/addr-of-overloaded-function.cpp +++ test/SemaCXX/addr-of-overloaded-function.cpp @@ -125,13 +125,9 @@ } namespace PR8033 { - template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note {{candidate function [with T1 = const int, T2 = int]}} \ - // expected-note{{candidate function}} - template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note {{candidate function [with T1 = int, T2 = const int]}} \ - // expected-note{{candidate function}} - int (*p)(const int *, const int *) = f; // expected-error{{address of overloaded function 'f' is ambiguous}} \ - // expected-error{{address of overloaded function 'f' is ambiguous}} - + template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note {{candidate function [with T1 = const int, T2 = int]}} + template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note {{candidate function [with T1 = int, T2 = const int]}} + int (*p)(const int *, const int *) = f; // expected-error{{address of overloaded function 'f' is ambiguous}} } namespace PR8196 { Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -9911,6 +9911,7 @@ bool TargetTypeIsNonStaticMemberFunction; bool FoundNonTemplateFunction; bool StaticMemberFunctionFromBoundPointer; + bool HasComplained; OverloadExpr::FindResult OvlExprInfo; OverloadExpr *OvlExpr; @@ -9927,6 +9928,7 @@ !!TargetType->getAs<MemberPointerType>()), FoundNonTemplateFunction(false), StaticMemberFunctionFromBoundPointer(false), + HasComplained(false), OvlExprInfo(OverloadExpr::find(SourceExpr)), OvlExpr(OvlExprInfo.Expression), FailedCandidates(OvlExpr->getNameLoc()) { @@ -9977,7 +9979,9 @@ Matches.size() > 1) EliminateSuboptimalCudaMatches(); } - + + bool hasComplained() const { return HasComplained; } + private: bool isTargetTypeAFunction() const { return TargetFunctionType->isFunctionType(); @@ -10056,9 +10060,12 @@ // If any candidate has a placeholder return type, trigger its deduction // now. if (S.getLangOpts().CPlusPlus14 && - FunDecl->getReturnType()->isUndeducedType() && - S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) - return false; + FunDecl->getReturnType()->isUndeducedType()) { + if (S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) { + HasComplained |= Complain; + return false; + } + } QualType ResultTy; if (Context.hasSameUnqualifiedType(TargetFunctionType, @@ -10140,7 +10147,8 @@ Matches[0].first = Matches[Result - MatchesCopy.begin()].first; Matches[0].second = cast<FunctionDecl>(*Result); Matches.resize(1); - } + } else + HasComplained |= Complain; } void EliminateAllTemplateMatches() { @@ -10261,13 +10269,14 @@ Complain); int NumMatches = Resolver.getNumMatches(); FunctionDecl *Fn = nullptr; - if (NumMatches == 0 && Complain) { + bool ShouldComplain = Complain && !Resolver.hasComplained(); + if (NumMatches == 0 && ShouldComplain) { if (Resolver.IsInvalidFormOfPointerToMemberFunction()) Resolver.ComplainIsInvalidFormOfPointerToMemberFunction(); else Resolver.ComplainNoMatchesFound(); } - else if (NumMatches > 1 && Complain) + else if (NumMatches > 1 && ShouldComplain) Resolver.ComplainMultipleMatchesFound(); else if (NumMatches == 1) { Fn = Resolver.getMatchingFunctionDecl();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits