ecatmur created this revision. Herald added a project: All. ecatmur requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
clang correctly rejects as ambiguous: template<class T> int f(T&, int); // 1 template<class T, class U> int f(T const&, U); // 2 int g(int const& i) { return f(i, 0); } However if the order of template parameters in (2) is swapped: template<class T> int f(T&, int); // 1 template<class U, class T> int f(T const&, U); // 2' int g(int const& i) { return f(i, 0); } clang incorrectly accepts, calling (1). All versions tested up to current trunk incorrectly accept; 3.6 and older also incorrectly accept the first case. gcc correctly rejects both cases since 4.5, incorrectly accepting in earlier versions. icc 13 onwards correctly rejects. MSVC correctly rejects (although it has other bugs in this area). The problem appears to be that DeduceTemplateArgumentsByTypeMatch incorrectly believes that P and A are distinct; P is type-parameter-0-1 whereas A is type-parameter-0-0. I believe this can be fixed simply by removing the hasSameUnqualifiedType check, since if the types are dissimilar the call would fail later anyway, Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D121517 Files: clang/lib/Sema/SemaTemplateDeduction.cpp clang/test/SemaCXX/overload-call.cpp Index: clang/test/SemaCXX/overload-call.cpp =================================================================== --- clang/test/SemaCXX/overload-call.cpp +++ clang/test/SemaCXX/overload-call.cpp @@ -688,3 +688,13 @@ f(pmf); } } + +namespace PR54347 { + template<class T> void f(T&, int); + template<class U, class T> void f(T const&, U); + void g(int const& i) { f(i, 0); } // expected-error {{ambiguous}} + + template<class T> void f(T(&)[5], int); + template<class U, class T> void f(T const(&)[5], U); + void g(int const(& a)[5]) { f(a, 0); } // expected-error {{ambiguous}} +} Index: clang/lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- clang/lib/Sema/SemaTemplateDeduction.cpp +++ clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1358,7 +1358,7 @@ if (ARef) A = A->getPointeeType(); - if (PRef && ARef && S.Context.hasSameUnqualifiedType(P, A)) { + if (PRef && ARef) { // C++11 [temp.deduct.partial]p9: // If, for a given type, deduction succeeds in both directions (i.e., // the types are identical after the transformations above) and both
Index: clang/test/SemaCXX/overload-call.cpp =================================================================== --- clang/test/SemaCXX/overload-call.cpp +++ clang/test/SemaCXX/overload-call.cpp @@ -688,3 +688,13 @@ f(pmf); } } + +namespace PR54347 { + template<class T> void f(T&, int); + template<class U, class T> void f(T const&, U); + void g(int const& i) { f(i, 0); } // expected-error {{ambiguous}} + + template<class T> void f(T(&)[5], int); + template<class U, class T> void f(T const(&)[5], U); + void g(int const(& a)[5]) { f(a, 0); } // expected-error {{ambiguous}} +} Index: clang/lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- clang/lib/Sema/SemaTemplateDeduction.cpp +++ clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1358,7 +1358,7 @@ if (ARef) A = A->getPointeeType(); - if (PRef && ARef && S.Context.hasSameUnqualifiedType(P, A)) { + if (PRef && ARef) { // C++11 [temp.deduct.partial]p9: // If, for a given type, deduction succeeds in both directions (i.e., // the types are identical after the transformations above) and both
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits