Here, the dependent template name in the return type of f() resolves to an alias of int& after substitution, and we end up complaining about qualifying this reference type with 'const' from cp_build_qualified_type rather than just silently dropping the qualification as per [dcl.ref]/1.
We already have the tf_ignore_bad_quals flag for this situation, but the TYPENAME_TYPE branch of tsubst for some reason doesn't always use this flag. This patch just makes tsubst unconditionally use this flag when substituting a TYPENAME_TYPE. This change also causes us to drop bogus __restrict__ qualifiers more consistently during substitution, as in qualttp20.C below where we no longer diagnose the __restrict__ qualifier on B1<AS>::r. Note that if we artificially introduced a typedef as in B1<AS>::s we silently dropped __restrict__ even before this patch, so this seems like an improvement. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? PR c++/100592 gcc/cp/ChangeLog: * pt.c (tsubst) <case TYPENAME_TYPE>: Always pass tf_ignore_bad_quals to cp_build_qualified_type. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/alias-decl-71.C: New test. * g++.dg/template/qualttp20.C: Remove dg-error and augment. --- gcc/cp/pt.c | 10 ++++------ gcc/testsuite/g++.dg/cpp0x/alias-decl-71.C | 13 +++++++++++++ gcc/testsuite/g++.dg/template/qualttp20.C | 6 ++++-- 3 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-71.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 86259e900e9..2da5407a2a7 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16066,10 +16066,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (f == error_mark_node) return f; if (TREE_CODE (f) == TYPE_DECL) - { - complain |= tf_ignore_bad_quals; - f = TREE_TYPE (f); - } + f = TREE_TYPE (f); if (TREE_CODE (f) != TYPENAME_TYPE) { @@ -16091,8 +16088,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) } } - return cp_build_qualified_type_real - (f, cp_type_quals (f) | cp_type_quals (t), complain); + int quals = cp_type_quals (f) | cp_type_quals (t); + complain |= tf_ignore_bad_quals; + return cp_build_qualified_type_real (f, quals, complain); } case UNBOUND_CLASS_TEMPLATE: diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-71.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-71.C new file mode 100644 index 00000000000..6a61f93a0b0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-71.C @@ -0,0 +1,13 @@ +// PR c++/100592 +// { dg-do compile { target c++11 } } + +template<bool> +struct meta { + template<class> using if_c = int&; +}; + +template<bool B> +typename meta<B>::template if_c<void> const f(); + +using type = decltype(f<true>()); +using type = int&; diff --git a/gcc/testsuite/g++.dg/template/qualttp20.C b/gcc/testsuite/g++.dg/template/qualttp20.C index 52989bae538..3281f5d9eab 100644 --- a/gcc/testsuite/g++.dg/template/qualttp20.C +++ b/gcc/testsuite/g++.dg/template/qualttp20.C @@ -10,13 +10,15 @@ struct AS { typedef void (myT) (); struct L {}; + typedef struct {} M; }; template <typename T> struct B1 : T { - typedef typename T::L __restrict__ r;// { dg-error "'__restrict__' qualifiers cannot" } + typedef typename T::L __restrict__ r; + typedef typename T::M __restrict__ s; typedef typename T::myT __restrict__ p; // The following are DR 295 dependent @@ -32,5 +34,5 @@ template <typename T> struct B2 : T myconst b; }; -B1<AS> b1; // { dg-message "required" } +B1<AS> b1; B2<AS> b2; -- 2.32.0.rc2