diff mbox series

[pushed] c++: printing AGGR_INIT_EXPR args

Message ID 20241029162456.3790172-1-jason@redhat.com
State New
Headers show
Series [pushed] c++: printing AGGR_INIT_EXPR args | expand

Commit Message

Jason Merrill Oct. 29, 2024, 4:24 p.m. UTC
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

PR30854 was about wrongly dumping the dummy object argument to a
constructor; r126582 in 4.3 fixed that by skipping the first argument.  But
not all functions called by AGGR_INIT_EXPR are constructors, as observed in
PR116634; we shouldn't skip for non-member functions.  And let's combine the
printing code for CALL_EXPR and AGGR_INIT_EXPR.

This doesn't make us accept the ill-formed 116634 testcase again with a
pedwarn, just fixes the diagnostic issue.

	PR c++/30854
	PR c++/116634

gcc/cp/ChangeLog:

	* error.cc (dump_aggr_init_expr_args): Remove.
	(dump_call_expr_args): Handle AGGR_INIT_EXPR.
	(dump_expr): Combine AGGR_INIT_EXPR and CALL_EXPR cases.

gcc/testsuite/ChangeLog:

	* g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C: Adjust
	diagnostic.
	* g++.dg/diagnostic/aggr-init1.C: New test.
---
 gcc/cp/error.cc                               | 79 +++++--------------
 .../coro-bad-alloc-02-no-op-new-nt.C          |  2 +-
 gcc/testsuite/g++.dg/diagnostic/aggr-init1.C  | 36 +++++++++
 3 files changed, 55 insertions(+), 62 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/aggr-init1.C


base-commit: 63b6967b06b5387821c4e5f2c113da6aaeeae2b7
diff mbox series

Patch

diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 8381f950488..4a60fac9694 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -84,7 +84,6 @@  static void dump_type_prefix (cxx_pretty_printer *, tree, int);
 static void dump_type_suffix (cxx_pretty_printer *, tree, int);
 static void dump_function_name (cxx_pretty_printer *, tree, int);
 static void dump_call_expr_args (cxx_pretty_printer *, tree, int, bool);
-static void dump_aggr_init_expr_args (cxx_pretty_printer *, tree, int, bool);
 static void dump_expr_list (cxx_pretty_printer *, tree, int);
 static void dump_global_iord (cxx_pretty_printer *, tree);
 static void dump_parameters (cxx_pretty_printer *, tree, int);
@@ -2253,46 +2252,15 @@  dump_template_parms (cxx_pretty_printer *pp, tree info,
 static void
 dump_call_expr_args (cxx_pretty_printer *pp, tree t, int flags, bool skipfirst)
 {
-  tree arg;
-  call_expr_arg_iterator iter;
+  const int len = call_expr_nargs (t);
 
   pp_cxx_left_paren (pp);
-  FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
+  for (int i = skipfirst; i < len; ++i)
     {
-      if (skipfirst)
-	skipfirst = false;
-      else
-	{
-	  dump_expr (pp, arg, flags | TFF_EXPR_IN_PARENS);
-	  if (more_call_expr_args_p (&iter))
-	    pp_separate_with_comma (pp);
-	}
-    }
-  pp_cxx_right_paren (pp);
-}
-
-/* Print out the arguments of AGGR_INIT_EXPR T as a parenthesized list
-   using flags FLAGS.  Skip over the first argument if SKIPFIRST is
-   true.  */
-
-static void
-dump_aggr_init_expr_args (cxx_pretty_printer *pp, tree t, int flags,
-                          bool skipfirst)
-{
-  tree arg;
-  aggr_init_expr_arg_iterator iter;
-
-  pp_cxx_left_paren (pp);
-  FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t)
-    {
-      if (skipfirst)
-	skipfirst = false;
-      else
-	{
-	  dump_expr (pp, arg, flags | TFF_EXPR_IN_PARENS);
-	  if (more_aggr_init_expr_args_p (&iter))
-	    pp_separate_with_comma (pp);
-	}
+      tree arg = get_nth_callarg (t, i);
+      dump_expr (pp, arg, flags | TFF_EXPR_IN_PARENS);
+      if (i + 1 < len)
+	pp_separate_with_comma (pp);
     }
   pp_cxx_right_paren (pp);
 }
@@ -2451,28 +2419,9 @@  dump_expr (cxx_pretty_printer *pp, tree t, int flags)
       break;
 
     case AGGR_INIT_EXPR:
-      {
-	tree fn = NULL_TREE;
-
-	if (TREE_CODE (AGGR_INIT_EXPR_FN (t)) == ADDR_EXPR)
-	  fn = TREE_OPERAND (AGGR_INIT_EXPR_FN (t), 0);
-
-	if (fn && TREE_CODE (fn) == FUNCTION_DECL)
-	  {
-	    if (DECL_CONSTRUCTOR_P (fn))
-	      dump_type (pp, DECL_CONTEXT (fn), flags);
-	    else
-	      dump_decl (pp, fn, 0);
-	  }
-	else
-	  dump_expr (pp, AGGR_INIT_EXPR_FN (t), 0);
-      }
-      dump_aggr_init_expr_args (pp, t, flags, true);
-      break;
-
     case CALL_EXPR:
       {
-	tree fn = CALL_EXPR_FN (t);
+	tree fn = cp_get_callee (t);
 	bool skipfirst = false;
 
 	/* Deal with internal functions.  */
@@ -2494,8 +2443,10 @@  dump_expr (cxx_pretty_printer *pp, tree t, int flags)
 	    && NEXT_CODE (fn) == METHOD_TYPE
 	    && call_expr_nargs (t))
 	  {
-	    tree ob = CALL_EXPR_ARG (t, 0);
-	    if (TREE_CODE (ob) == ADDR_EXPR)
+	    tree ob = get_nth_callarg (t, 0);
+	    if (is_dummy_object (ob))
+	      /* Don't print dummy object.  */;
+	    else if (TREE_CODE (ob) == ADDR_EXPR)
 	      {
 		dump_expr (pp, TREE_OPERAND (ob, 0),
                            flags | TFF_EXPR_IN_PARENS);
@@ -2514,7 +2465,13 @@  dump_expr (cxx_pretty_printer *pp, tree t, int flags)
 	    pp_string (cxx_pp, M_("<ubsan routine call>"));
 	    break;
 	  }
-	dump_expr (pp, fn, flags | TFF_EXPR_IN_PARENS);
+
+	if (TREE_CODE (fn) == FUNCTION_DECL
+	    && DECL_CONSTRUCTOR_P (fn)
+	    && is_dummy_object (get_nth_callarg (t, 0)))
+	  dump_type (pp, DECL_CONTEXT (fn), flags);
+	else
+	  dump_expr (pp, fn, flags | TFF_EXPR_IN_PARENS);
 	dump_call_expr_args (pp, t, flags, skipfirst);
       }
       break;
diff --git a/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C b/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C
index 89972b60945..f375ba9473a 100644
--- a/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C
+++ b/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C
@@ -9,7 +9,7 @@ 
 #include "coro1-allocators.h"
 
 struct coro1
-f () /* { dg-error {'coro1::promise_type::get_return_object_on_allocation_failure\(\)\(\)' is provided by 'std::__n4861::__coroutine_traits_impl<coro1, void>::promise_type' \{aka 'coro1::promise_type'\} but 'operator new' is not marked 'throw\(\)' or 'noexcept'} } */
+f () /* { dg-error {'coro1::promise_type::get_return_object_on_allocation_failure\(\)' is provided by 'std::__n4861::__coroutine_traits_impl<coro1, void>::promise_type' \{aka 'coro1::promise_type'\} but 'operator new' is not marked 'throw\(\)' or 'noexcept'} } */
 {
   co_return;
 }
diff --git a/gcc/testsuite/g++.dg/diagnostic/aggr-init1.C b/gcc/testsuite/g++.dg/diagnostic/aggr-init1.C
new file mode 100644
index 00000000000..3c32124d6fd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/aggr-init1.C
@@ -0,0 +1,36 @@ 
+// PR c++/116634
+// { dg-do compile { target c++11 } }
+
+namespace std {
+  using size_t = decltype(sizeof(42));
+}
+
+class ConstString final {
+public:
+    constexpr ConstString() noexcept: buf(), len(0) {}
+    template<int N>
+    constexpr ConstString(const char (&a)[N]): buf(a), len(N - 1) {}
+    constexpr ConstString(const ConstString &c1): buf(c1.buf), len(static_cast<int>(c1.len)) {}
+
+private:
+    const char* buf;
+    int len;
+};
+
+template<int N>
+struct Any final {
+    constexpr
+    Any(ConstString (&&_vec)[N]) noexcept: vec(_vec){} // { dg-error "array" }
+
+    ConstString vec[N];
+};
+
+template<int... N1>
+constexpr static
+auto Any_of(const char (&...c1)[N1]) -> Any<static_cast<int>(sizeof...(N1))> {
+  return {{ConstString(c1)...}};
+}
+
+int main() {
+  constexpr static const auto aa1 = Any_of("abcd", "def"); // { dg-message {"abcd", "def"} }
+}