diff mbox series

c++: Improve printing of pointers-to-members [PR97406, PR85901]

Message ID 20201014195245.1237803-1-polacek@redhat.com
State New
Headers show
Series c++: Improve printing of pointers-to-members [PR97406, PR85901] | expand

Commit Message

Marek Polacek Oct. 14, 2020, 7:52 p.m. UTC
This PR points out that when printing the parameter mapping for a
pointer-to-member-function, the output was truncated:

  [with T = void (X::*]

Fixed by printing the abstract declarator for pointers-to-members in
cxx_pretty_printer::type_id.  So now we print:

  [with T = void (X::*)()]

But when I tried a pointer-to-data-member, I got

  [with T = ‘offset_type’ not supported by simple_type_specifier)‘offset_type’ not supported by direct_abstract_declarator]

so had to fix that too so that we now print:

  [with T = int X::*]

or

  [with T = int (X::*)[5]]

when the type is an array type.  Which is what PR85901 was about.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

gcc/cp/ChangeLog:

	PR c++/97406
	PR c++/85901
	* cxx-pretty-print.c (pp_cxx_type_specifier_seq): Handle OFFSET_TYPE.
	(cxx_pretty_printer::abstract_declarator): Fix the printing of ')'.
	(cxx_pretty_printer::direct_abstract_declarator): Handle OFFSET_TYPE.
	(cxx_pretty_printer::type_id): Likewise.  Print the abstract declarator
	for pointers-to-members.

gcc/testsuite/ChangeLog:

	PR c++/97406
	PR c++/85901
	* g++.dg/diagnostic/ptrtomem1.C: New test.
	* g++.dg/diagnostic/ptrtomem2.C: New test.
---
 gcc/cp/cxx-pretty-print.c                   | 33 ++++++++++++++++++++-
 gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C | 31 +++++++++++++++++++
 gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C | 14 +++++++++
 3 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C


base-commit: 93103603fd66a9fcf3ea2d8b52657e4b2496f544

Comments

Jason Merrill Oct. 15, 2020, 3:33 p.m. UTC | #1
On 10/14/20 3:52 PM, Marek Polacek wrote:
> This PR points out that when printing the parameter mapping for a
> pointer-to-member-function, the output was truncated:
> 
>    [with T = void (X::*]
> 
> Fixed by printing the abstract declarator for pointers-to-members in
> cxx_pretty_printer::type_id.  So now we print:
> 
>    [with T = void (X::*)()]
> 
> But when I tried a pointer-to-data-member, I got
> 
>    [with T = ‘offset_type’ not supported by simple_type_specifier)‘offset_type’ not supported by direct_abstract_declarator]
> 
> so had to fix that too so that we now print:
> 
>    [with T = int X::*]
> 
> or
> 
>    [with T = int (X::*)[5]]
> 
> when the type is an array type.  Which is what PR85901 was about.
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK.

> gcc/cp/ChangeLog:
> 
> 	PR c++/97406
> 	PR c++/85901
> 	* cxx-pretty-print.c (pp_cxx_type_specifier_seq): Handle OFFSET_TYPE.
> 	(cxx_pretty_printer::abstract_declarator): Fix the printing of ')'.
> 	(cxx_pretty_printer::direct_abstract_declarator): Handle OFFSET_TYPE.
> 	(cxx_pretty_printer::type_id): Likewise.  Print the abstract declarator
> 	for pointers-to-members.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR c++/97406
> 	PR c++/85901
> 	* g++.dg/diagnostic/ptrtomem1.C: New test.
> 	* g++.dg/diagnostic/ptrtomem2.C: New test.
> ---
>   gcc/cp/cxx-pretty-print.c                   | 33 ++++++++++++++++++++-
>   gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C | 31 +++++++++++++++++++
>   gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C | 14 +++++++++
>   3 files changed, 77 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C
>   create mode 100644 gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C
> 
> diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
> index 8bea79b93a2..058b9c2f4fc 100644
> --- a/gcc/cp/cxx-pretty-print.c
> +++ b/gcc/cp/cxx-pretty-print.c
> @@ -1420,6 +1420,16 @@ pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
>   	}
>         /* fall through */
>   
> +    case OFFSET_TYPE:
> +      if (TYPE_PTRDATAMEM_P (t))
> +	{
> +	  pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
> +	  pp_cxx_whitespace (pp);
> +	  pp_cxx_ptr_operator (pp, t);
> +	  break;
> +	}
> +      /* fall through */
> +
>       default:
>         if (!(TREE_CODE (t) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (t)))
>   	pp_c_specifier_qualifier_list (pp, t);
> @@ -1753,7 +1763,20 @@ pp_cxx_function_definition (cxx_pretty_printer *pp, tree t)
>   void
>   cxx_pretty_printer::abstract_declarator (tree t)
>   {
> -  if (TYPE_PTRMEM_P (t))
> +  /* pp_cxx_ptr_operator prints '(' for a pointer-to-member function,
> +     or a pointer-to-data-member of array type:
> +
> +       void (X::*)()
> +       int (X::*)[5]
> +
> +     but not for a pointer-to-data-member of non-array type:
> +
> +       int X::*
> +
> +     so be mindful of that.  */
> +  if (TYPE_PTRMEMFUNC_P (t)
> +      || (TYPE_PTRDATAMEM_P (t)
> +	  && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
>       pp_cxx_right_paren (this);
>     else if (INDIRECT_TYPE_P (t))
>       {
> @@ -1785,6 +1808,11 @@ cxx_pretty_printer::direct_abstract_declarator (tree t)
>   	direct_abstract_declarator (TYPE_PTRMEMFUNC_FN_TYPE (t));
>         break;
>   
> +    case OFFSET_TYPE:
> +      if (TYPE_PTRDATAMEM_P (t))
> +	direct_abstract_declarator (TREE_TYPE (t));
> +      break;
> +
>       case METHOD_TYPE:
>       case FUNCTION_TYPE:
>         pp_cxx_parameter_declaration_clause (this, t);
> @@ -1837,7 +1865,10 @@ cxx_pretty_printer::type_id (tree t)
>       case UNDERLYING_TYPE:
>       case DECLTYPE_TYPE:
>       case TEMPLATE_ID_EXPR:
> +    case OFFSET_TYPE:
>         pp_cxx_type_specifier_seq (this, t);
> +      if (TYPE_PTRMEM_P (t))
> +	abstract_declarator (t);
>         break;
>   
>       case TYPE_PACK_EXPANSION:
> diff --git a/gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C b/gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C
> new file mode 100644
> index 00000000000..bb1327f7af1
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C
> @@ -0,0 +1,31 @@
> +// PR c++/97406
> +// { dg-do compile { target c++20 } }
> +
> +struct X {
> +  void f() { }
> +  int a;
> +  int arr[5];
> +};
> +
> +// Duplicated so that I can check dg-message.
> +template<typename T>
> +requires (sizeof(T)==1) // { dg-message {\[with T = void \(X::\*\)\(\)\]} }
> +void f1(T)
> +{ }
> +
> +template<typename T>
> +requires (sizeof(T)==1) // { dg-message {\[with T = int X::\*\]} }
> +void f2(T)
> +{ }
> +
> +template<typename T>
> +requires (sizeof(T)==1) // dg-message {\[with T = int \(X::\*\)\[5\]\]} }
> +void f3(T)
> +{ }
> +
> +int main()
> +{
> +  f1(&X::f); // { dg-error "no matching function for call" }
> +  f2(&X::a); // { dg-error "no matching function for call" }
> +  f3(&X::arr); // { dg-error "no matching function for call" }
> +}
> diff --git a/gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C b/gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C
> new file mode 100644
> index 00000000000..f3b29a07a99
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C
> @@ -0,0 +1,14 @@
> +// PR c++/85901
> +// { dg-do compile { target c++11 } }
> +
> +template<class> struct A;
> +
> +template<class U>
> +struct A<int U::*> {
> +    template<class TT>
> +    static auto c(int U::*p, TT o) -> decltype(o.*p); // { dg-message {A<int U::\*>} }
> +};
> +
> +struct X {};
> +
> +int x = A<int X::*>::c(); // { dg-error "no matching function for call" }
> 
> base-commit: 93103603fd66a9fcf3ea2d8b52657e4b2496f544
>
diff mbox series

Patch

diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 8bea79b93a2..058b9c2f4fc 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -1420,6 +1420,16 @@  pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
 	}
       /* fall through */
 
+    case OFFSET_TYPE:
+      if (TYPE_PTRDATAMEM_P (t))
+	{
+	  pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
+	  pp_cxx_whitespace (pp);
+	  pp_cxx_ptr_operator (pp, t);
+	  break;
+	}
+      /* fall through */
+
     default:
       if (!(TREE_CODE (t) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (t)))
 	pp_c_specifier_qualifier_list (pp, t);
@@ -1753,7 +1763,20 @@  pp_cxx_function_definition (cxx_pretty_printer *pp, tree t)
 void
 cxx_pretty_printer::abstract_declarator (tree t)
 {
-  if (TYPE_PTRMEM_P (t))
+  /* pp_cxx_ptr_operator prints '(' for a pointer-to-member function,
+     or a pointer-to-data-member of array type:
+
+       void (X::*)()
+       int (X::*)[5]
+
+     but not for a pointer-to-data-member of non-array type:
+
+       int X::*
+
+     so be mindful of that.  */
+  if (TYPE_PTRMEMFUNC_P (t)
+      || (TYPE_PTRDATAMEM_P (t)
+	  && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
     pp_cxx_right_paren (this);
   else if (INDIRECT_TYPE_P (t))
     {
@@ -1785,6 +1808,11 @@  cxx_pretty_printer::direct_abstract_declarator (tree t)
 	direct_abstract_declarator (TYPE_PTRMEMFUNC_FN_TYPE (t));
       break;
 
+    case OFFSET_TYPE:
+      if (TYPE_PTRDATAMEM_P (t))
+	direct_abstract_declarator (TREE_TYPE (t));
+      break;
+
     case METHOD_TYPE:
     case FUNCTION_TYPE:
       pp_cxx_parameter_declaration_clause (this, t);
@@ -1837,7 +1865,10 @@  cxx_pretty_printer::type_id (tree t)
     case UNDERLYING_TYPE:
     case DECLTYPE_TYPE:
     case TEMPLATE_ID_EXPR:
+    case OFFSET_TYPE:
       pp_cxx_type_specifier_seq (this, t);
+      if (TYPE_PTRMEM_P (t))
+	abstract_declarator (t);
       break;
 
     case TYPE_PACK_EXPANSION:
diff --git a/gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C b/gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C
new file mode 100644
index 00000000000..bb1327f7af1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/ptrtomem1.C
@@ -0,0 +1,31 @@ 
+// PR c++/97406
+// { dg-do compile { target c++20 } }
+
+struct X {
+  void f() { }
+  int a;
+  int arr[5];
+};
+
+// Duplicated so that I can check dg-message.
+template<typename T>
+requires (sizeof(T)==1) // { dg-message {\[with T = void \(X::\*\)\(\)\]} }
+void f1(T)
+{ }
+
+template<typename T>
+requires (sizeof(T)==1) // { dg-message {\[with T = int X::\*\]} }
+void f2(T)
+{ }
+
+template<typename T>
+requires (sizeof(T)==1) // dg-message {\[with T = int \(X::\*\)\[5\]\]} }
+void f3(T)
+{ }
+
+int main()
+{
+  f1(&X::f); // { dg-error "no matching function for call" }
+  f2(&X::a); // { dg-error "no matching function for call" }
+  f3(&X::arr); // { dg-error "no matching function for call" }
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C b/gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C
new file mode 100644
index 00000000000..f3b29a07a99
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/ptrtomem2.C
@@ -0,0 +1,14 @@ 
+// PR c++/85901
+// { dg-do compile { target c++11 } }
+
+template<class> struct A;
+
+template<class U>
+struct A<int U::*> {
+    template<class TT>
+    static auto c(int U::*p, TT o) -> decltype(o.*p); // { dg-message {A<int U::\*>} }
+};
+
+struct X {};
+
+int x = A<int X::*>::c(); // { dg-error "no matching function for call" }