From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from nikam.ms.mff.cuni.cz (nikam.ms.mff.cuni.cz [195.113.20.16]) by sourceware.org (Postfix) with ESMTPS id 06B3D38582B1 for ; Thu, 23 Jun 2022 13:59:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 06B3D38582B1 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id E7387289A81; Thu, 23 Jun 2022 15:59:34 +0200 (CEST) Date: Thu, 23 Jun 2022 15:59:34 +0200 From: Jan Hubicka To: gcc-patches@gcc.gnu.org, rguenther@suse.de Subject: Add fnspec attributes to cxa_* functions Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Jun 2022 13:59:38 -0000 Hi, this patch adds fnspecs for cxa_* functions in except.cc. Main goal is to make modref to see proper side-effects of functions which may throw. So in general we get - cxa_allocate_exception which gets the same annotations as malloc (since it is kind of same thing) - cxa_free_exception which gets the same annotations as free - cxa_throw which is marked as const except for first parameter which is believed that it makes it escape (which is necessary) and modify (which is not necessary but it would matter inly if we would like to do constant propagation across EH edges. Honza gcc/cp/ChangeLog: 2022-06-23 Jan Hubicka * except.cc (declare_library_fn_1): Add fnspec parameter. (declare_library_fn): Add fnspec parameter. (do_allocate_exception): Declare fnspecs. (do_free_exception): Declare fnspecs. (build_throw): Declare fnspecs. gcc/testsuite/ChangeLog: 2022-06-23 Jan Hubicka * g++.dg/opt/eh6.C: New test. * g++.dg/tree-ssa/kill.C: New test. diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc index da0a65c613d..bb9a5aee6da 100644 --- a/gcc/cp/except.cc +++ b/gcc/cp/except.cc @@ -133,13 +133,14 @@ build_exc_ptr (void) } /* Declare an exception ABI entry point called NAME. - ECF are the library flags, RTYPE the return type and ARGS[NARGS] + ECF are the library flags, FNSPEC is the attr "fn spec" string (or NULL), + RTYPE the return type and ARGS[NARGS] the parameter types. We return the DECL -- which might be one found via the symbol table pushing, if the user already declared it. If we pushed a new decl, the user will see it. */ static tree -declare_library_fn_1 (const char *name, int ecf, +declare_library_fn_1 (const char *name, int ecf, const char *fnspec, tree rtype, int nargs, tree args[]) { tree ident = get_identifier (name); @@ -150,6 +151,14 @@ declare_library_fn_1 (const char *name, int ecf, for (unsigned ix = nargs; ix--;) arg_list = tree_cons (NULL_TREE, args[ix], arg_list); tree fntype = build_function_type (rtype, arg_list); + if (fnspec) + { + tree attr_args = build_tree_list (NULL_TREE, + build_string (strlen (fnspec), fnspec)); + tree attrs = tree_cons (get_identifier ("fn spec"), + attr_args, TYPE_ATTRIBUTES (fntype)); + fntype = build_type_attribute_variant (fntype, attrs); + } tree res = push_library_fn (ident, fntype, except, ecf); return res; @@ -157,7 +166,8 @@ declare_library_fn_1 (const char *name, int ecf, /* Find or declare a function NAME, returning RTYPE, taking a single parameter PTYPE, with an empty exception specification. ECF are the - library fn flags. If TM_ECF is non-zero, also find or create a + library fn flags. FNSPEC is the attr "fn spec" string (or NULL). + If TM_ECF is non-zero, also find or create a transaction variant and record it as a replacement, when flag_tm is in effect. @@ -167,9 +177,10 @@ declare_library_fn_1 (const char *name, int ecf, static tree declare_library_fn (const char *name, tree rtype, tree ptype, - int ecf, int tm_ecf) + int ecf, int tm_ecf, const char *fnspec = NULL) { - tree res = declare_library_fn_1 (name, ecf, rtype, ptype ? 1 : 0, &ptype); + tree res = declare_library_fn_1 (name, ecf, fnspec, + rtype, ptype ? 1 : 0, &ptype); if (res == error_mark_node) return res; @@ -177,7 +188,7 @@ declare_library_fn (const char *name, tree rtype, tree ptype, { char *tm_name = concat ("_ITM_", name + 2, NULL_TREE); - tree tm_fn = declare_library_fn_1 (tm_name, ecf | tm_ecf, rtype, + tree tm_fn = declare_library_fn_1 (tm_name, ecf | tm_ecf, fnspec, rtype, ptype ? 1 : 0, &ptype); free (tm_name); if (tm_fn != error_mark_node) @@ -547,7 +558,8 @@ do_allocate_exception (tree type) allocate_exception_fn = declare_library_fn ("__cxa_allocate_exception", ptr_type_node, size_type_node, - ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE); + ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE, + "mc"); return cp_build_function_call_nary (allocate_exception_fn, tf_warning_or_error, @@ -565,7 +577,8 @@ do_free_exception (tree ptr) free_exception_fn = declare_library_fn ("__cxa_free_exception", void_type_node, ptr_type_node, - ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE); + ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE, + ".co "); return cp_build_function_call_nary (free_exception_fn, tf_warning_or_error, ptr, NULL_TREE); @@ -653,11 +666,13 @@ build_throw (location_t loc, tree exp) throw_fn = declare_library_fn_1 ("__cxa_throw", ECF_NORETURN | ECF_COLD, + ".c. X X ", void_type_node, 3, args); if (flag_tm && throw_fn != error_mark_node) { tree itm_fn = declare_library_fn_1 ("_ITM_cxa_throw", ECF_NORETURN | ECF_COLD, + ".c. X X ", void_type_node, 3, args); if (itm_fn != error_mark_node) { @@ -804,6 +819,7 @@ build_throw (location_t loc, tree exp) { rethrow_fn = declare_library_fn_1 ("__cxa_rethrow", ECF_NORETURN | ECF_COLD, + ".c", void_type_node, 0, NULL); if (flag_tm && rethrow_fn != error_mark_node) apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure")); diff --git a/gcc/testsuite/g++.dg/opt/eh6.C b/gcc/testsuite/g++.dg/opt/eh6.C new file mode 100644 index 00000000000..fa891fb2559 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/eh6.C @@ -0,0 +1,34 @@ +// PR middle-end/106057 +// { dg-do run } +// { dg-options "-O2" } +struct a {int a; int b;} a; +int b; + +__attribute__((noinline)) +struct a maybethrow(int b) +{ + if (!b) + throw(0); + return {0,0}; +} + +void +test(int b) +{ + a={1,1}; + a=maybethrow(b); + a={0,0}; +} +int +main() +{ + try { + test(b); + } + catch(int) { + if (!a.a) + __builtin_abort (); + } + return 0; +} + diff --git a/gcc/testsuite/g++.dg/tree-ssa/kill.C b/gcc/testsuite/g++.dg/tree-ssa/kill.C new file mode 100644 index 00000000000..bee58cd91fe --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/kill.C @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-modref1" } */ +__attribute__ ((noinline)) +void test(int a) +{ + if (a) + throw (1); +} +int mem; +void link_error (); +int +main() +{ + mem = 0; + test (0); + if (mem) + link_error (); + return 0; +} +// { dg-final { scan-tree-dump-not "modref done with result: tracked." "modref1" } }