public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592]
@ 2021-06-02 18:39 Patrick Palka
  2021-06-02 19:55 ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Patrick Palka @ 2021-06-02 18:39 UTC (permalink / raw)
  To: gcc-patches

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


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592]
  2021-06-02 18:39 [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592] Patrick Palka
@ 2021-06-02 19:55 ` Jason Merrill
  2021-06-02 20:50   ` Patrick Palka
  0 siblings, 1 reply; 7+ messages in thread
From: Jason Merrill @ 2021-06-02 19:55 UTC (permalink / raw)
  To: Patrick Palka, gcc-patches

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?

> 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;
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592]
  2021-06-02 19:55 ` Jason Merrill
@ 2021-06-02 20:50   ` Patrick Palka
  2021-06-02 20:56     ` Patrick Palka
  0 siblings, 1 reply; 7+ messages in thread
From: Patrick Palka @ 2021-06-02 20:50 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Patrick Palka, gcc-patches

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.

-- >8 --

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);


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592]
  2021-06-02 20:50   ` Patrick Palka
@ 2021-06-02 20:56     ` Patrick Palka
  2021-06-02 21:37       ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Patrick Palka @ 2021-06-02 20:56 UTC (permalink / raw)
  To: Patrick Palka; +Cc: Jason Merrill, gcc-patches

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):

-- >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&;
-- 
2.32.0.rc2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592]
  2021-06-02 20:56     ` Patrick Palka
@ 2021-06-02 21:37       ` Jason Merrill
  2021-06-02 23:05         ` Patrick Palka
  0 siblings, 1 reply; 7+ messages in thread
From: Jason Merrill @ 2021-06-02 21:37 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches

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&;
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592]
  2021-06-02 21:37       ` Jason Merrill
@ 2021-06-02 23:05         ` Patrick Palka
  2021-06-03  3:55           ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Patrick Palka @ 2021-06-02 23:05 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Patrick Palka, gcc-patches

On Wed, 2 Jun 2021, Jason Merrill wrote:

> 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?

Indeed, checking for error_mark_node instead works nicely.  Does the
following look OK?  Bootstrapped and regtested on x86_64-pc-linux-gnu.

-- >8 --

Subject: [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592]

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.

The problem is ultimately that make_typename_type ignores the
tf_keep_type_decl flag when the dependent name is a template-id.  This
in turn causes the TYPE_DECL check within tsubst <case TYPENAME_TYPE>
to fail, and so we end up not passing tf_ignore_bad_quals to
cp_build_qualified_type.  This patch fixes this by making
make_typename_type respect the tf_keep_type_decl flag even in the case
of a dependent template-id name.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

	PR c++/100592

gcc/cp/ChangeLog:

	* decl.c (make_typename_type): After dispatching to
	lookup_template_class, adjust the result to its TYPE_NAME
	and then consider the tf_keep_type_decl flag.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/alias-decl-71.C: New test.
	* g++.dg/template/qualttp20.C: Remove dg-error and augment.
---
 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..a3687dbb0dd 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 (t == error_mark_node)
+	return error_mark_node;
+      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&;
-- 
2.32.0.rc2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592]
  2021-06-02 23:05         ` Patrick Palka
@ 2021-06-03  3:55           ` Jason Merrill
  0 siblings, 0 replies; 7+ messages in thread
From: Jason Merrill @ 2021-06-03  3:55 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches

On 6/2/21 7:05 PM, Patrick Palka wrote:
> On Wed, 2 Jun 2021, Jason Merrill wrote:
> 
>> 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?
> 
> Indeed, checking for error_mark_node instead works nicely.  Does the
> following look OK?  Bootstrapped and regtested on x86_64-pc-linux-gnu.

OK.

> -- >8 --
> 
> Subject: [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592]
> 
> 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.
> 
> The problem is ultimately that make_typename_type ignores the
> tf_keep_type_decl flag when the dependent name is a template-id.  This
> in turn causes the TYPE_DECL check within tsubst <case TYPENAME_TYPE>
> to fail, and so we end up not passing tf_ignore_bad_quals to
> cp_build_qualified_type.  This patch fixes this by making
> make_typename_type respect the tf_keep_type_decl flag even in the case
> of a dependent template-id name.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> 
> 	PR c++/100592
> 
> gcc/cp/ChangeLog:
> 
> 	* decl.c (make_typename_type): After dispatching to
> 	lookup_template_class, adjust the result to its TYPE_NAME
> 	and then consider the tf_keep_type_decl flag.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp0x/alias-decl-71.C: New test.
> 	* g++.dg/template/qualttp20.C: Remove dg-error and augment.
> ---
>   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..a3687dbb0dd 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 (t == error_mark_node)
> +	return error_mark_node;
> +      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&;
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-06-03  3:55 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-02 18:39 [PATCH] c++: cv-qualified dependent name of alias tmpl [PR100592] Patrick Palka
2021-06-02 19:55 ` Jason Merrill
2021-06-02 20:50   ` Patrick Palka
2021-06-02 20:56     ` Patrick Palka
2021-06-02 21:37       ` Jason Merrill
2021-06-02 23:05         ` Patrick Palka
2021-06-03  3:55           ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).