]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c++/87366 - wrong error with alias template.
authorJason Merrill <jason@redhat.com>
Mon, 22 Apr 2019 19:16:46 +0000 (15:16 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 22 Apr 2019 19:16:46 +0000 (15:16 -0400)
With this testcase the code in template_args_equal to treat aliases as
distinct wasn't sufficient, because it only looked at the top level, whereas
here we have a reference to the alias.  So let's also handle treating them
as distinct in structural_comptypes.  For GCC 10 I have a more comprehensive
patch, but for GCC 9 let's go with this smaller change.

* typeck.c (structural_comptypes): When comparing_specializations,
aliases are unequal.
(comptypes): When comparing_specializations, do structural
comparison.

From-SVN: r270494

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/g++.dg/cpp0x/alias-decl-66.C [new file with mode: 0644]

index 11fc9de29b05c311da08d5354bd11acf381b82fb..d207d95256ef97669f0900abd422af9001fe65c1 100644 (file)
@@ -1,3 +1,11 @@
+2019-04-22  Jason Merrill  <jason@redhat.com>
+
+       PR c++/87366 - wrong error with alias template.
+       * typeck.c (structural_comptypes): When comparing_specializations,
+       aliases are unequal.
+       (comptypes): When comparing_specializations, do structural
+       comparison.
+
 2019-04-19  Jason Merrill  <jason@redhat.com>
 
        PR c++/90190 - CTAD with list-constructor.
index 7224d9bf9ed67e36e265c9de6fa06b5294775cfb..fff88ab8df4a0734471183f47c415281ab1fe96b 100644 (file)
@@ -1443,6 +1443,17 @@ structural_comptypes (tree t1, tree t2, int strict)
       return false;
     }
 
+  /* Don't treat an alias template specialization with dependent
+     arguments as equivalent to its underlying type when used as a
+     template argument; we need them to be distinct so that we
+     substitute into the specialization arguments at instantiation
+     time.  And aliases can't be equivalent without being ==, so
+     we don't need to look any deeper.  */
+  if (comparing_specializations
+      && (dependent_alias_template_spec_p (t1)
+         || dependent_alias_template_spec_p (t2)))
+    return false;
+
   /* If we get here, we know that from a target independent POV the
      types are the same.  Make sure the target attributes are also
      the same.  */
@@ -1455,6 +1466,10 @@ structural_comptypes (tree t1, tree t2, int strict)
 bool
 comptypes (tree t1, tree t2, int strict)
 {
+  if (strict == COMPARE_STRICT && comparing_specializations
+      && (t1 != TYPE_CANONICAL (t1) || t2 != TYPE_CANONICAL (t2)))
+    /* If comparing_specializations, treat dependent aliases as distinct.  */
+    strict = COMPARE_STRUCTURAL;
   if (strict == COMPARE_STRICT)
     {
       if (t1 == t2)
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-66.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-66.C
new file mode 100644 (file)
index 0000000..acdea77
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/87366
+// { dg-do compile { target c++11 } }
+
+struct A {};
+struct B {};
+
+template <typename T> struct wrapper {};
+
+template <typename> struct enable_if_A { };
+template<> struct enable_if_A<A> { using type = void; };
+
+template <typename T, typename = typename enable_if_A<T>::type> using ok_t = T;
+
+template <typename T> void not_even_called(wrapper<const ok_t<T>&> a);
+
+template <typename T> int called(wrapper<const T&> a);
+
+void test(wrapper<const B&>& val)
+{
+    called(val);
+}