On 6/2/21 4:56 PM, Patrick Palka wrote:
On Wed, 2 Jun 2021, Patrick Palka wrote:
On Wed, 2 Jun 2021, Jason Merrill wrote:
On 6/2/21 2:39 PM, Patrick Palka wrote:
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.
Hmm, the patch looks fine, but why does the TYPE_DECL test fail for the alias?
Ah, I hadn't considered investigating that. It seems make_typename_type
always returns a _TYPE instead of a TYPE_DECL when resolving a dependent
name that's a template-id, regardless of the tf_keep_type_decl flag.
This can be easily fixed like so, and this change alone is sufficient to
fix the PR (no changes to qualttp20.C needed). Note that this change
should only have an effect when tf_keep_type_decl is passed to
make_typename_type, and the only such caller is the TYPENAME_TYPE case
of tsubst in question, so this change seems pretty safe.
The downside is that we don't get the __restrict__-dropping
"improvement" as exhibited by qualttp20.C that the original patch
provides, so this other approach is more conservative in that sense.
So shall we go with the original patch, or something like the following?
(If we go with the original patch, it just occurred to me that we could
remove tf_keep_type_decl altogether.) Testing in progress.
For sake of concreteness, here's the full alternative patch for
consideration (modulo ChangeLog):
This seems better. I think the only non-type return from
lookup_template_class is error_mark_node; does it work to check that
specifically rather than !TYPE_P?
-- >8 --
---
gcc/cp/decl.c | 13 +++++++++----
gcc/testsuite/g++.dg/cpp0x/alias-decl-71.C | 13 +++++++++++++
2 files changed, 22 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-71.C
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index fb21a3a1ae8..1be232af483 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4136,10 +4136,15 @@ make_typename_type (tree context, tree name, enum
tag_types tag_type,
return error_mark_node;
if (want_template)
- return lookup_template_class (t, TREE_OPERAND (fullname, 1),
- NULL_TREE, context,
- /*entering_scope=*/0,
- complain | tf_user);
+ {
+ t = lookup_template_class (t, TREE_OPERAND (fullname, 1),
+ NULL_TREE, context,
+ /*entering_scope=*/0,
+ complain | tf_user);
+ if (!TYPE_P (t))
+ return t;
+ t = TYPE_NAME (t);
+ }
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
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&;