diff options
author | Jason Merrill <jason@redhat.com> | 2022-05-09 16:03:35 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2022-05-10 01:05:51 -0400 |
commit | bb2921ab84dba014f24be06663636c7fb1361474 (patch) | |
tree | 4916f6215202be7c12b436d43d04f050ec5f10ef /gcc/cp/decl.cc | |
parent | 067fe66c8ba9b16feacf66fce9ae668091e42821 (diff) | |
download | gcc-bb2921ab84dba014f24be06663636c7fb1361474.zip gcc-bb2921ab84dba014f24be06663636c7fb1361474.tar.gz gcc-bb2921ab84dba014f24be06663636c7fb1361474.tar.bz2 |
c++: fix arm-eabi crash building libstdc++ [PR105529]
My recent change to cxx_eval_store_expression asserts that the target and
value can only end up having different types in the case of an empty base;
this was crashing arm-eabi compilers because in that ABI [cd]tors
return *this, and weren't converting it to void* first.
This also shares the 'return this' code between the three places it occurs.
Thanks to Marek for the tests.
PR c++/105529
gcc/cp/ChangeLog:
* decl.cc (maybe_return_this): Replace...
(finish_constructor_body, finish_destructor_body): ...these.
(finish_function_body): Call it.
* optimize.cc (build_delete_destructor_body): Call it.
* cp-tree.h (maybe_return_this): Declare.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/constexpr-dtor13.C: New test.
* g++.dg/cpp2a/constexpr-dtor14.C: New test.
Diffstat (limited to 'gcc/cp/decl.cc')
-rw-r--r-- | gcc/cp/decl.cc | 47 |
1 files changed, 10 insertions, 37 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 872b02d..9c9cf9f 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -86,9 +86,7 @@ static tree check_initializer (tree, tree, int, vec<tree, va_gc> **); static void make_rtl_for_nonlocal_decl (tree, tree, const char *); static void copy_type_enum (tree , tree); static void check_function_type (tree, tree); -static void finish_constructor_body (void); static void begin_destructor_body (void); -static void finish_destructor_body (void); static void record_key_method_defined (tree); static tree create_array_type_for_decl (tree, tree, tree, location_t); static tree get_atexit_node (void); @@ -17502,22 +17500,20 @@ store_parm_decls (tree current_function_parms) } -/* Set the return value of the constructor (if present). */ +/* Set the return value of the [cd]tor if the ABI wants that. */ -static void -finish_constructor_body (void) +void +maybe_return_this (void) { - tree val; - tree exprstmt; - if (targetm.cxx.cdtor_returns_this ()) { - val = DECL_ARGUMENTS (current_function_decl); + /* Return the address of the object. */ + tree val = DECL_ARGUMENTS (current_function_decl); suppress_warning (val, OPT_Wuse_after_free); + val = fold_convert (TREE_TYPE (DECL_RESULT (current_function_decl)), val); val = build2 (MODIFY_EXPR, TREE_TYPE (val), DECL_RESULT (current_function_decl), val); - /* Return the address of the object. */ - exprstmt = build_stmt (input_location, RETURN_EXPR, val); + tree exprstmt = build_stmt (input_location, RETURN_EXPR, val); add_stmt (exprstmt); } } @@ -17590,28 +17586,6 @@ begin_destructor_body (void) } } -/* At the end of every destructor we generate code to delete the object if - necessary. Do that now. */ - -static void -finish_destructor_body (void) -{ - tree exprstmt; - - if (targetm.cxx.cdtor_returns_this ()) - { - tree val; - - val = DECL_ARGUMENTS (current_function_decl); - suppress_warning (val, OPT_Wuse_after_free); - val = build2 (MODIFY_EXPR, TREE_TYPE (val), - DECL_RESULT (current_function_decl), val); - /* Return the address of the object. */ - exprstmt = build_stmt (input_location, RETURN_EXPR, val); - add_stmt (exprstmt); - } -} - /* Do the necessary processing for the beginning of a function body, which in this case includes member-initializers, but not the catch clauses of a function-try-block. Currently, this means opening a binding level @@ -17662,10 +17636,9 @@ finish_function_body (tree compstmt) if (processing_template_decl) /* Do nothing now. */; - else if (DECL_CONSTRUCTOR_P (current_function_decl)) - finish_constructor_body (); - else if (DECL_DESTRUCTOR_P (current_function_decl)) - finish_destructor_body (); + else if (DECL_CONSTRUCTOR_P (current_function_decl) + || DECL_DESTRUCTOR_P (current_function_decl)) + maybe_return_this (); } /* Given a function, returns the BLOCK corresponding to the outermost level |