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 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"} } +} base-commit: 63b6967b06b5387821c4e5f2c113da6aaeeae2b7 -- 2.47.0