> Am 23.06.2022 um 16:00 schrieb Jan Hubicka via Gcc-patches 
> <gcc-patches@gcc.gnu.org>:
> 
> 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.
> 

Looks OK to me, let’s see if Jason has any comments though.

Richard 

> Honza
> 
> gcc/cp/ChangeLog:
> 
> 2022-06-23  Jan Hubicka  <hubi...@ucw.cz>
> 
>    * 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  <hubi...@ucw.cz>
> 
>    * 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" } }

Reply via email to