[C++,PR86648] use auto identifier for class placeholder templates

Message ID oro995h1vh.fsf@lxoliva.fsfla.org
State New
Headers show
Series
  • [C++,PR86648] use auto identifier for class placeholder templates
Related show

Commit Message

Alexandre Oliva Dec. 28, 2018, 7:45 p.m.
dwarf2out recognizes unspecified auto types by the identifier.  C++
template class placeholders are unspecified auto types that take the
identifier of the class rather than those used by preexisting auto
types, so dwarf2out ICEs when it finds one of those.  Alas, they may
be visible to dwarf2out, since the types of e.g. static data members
of templates are only deduced at member instantiation, i.e., if the
data member is actually referenced, but the data member is added as a
field, still with unspecified auto placeholder type, when the
enclosing class is instantiated.

I've changed placeholder creator to use an auto identifier instead,
which allowed dropping the placeholder test in C++'s is_auto (alas, it
can't be used in dwarf2out, think LTO).  To avoid losing information
in error messages and dumps and whatnot, I've added code to recognize
placeholders for template classes say A and print them out as
A<...auto...>.

Regstrapped on x86_64- and i686-linux-gnu.  Ok to install?


for  gcc/cp/ChangeLog

	PR c++/86648
        * pt.c (make_template_placeholder): Use auto_identifier.
        (is_auto): Drop CLASS_PLACEHOLDER_TEMPLATE test.
        * error.c (dump_type): Handle template placeholders.
        * cxx-pretty-print.c (pp_cx_unqualified_id): Likewise.

for  gcc/testsuite/ChangeLog

	PR c++/86648
        * gcc.dg/cpp1z/pr86648.C: New.

---
 gcc/cp/cxx-pretty-print.c            |   10 +++++++++-
 gcc/cp/error.c                       |    8 ++++++++
 gcc/cp/pt.c                          |    5 ++---
 gcc/testsuite/g++.dg/cpp1z/pr86648.C |    5 +++++
 4 files changed, 24 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/pr86648.C



-- 
Alexandre Oliva, freedom fighter   https://FSFLA.org/blogs/lxo
Be the change, be Free!         FSF Latin America board member
GNU Toolchain Engineer                Free Software Evangelist
Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe

Comments

Jason Merrill Jan. 8, 2019, 8:55 p.m. | #1
On 12/28/18 2:45 PM, Alexandre Oliva wrote:
> 

> dwarf2out recognizes unspecified auto types by the identifier.  C++

> template class placeholders are unspecified auto types that take the

> identifier of the class rather than those used by preexisting auto

> types, so dwarf2out ICEs when it finds one of those.  Alas, they may

> be visible to dwarf2out, since the types of e.g. static data members

> of templates are only deduced at member instantiation, i.e., if the

> data member is actually referenced, but the data member is added as a

> field, still with unspecified auto placeholder type, when the

> enclosing class is instantiated.

> 

> I've changed placeholder creator to use an auto identifier instead,

> which allowed dropping the placeholder test in C++'s is_auto (alas, it

> can't be used in dwarf2out, think LTO).  To avoid losing information

> in error messages and dumps and whatnot, I've added code to recognize

> placeholders for template classes say A and print them out as

> A<...auto...>.

> 

> Regstrapped on x86_64- and i686-linux-gnu.  Ok to install?

> 

> 

> for  gcc/cp/ChangeLog

> 

> 	PR c++/86648

>          * pt.c (make_template_placeholder): Use auto_identifier.

>          (is_auto): Drop CLASS_PLACEHOLDER_TEMPLATE test.

>          * error.c (dump_type): Handle template placeholders.

>          * cxx-pretty-print.c (pp_cx_unqualified_id): Likewise.

> 

> for  gcc/testsuite/ChangeLog

> 

> 	PR c++/86648

>          * gcc.dg/cpp1z/pr86648.C: New.

> 

> ---

>   gcc/cp/cxx-pretty-print.c            |   10 +++++++++-

>   gcc/cp/error.c                       |    8 ++++++++

>   gcc/cp/pt.c                          |    5 ++---

>   gcc/testsuite/g++.dg/cpp1z/pr86648.C |    5 +++++

>   4 files changed, 24 insertions(+), 4 deletions(-)

>   create mode 100644 gcc/testsuite/g++.dg/cpp1z/pr86648.C

> 

> diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c

> index b79ff5137aa1..c173760f0425 100644

> --- a/gcc/cp/cxx-pretty-print.c

> +++ b/gcc/cp/cxx-pretty-print.c

> @@ -187,7 +187,15 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)

>   

>       case TEMPLATE_TYPE_PARM:

>       case TEMPLATE_TEMPLATE_PARM:

> -      if (TYPE_IDENTIFIER (t))

> +      if (template_placeholder_p (t)

> +	  && DECL_P (CLASS_PLACEHOLDER_TEMPLATE (t))

> +	  && TYPE_IDENTIFIER (TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t))))


Are these extra checks needed?  I would expect them to be true whenever 
template_placeholder_p is.

Jason
Alexandre Oliva Jan. 17, 2019, 4:10 a.m. | #2
On Jan  8, 2019, Jason Merrill <jason@redhat.com> wrote:

> On 12/28/18 2:45 PM, Alexandre Oliva wrote:

>> +      if (template_placeholder_p (t)

>> +	  && DECL_P (CLASS_PLACEHOLDER_TEMPLATE (t))

>> +	  && TYPE_IDENTIFIER (TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t))))


> Are these extra checks needed?


Nope, that was just my overly defensive programming ;-)

> I would expect them to be true whenever template_placeholder_p is.


Testing agrees with your expectation.  Here's a test without the extra
checks, regstrapped on x86_64- and i686-linux-gnu.  Ok to install?


[PR86648] use auto identifier for class placeholder templates

dwarf2out recognizes unspecified auto types by the identifier.  C++
template class placeholders are unspecified auto types that take the
identifier of the class rather than those used by preexisting auto
types, so dwarf2out ICEs when it finds one of those.  Alas, they may
be visible to dwarf2out, since the types of e.g. static data members
of templates are only deduced at member instantiation, i.e., if the
data member is actually referenced, but the data member is added as a
field, still with unspecified auto placeholder type, when the
enclosing class is instantiated.

I've changed placeholder creator to use an auto identifier instead,
which allowed dropping the placeholder test in C++'s is_auto (alas, it
can't be used in dwarf2out, think LTO).  To avoid losing information
in error messages and dumps and whatnot, I've added code to recognize
placeholders for template classes say A and print them out as
A<...auto...>.

for  gcc/cp/ChangeLog

	PR c++/86648
        * pt.c (make_template_placeholder): Use auto_identifier.
        (is_auto): Drop CLASS_PLACEHOLDER_TEMPLATE test.
        * error.c (dump_type): Handle template placeholders.
        * cxx-pretty-print.c (pp_cx_unqualified_id): Likewise.

for  gcc/testsuite/ChangeLog

	PR c++/86648
        * gcc.dg/cpp1z/pr86648.C: New.
---
 gcc/cp/cxx-pretty-print.c            |    8 +++++++-
 gcc/cp/error.c                       |    6 ++++++
 gcc/cp/pt.c                          |    5 ++---
 gcc/testsuite/g++.dg/cpp1z/pr86648.C |    5 +++++
 4 files changed, 20 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/pr86648.C

diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 47eebd1729a3..a114d6654e91 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -187,7 +187,13 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-      if (TYPE_IDENTIFIER (t))
+      if (template_placeholder_p (t))
+	{
+	  t = TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t));
+	  pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
+	  pp_string (pp, "<...auto...>");
+	}
+      else if (TYPE_IDENTIFIER (t))
 	pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
       else
 	pp_cxx_canonical_template_parameter (pp, t);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 367721328834..f585d5fe58fe 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -546,6 +546,12 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
       pp_cxx_cv_qualifier_seq (pp, t);
       if (tree c = PLACEHOLDER_TYPE_CONSTRAINTS (t))
 	pp_cxx_constrained_type_spec (pp, c);
+      else if (template_placeholder_p (t))
+	{
+	  t = TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t));
+	  pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
+	  pp_string (pp, "<...auto...>");
+	}
       else if (TYPE_IDENTIFIER (t))
 	pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
       else
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index c6fc1cfeffb2..8e3311b63ef0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -26456,7 +26456,7 @@ make_auto (void)
 tree
 make_template_placeholder (tree tmpl)
 {
-  tree t = make_auto_1 (DECL_NAME (tmpl), true);
+  tree t = make_auto_1 (auto_identifier, true);
   CLASS_PLACEHOLDER_TEMPLATE (t) = tmpl;
   return t;
 }
@@ -27389,8 +27389,7 @@ is_auto (const_tree type)
 {
   if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
       && (TYPE_IDENTIFIER (type) == auto_identifier
-	  || TYPE_IDENTIFIER (type) == decltype_auto_identifier
-	  || CLASS_PLACEHOLDER_TEMPLATE (type)))
+	  || TYPE_IDENTIFIER (type) == decltype_auto_identifier))
     return true;
   else
     return false;
diff --git a/gcc/testsuite/g++.dg/cpp1z/pr86648.C b/gcc/testsuite/g++.dg/cpp1z/pr86648.C
new file mode 100644
index 000000000000..20ee4c8c0d44
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/pr86648.C
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++17 } }
+
+template <typename> class A;
+template <class T> struct B { static A a{T::a}; };
+void foo () { B<int> a; }


-- 
Alexandre Oliva, freedom fighter   https://FSFLA.org/blogs/lxo
Be the change, be Free!         FSF Latin America board member
GNU Toolchain Engineer                Free Software Evangelist
Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe
Jason Merrill Jan. 17, 2019, 4:36 a.m. | #3
On 1/16/19 11:10 PM, Alexandre Oliva wrote:
> On Jan  8, 2019, Jason Merrill <jason@redhat.com> wrote:

> 

>> On 12/28/18 2:45 PM, Alexandre Oliva wrote:

>>> +      if (template_placeholder_p (t)

>>> +	  && DECL_P (CLASS_PLACEHOLDER_TEMPLATE (t))

>>> +	  && TYPE_IDENTIFIER (TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t))))

> 

>> Are these extra checks needed?

> 

> Nope, that was just my overly defensive programming ;-)

> 

>> I would expect them to be true whenever template_placeholder_p is.

> 

> Testing agrees with your expectation.  Here's a test without the extra

> checks, regstrapped on x86_64- and i686-linux-gnu.  Ok to install?

> 

> 

> [PR86648] use auto identifier for class placeholder templates

> 

> dwarf2out recognizes unspecified auto types by the identifier.  C++

> template class placeholders are unspecified auto types that take the

> identifier of the class rather than those used by preexisting auto

> types, so dwarf2out ICEs when it finds one of those.  Alas, they may

> be visible to dwarf2out, since the types of e.g. static data members

> of templates are only deduced at member instantiation, i.e., if the

> data member is actually referenced, but the data member is added as a

> field, still with unspecified auto placeholder type, when the

> enclosing class is instantiated.

> 

> I've changed placeholder creator to use an auto identifier instead,

> which allowed dropping the placeholder test in C++'s is_auto (alas, it

> can't be used in dwarf2out, think LTO).  To avoid losing information

> in error messages and dumps and whatnot, I've added code to recognize

> placeholders for template classes say A and print them out as

> A<...auto...>.

> 

> for  gcc/cp/ChangeLog

> 

> 	PR c++/86648

>          * pt.c (make_template_placeholder): Use auto_identifier.

>          (is_auto): Drop CLASS_PLACEHOLDER_TEMPLATE test.

>          * error.c (dump_type): Handle template placeholders.

>          * cxx-pretty-print.c (pp_cx_unqualified_id): Likewise.


OK.

Jason

Patch

diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index b79ff5137aa1..c173760f0425 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -187,7 +187,15 @@  pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-      if (TYPE_IDENTIFIER (t))
+      if (template_placeholder_p (t)
+	  && DECL_P (CLASS_PLACEHOLDER_TEMPLATE (t))
+	  && TYPE_IDENTIFIER (TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t))))
+	{
+	  t = TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t));
+	  pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
+	  pp_string (pp, "<...auto...>");
+	}
+      else if (TYPE_IDENTIFIER (t))
 	pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
       else
 	pp_cxx_canonical_template_parameter (pp, t);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index f9b0b9987174..e2f039d1f09e 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -546,6 +546,14 @@  dump_type (cxx_pretty_printer *pp, tree t, int flags)
       pp_cxx_cv_qualifier_seq (pp, t);
       if (tree c = PLACEHOLDER_TYPE_CONSTRAINTS (t))
 	pp_cxx_constrained_type_spec (pp, c);
+      else if (template_placeholder_p (t)
+	       && DECL_P (CLASS_PLACEHOLDER_TEMPLATE (t))
+	       && TYPE_IDENTIFIER (TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t))))
+	{
+	  t = TREE_TYPE (CLASS_PLACEHOLDER_TEMPLATE (t));
+	  pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
+	  pp_string (pp, "<...auto...>");
+	}
       else if (TYPE_IDENTIFIER (t))
 	pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t));
       else
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 18b093e7d2d2..04bf4cd238e9 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -26433,7 +26433,7 @@  make_auto (void)
 tree
 make_template_placeholder (tree tmpl)
 {
-  tree t = make_auto_1 (DECL_NAME (tmpl), true);
+  tree t = make_auto_1 (auto_identifier, true);
   CLASS_PLACEHOLDER_TEMPLATE (t) = tmpl;
   return t;
 }
@@ -27364,8 +27364,7 @@  is_auto (const_tree type)
 {
   if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
       && (TYPE_IDENTIFIER (type) == auto_identifier
-	  || TYPE_IDENTIFIER (type) == decltype_auto_identifier
-	  || CLASS_PLACEHOLDER_TEMPLATE (type)))
+	  || TYPE_IDENTIFIER (type) == decltype_auto_identifier))
     return true;
   else
     return false;
diff --git a/gcc/testsuite/g++.dg/cpp1z/pr86648.C b/gcc/testsuite/g++.dg/cpp1z/pr86648.C
new file mode 100644
index 000000000000..20ee4c8c0d44
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/pr86648.C
@@ -0,0 +1,5 @@ 
+// { dg-do compile { target c++17 } }
+
+template <typename> class A;
+template <class T> struct B { static A a{T::a}; };
+void foo () { B<int> a; }