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.
Tested x86_64-pc-linux-gnu, applying to trunk. * typeck.c (structural_comptypes): When comparing_specializations, aliases are unequal. (comptypes): When comparing_specializations, do structural comparison. --- gcc/cp/typeck.c | 15 +++++++++++++++ gcc/testsuite/g++.dg/cpp0x/alias-decl-66.C | 21 +++++++++++++++++++++ gcc/cp/ChangeLog | 8 ++++++++ 3 files changed, 44 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-66.C diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 7224d9bf9ed..fff88ab8df4 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 00000000000..acdea77a326 --- /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); +} diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 11fc9de29b0..d207d95256e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2019-04-22 Jason Merrill <ja...@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 <ja...@redhat.com> PR c++/90190 - CTAD with list-constructor. base-commit: a796a13541419edf99653581cf945253fb417064 -- 2.20.1