+ 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" } }