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

Reply via email to