aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-04-22 15:16:46 -0400
committerJason Merrill <jason@gcc.gnu.org>2019-04-22 15:16:46 -0400
commitf2b6aeeab219cc41ebc763e8e8378f83287d3591 (patch)
tree5463b687bd25e7cba53974befa499a9967e41cf6 /gcc
parent1e8dac32576fbde72a1ea44b567a2c10f332ecd2 (diff)
downloadgcc-f2b6aeeab219cc41ebc763e8e8378f83287d3591.zip
gcc-f2b6aeeab219cc41ebc763e8e8378f83287d3591.tar.gz
gcc-f2b6aeeab219cc41ebc763e8e8378f83287d3591.tar.bz2
PR c++/87366 - wrong error with alias template.
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/typeck.c15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-66.C21
3 files changed, 44 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 11fc9de..d207d95 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 7224d9b..fff88ab8 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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
index 0000000..acdea77
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-66.C
@@ -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);
+}