public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] Sanity check __cxa_* user declarations (PR c++/88482)
@ 2018-12-13 23:30 Jakub Jelinek
  2018-12-14 21:59 ` Jason Merrill
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Jelinek @ 2018-12-13 23:30 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Hi!

If the user provides his own __cxa_* prototypes and does so incorrectly
(or even worse declares them as variables etc.), we can get various ICEs.

The following patch adds some sanity checking, mainly that they are actually
functions and with a compatible return type and argument type(s).
For __cxa_throw it gives some freedom for the second and third arguments,
but apparently not enough for libitm where it causes
+FAIL: libitm.c++/throwdown.C (test for excess errors)

This is because cxxabi.h has:
  void
  __cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void *))
  __attribute__((__noreturn__));
and the patch checks that the second argument is a pointer (any kind) and
third parameter is a function pointer, but libitm.h has:
extern void _ITM_cxa_throw (void *obj, void *tinfo, void *dest);
and eh_cpp.cc has:
extern void __cxa_throw (void *, void *, void *) WEAK;
void 
_ITM_cxa_throw (void *obj, void *tinfo, void *dest)
{
  // This used to be instrumented, but does not need to be anymore.
  __cxa_throw (obj, tinfo, dest);
}
Shall we fix libitm to use void (*dest) (void *) instead of void *dest,
or shall I make the verify_library_fn handle both i == 1 and i == 2
the same?

Bootstrapped/regtested on x86_64-linux and i686-linux (with the above
mentioned FAIL), ok for trunk (and with what solution for libitm)?

2018-12-13  Jakub Jelinek  <jakub@redhat.com>

	PR c++/88482
	* except.c (verify_library_fn): New function.
	(declare_library_fn): Use it.
	(do_end_catch): Don't set TREE_NOTHROW on error_mark_node.
	(expand_start_catch_block): Don't call initialize_handler_parm
	for error_mark_node.
	(build_throw): Use verify_library_fn.  Don't crash if
	any library fn is error_mark_node.

	* g++.dg/eh/builtin5.C: New test.
	* g++.dg/eh/builtin6.C: New test.
	* g++.dg/eh/builtin7.C: New test.
	* g++.dg/eh/builtin8.C: New test.
	* g++.dg/eh/builtin9.C: New test.
	* g++.dg/eh/builtin10.C: New test.
	* g++.dg/eh/builtin11.C: New test.
	* g++.dg/parse/crash55.C: Adjust expected diagnostics.

--- gcc/cp/except.c.jj	2018-12-07 00:23:15.008998854 +0100
+++ gcc/cp/except.c	2018-12-13 20:05:23.053122023 +0100
@@ -132,6 +132,49 @@ build_exc_ptr (void)
 		       1, integer_zero_node);
 }
 
+/* Check that user declared function FN is a function and has return
+   type RTYPE and argument types ARG{1,2,3}TYPE.  */
+
+static bool
+verify_library_fn (tree fn, const char *name, tree rtype,
+		   tree arg1type, tree arg2type, tree arg3type)
+{
+  if (TREE_CODE (fn) != FUNCTION_DECL
+      || TREE_CODE (TREE_TYPE (fn)) != FUNCTION_TYPE)
+    {
+  bad:
+      error_at (DECL_SOURCE_LOCATION (fn), "%qs declared incorrectly", name);
+      return false;
+    }
+  tree fntype = TREE_TYPE (fn);
+  if (!same_type_p (TREE_TYPE (fntype), rtype))
+    goto bad;
+  tree targs = TYPE_ARG_TYPES (fntype);
+  tree args[3] = { arg1type, arg2type, arg3type };
+  for (int i = 0; i < 3 && args[i]; i++)
+    {
+      if (targs == NULL_TREE)
+	goto bad;
+      if (!same_type_p (TREE_VALUE (targs), args[i]))
+	{
+	  if (i == 0)
+	    goto bad;
+	  /* Be less strict for __cxa_throw last 2 arguments.  */
+	  if (i == 1 && TREE_CODE (TREE_VALUE (targs)) != POINTER_TYPE)
+	    goto bad;
+	  if (i == 2
+	      && (TREE_CODE (TREE_VALUE (targs)) != POINTER_TYPE
+		  || (TREE_CODE (TREE_TYPE (TREE_VALUE (targs)))
+		      != FUNCTION_TYPE)))
+	    goto bad;
+	}
+      targs = TREE_CHAIN (targs);
+    }
+  if (targs != void_list_node)
+    goto bad;
+  return true;
+}
+
 /* 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
@@ -161,9 +204,16 @@ declare_library_fn (const char *name, tr
 	  tree tm_fn = get_global_binding (tm_ident);
 	  if (!tm_fn)
 	    tm_fn = push_library_fn (tm_ident, type, except, ecf | tm_ecf);
-	  record_tm_replacement (res, tm_fn);
+	  else if (!verify_library_fn (tm_fn, tm_name, rtype, ptype,
+				       NULL_TREE, NULL_TREE))
+	    tm_fn = error_mark_node;
+	  if (tm_fn != error_mark_node)
+	    record_tm_replacement (res, tm_fn);
 	}
     }
+  else if (!verify_library_fn (res, name, rtype, ptype, NULL_TREE, NULL_TREE))
+    return error_mark_node;
+
   return res;
 }
 
@@ -236,7 +286,8 @@ do_end_catch (tree type)
 
   tree cleanup = cp_build_function_call_vec (end_catch_fn,
 					     NULL, tf_warning_or_error);
-  TREE_NOTHROW (cleanup) = dtor_nothrow (type);
+  if (cleanup != error_mark_node)
+    TREE_NOTHROW (cleanup) = dtor_nothrow (type);
 
   return cleanup;
 }
@@ -400,7 +451,8 @@ expand_start_catch_block (tree decl)
 	   && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
     {
       exp = do_get_exception_ptr ();
-      initialize_handler_parm (decl, exp);
+      if (exp != error_mark_node)
+	initialize_handler_parm (decl, exp);
       finish_expr_stmt (init);
     }
 
@@ -625,10 +677,22 @@ build_throw (tree exp)
 		  tree itm_fn = get_global_binding (itm_name);
 		  if (!itm_fn)
 		    itm_fn = push_throw_library_fn (itm_name, tmp);
-		  apply_tm_attr (itm_fn, get_identifier ("transaction_pure"));
-		  record_tm_replacement (throw_fn, itm_fn);
+		  else if (!verify_library_fn (itm_fn, "_ITM_cxa_throw",
+					       void_type_node, ptr_type_node,
+					       ptr_type_node, cleanup_type))
+		    itm_fn = error_mark_node;
+		  if (itm_fn != error_mark_node)
+		    {
+		      apply_tm_attr (itm_fn,
+				     get_identifier ("transaction_pure"));
+		      record_tm_replacement (throw_fn, itm_fn);
+		    }
 		}
 	    }
+	  else if (!verify_library_fn (throw_fn, "__cxa_throw", void_type_node,
+				       ptr_type_node, ptr_type_node,
+				       cleanup_type))
+	    throw_fn = error_mark_node;
 	}
 
       /* [except.throw]
@@ -658,6 +722,8 @@ build_throw (tree exp)
 
       /* Allocate the space for the exception.  */
       allocate_expr = do_allocate_exception (temp_type);
+      if (allocate_expr == error_mark_node)
+	return error_mark_node;
       allocate_expr = get_target_expr (allocate_expr);
       ptr = TARGET_EXPR_SLOT (allocate_expr);
       TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr);
@@ -766,8 +832,12 @@ build_throw (tree exp)
 	    /* Declare void __cxa_rethrow (void).  */
 	    rethrow_fn = push_throw_library_fn
 	      (name, build_function_type_list (void_type_node, NULL_TREE));
+	  else if (!verify_library_fn (rethrow_fn, "__cxa_rethrow",
+				       void_type_node, NULL_TREE,
+				       NULL_TREE, NULL_TREE))
+	    rethrow_fn = error_mark_node;
 
-	  if (flag_tm)
+	  if (flag_tm && rethrow_fn != error_mark_node)
 	    apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure"));
 	}
 
--- gcc/testsuite/g++.dg/eh/builtin5.C.jj	2018-12-13 20:29:55.633235455 +0100
+++ gcc/testsuite/g++.dg/eh/builtin5.C	2018-12-13 20:26:47.136297368 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" void __cxa_throw (void *, void *, void (*) (void *));
+extern "C" void *__cxa_get_exception_ptr (void *);
+extern "C" void *__cxa_begin_catch (void *);
+extern "C" void __cxa_end_catch ();
+extern "C" void __cxa_rethrow ();
+extern "C" void *__cxa_allocate_exception (__SIZE_TYPE__);
+extern "C" void __cxa_free_exception (void *);
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin6.C.jj	2018-12-13 20:29:58.528188430 +0100
+++ gcc/testsuite/g++.dg/eh/builtin6.C	2018-12-13 20:35:13.441073600 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+float __cxa_throw;		// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_get_exception_ptr (void *);
+float __cxa_begin_catch;	// { dg-error "declared incorrectly" }
+float __cxa_end_catch;		// { dg-error "declared incorrectly" }
+float __cxa_rethrow;		// { dg-error "declared incorrectly" }
+float __cxa_allocate_exception;	// { dg-error "declared incorrectly" }
+extern "C" void __cxa_free_exception (void *);
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin7.C.jj	2018-12-13 20:30:13.688942161 +0100
+++ gcc/testsuite/g++.dg/eh/builtin7.C	2018-12-13 20:31:33.696642532 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" void __cxa_throw (void *, void *, void (*) (void *));
+int __cxa_get_exception_ptr;		// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_begin_catch (void *);
+extern "C" void __cxa_end_catch ();
+extern "C" void __cxa_rethrow ();
+extern "C" void *__cxa_allocate_exception (__SIZE_TYPE__);
+int __cxa_free_exception;		// { dg-error "declared incorrectly" }
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin8.C.jj	2018-12-13 20:31:43.635481087 +0100
+++ gcc/testsuite/g++.dg/eh/builtin8.C	2018-12-13 20:32:09.484061207 +0100
@@ -0,0 +1,23 @@
+// PR c++/88482
+// { dg-do compile }
+
+#include <cxxabi.h>
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin9.C.jj	2018-12-13 20:32:20.079889087 +0100
+++ gcc/testsuite/g++.dg/eh/builtin9.C	2018-12-13 20:34:34.043713014 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" int __cxa_throw (void *, void *, void (*) (void *));	// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_get_exception_ptr (void *);
+extern "C" double __cxa_begin_catch (void *);			// { dg-error "declared incorrectly" }
+extern "C" long *__cxa_end_catch ();				// { dg-error "declared incorrectly" }
+extern "C" char __cxa_rethrow ();				// { dg-error "declared incorrectly" }
+extern "C" void __cxa_allocate_exception (__SIZE_TYPE__);	// { dg-error "declared incorrectly" }
+extern "C" void __cxa_free_exception (void *);
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin10.C.jj	2018-12-13 20:36:03.602259495 +0100
+++ gcc/testsuite/g++.dg/eh/builtin10.C	2018-12-13 20:36:43.522611598 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" void __cxa_throw (void *, void *, void (*) (void *));
+extern "C" float __cxa_get_exception_ptr (void *);		// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_begin_catch (void *);
+extern "C" void __cxa_end_catch ();
+extern "C" void __cxa_rethrow ();
+extern "C" void *__cxa_allocate_exception (__SIZE_TYPE__);
+extern "C" int __cxa_free_exception (void *);			// { dg-error "declared incorrectly" }
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin11.C.jj	2018-12-13 20:36:59.407353793 +0100
+++ gcc/testsuite/g++.dg/eh/builtin11.C	2018-12-13 20:37:49.222545303 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" void __cxa_throw (float, void *, void (*) (void *));	// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_get_exception_ptr (void *);
+extern "C" void *__cxa_begin_catch (int);			// { dg-error "declared incorrectly" }
+extern "C" void __cxa_end_catch (long long);			// { dg-error "declared incorrectly" }
+extern "C" void __cxa_rethrow (int);				// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_allocate_exception (void *);		// { dg-error "declared incorrectly" }
+extern "C" void __cxa_free_exception (void *);
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/parse/crash55.C.jj	2010-01-22 18:47:18.000000000 +0100
+++ gcc/testsuite/g++.dg/parse/crash55.C	2018-12-14 00:20:01.988703354 +0100
@@ -1,8 +1,8 @@
 // PR c++/42038
 
-extern int __cxa_begin_catch;
+extern int __cxa_begin_catch;	// { dg-error "declared incorrectly" }
 
 void f(void)
 {
-  try { } catch (int) { } // { dg-error "cannot be used" }
+  try { } catch (int) { }
 }

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++ PATCH] Sanity check __cxa_* user declarations (PR c++/88482)
  2018-12-13 23:30 [C++ PATCH] Sanity check __cxa_* user declarations (PR c++/88482) Jakub Jelinek
@ 2018-12-14 21:59 ` Jason Merrill
  2018-12-15 11:22   ` Jakub Jelinek
  0 siblings, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2018-12-14 21:59 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 12/13/18 6:29 PM, Jakub Jelinek wrote:
> Hi!
> 
> If the user provides his own __cxa_* prototypes and does so incorrectly
> (or even worse declares them as variables etc.), we can get various ICEs.
> 
> The following patch adds some sanity checking, mainly that they are actually
> functions and with a compatible return type and argument type(s).
> For __cxa_throw it gives some freedom for the second and third arguments,
> but apparently not enough for libitm where it causes
> +FAIL: libitm.c++/throwdown.C (test for excess errors)
> 
> This is because cxxabi.h has:
>    void
>    __cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void *))
>    __attribute__((__noreturn__));
> and the patch checks that the second argument is a pointer (any kind) and
> third parameter is a function pointer, but libitm.h has:
> extern void _ITM_cxa_throw (void *obj, void *tinfo, void *dest);
> and eh_cpp.cc has:
> extern void __cxa_throw (void *, void *, void *) WEAK;
> void
> _ITM_cxa_throw (void *obj, void *tinfo, void *dest)
> {
>    // This used to be instrumented, but does not need to be anymore.
>    __cxa_throw (obj, tinfo, dest);
> }
> Shall we fix libitm to use void (*dest) (void *) instead of void *dest,
> or shall I make the verify_library_fn handle both i == 1 and i == 2
> the same?

Fix libitm.  Do function pointers and object pointers have the same 
representation on all the targets we support?

> Bootstrapped/regtested on x86_64-linux and i686-linux (with the above
> mentioned FAIL), ok for trunk (and with what solution for libitm)?
> 
> 2018-12-13  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/88482
> 	* except.c (verify_library_fn): New function.
> 	(declare_library_fn): Use it.
> 	(do_end_catch): Don't set TREE_NOTHROW on error_mark_node.
> 	(expand_start_catch_block): Don't call initialize_handler_parm
> 	for error_mark_node.
> 	(build_throw): Use verify_library_fn.  Don't crash if
> 	any library fn is error_mark_node.
> 
> 	* g++.dg/eh/builtin5.C: New test.
> 	* g++.dg/eh/builtin6.C: New test.
> 	* g++.dg/eh/builtin7.C: New test.
> 	* g++.dg/eh/builtin8.C: New test.
> 	* g++.dg/eh/builtin9.C: New test.
> 	* g++.dg/eh/builtin10.C: New test.
> 	* g++.dg/eh/builtin11.C: New test.
> 	* g++.dg/parse/crash55.C: Adjust expected diagnostics.
> 
> --- gcc/cp/except.c.jj	2018-12-07 00:23:15.008998854 +0100
> +++ gcc/cp/except.c	2018-12-13 20:05:23.053122023 +0100
> @@ -132,6 +132,49 @@ build_exc_ptr (void)
>   		       1, integer_zero_node);
>   }
>   
> +/* Check that user declared function FN is a function and has return
> +   type RTYPE and argument types ARG{1,2,3}TYPE.  */
> +
> +static bool
> +verify_library_fn (tree fn, const char *name, tree rtype,
> +		   tree arg1type, tree arg2type, tree arg3type)
> +{

Do we want to skip all of this if DECL_ARTIFICIAL?

> +  if (TREE_CODE (fn) != FUNCTION_DECL
> +      || TREE_CODE (TREE_TYPE (fn)) != FUNCTION_TYPE)
> +    {
> +  bad:
> +      error_at (DECL_SOURCE_LOCATION (fn), "%qs declared incorrectly", name);
> +      return false;
> +    }
> +  tree fntype = TREE_TYPE (fn);
> +  if (!same_type_p (TREE_TYPE (fntype), rtype))
> +    goto bad;
> +  tree targs = TYPE_ARG_TYPES (fntype);
> +  tree args[3] = { arg1type, arg2type, arg3type };
> +  for (int i = 0; i < 3 && args[i]; i++)
> +    {
> +      if (targs == NULL_TREE)
> +	goto bad;
> +      if (!same_type_p (TREE_VALUE (targs), args[i]))
> +	{
> +	  if (i == 0)
> +	    goto bad;
> +	  /* Be less strict for __cxa_throw last 2 arguments.  */
> +	  if (i == 1 && TREE_CODE (TREE_VALUE (targs)) != POINTER_TYPE)
> +	    goto bad;
> +	  if (i == 2
> +	      && (TREE_CODE (TREE_VALUE (targs)) != POINTER_TYPE
> +		  || (TREE_CODE (TREE_TYPE (TREE_VALUE (targs)))
> +		      != FUNCTION_TYPE)))

These seem to assume that any library function with more than one 
parameter will have pointers for the second and third parameters.

TYPE_PTROBV_P might be useful.

> +	    goto bad;
> +	}
> +      targs = TREE_CHAIN (targs);
> +    }
> +  if (targs != void_list_node)
> +    goto bad;
> +  return true;
> +}
> +
>   /* 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
> @@ -161,9 +204,16 @@ declare_library_fn (const char *name, tr
>   	  tree tm_fn = get_global_binding (tm_ident);
>   	  if (!tm_fn)
>   	    tm_fn = push_library_fn (tm_ident, type, except, ecf | tm_ecf);
> -	  record_tm_replacement (res, tm_fn);
> +	  else if (!verify_library_fn (tm_fn, tm_name, rtype, ptype,
> +				       NULL_TREE, NULL_TREE))
> +	    tm_fn = error_mark_node;
> +	  if (tm_fn != error_mark_node)
> +	    record_tm_replacement (res, tm_fn);
>   	}
>       }
> +  else if (!verify_library_fn (res, name, rtype, ptype, NULL_TREE, NULL_TREE))
> +    return error_mark_node;
> +
>     return res;
>   }
>   
> @@ -236,7 +286,8 @@ do_end_catch (tree type)
>   
>     tree cleanup = cp_build_function_call_vec (end_catch_fn,
>   					     NULL, tf_warning_or_error);
> -  TREE_NOTHROW (cleanup) = dtor_nothrow (type);
> +  if (cleanup != error_mark_node)
> +    TREE_NOTHROW (cleanup) = dtor_nothrow (type);
>   
>     return cleanup;
>   }
> @@ -400,7 +451,8 @@ expand_start_catch_block (tree decl)
>   	   && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
>       {
>         exp = do_get_exception_ptr ();
> -      initialize_handler_parm (decl, exp);
> +      if (exp != error_mark_node)
> +	initialize_handler_parm (decl, exp);
>         finish_expr_stmt (init);
>       }
>   
> @@ -625,10 +677,22 @@ build_throw (tree exp)
>   		  tree itm_fn = get_global_binding (itm_name);
>   		  if (!itm_fn)
>   		    itm_fn = push_throw_library_fn (itm_name, tmp);
> -		  apply_tm_attr (itm_fn, get_identifier ("transaction_pure"));
> -		  record_tm_replacement (throw_fn, itm_fn);
> +		  else if (!verify_library_fn (itm_fn, "_ITM_cxa_throw",
> +					       void_type_node, ptr_type_node,
> +					       ptr_type_node, cleanup_type))
> +		    itm_fn = error_mark_node;
> +		  if (itm_fn != error_mark_node)
> +		    {
> +		      apply_tm_attr (itm_fn,
> +				     get_identifier ("transaction_pure"));
> +		      record_tm_replacement (throw_fn, itm_fn);
> +		    }
>   		}
>   	    }
> +	  else if (!verify_library_fn (throw_fn, "__cxa_throw", void_type_node,
> +				       ptr_type_node, ptr_type_node,
> +				       cleanup_type))
> +	    throw_fn = error_mark_node;

This should happen whether or not flag_tm.

Let's avoid repeating the strings "__cxa_throw" and "_ITM_cxa_throw".

Jason

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++ PATCH] Sanity check __cxa_* user declarations (PR c++/88482)
  2018-12-14 21:59 ` Jason Merrill
@ 2018-12-15 11:22   ` Jakub Jelinek
  2018-12-15 13:09     ` Jakub Jelinek
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Jelinek @ 2018-12-15 11:22 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Fri, Dec 14, 2018 at 04:59:44PM -0500, Jason Merrill wrote:
> > extern void __cxa_throw (void *, void *, void *) WEAK;
> > void
> > _ITM_cxa_throw (void *obj, void *tinfo, void *dest)
> > {
> >    // This used to be instrumented, but does not need to be anymore.
> >    __cxa_throw (obj, tinfo, dest);
> > }
> > Shall we fix libitm to use void (*dest) (void *) instead of void *dest,
> > or shall I make the verify_library_fn handle both i == 1 and i == 2
> > the same?
> 
> Fix libitm.

Ok, will do.

> Do function pointers and object pointers have the same
> representation on all the targets we support?

Not sure about this, but we have all kinds of weird targets.

> > +/* Check that user declared function FN is a function and has return
> > +   type RTYPE and argument types ARG{1,2,3}TYPE.  */
> > +
> > +static bool
> > +verify_library_fn (tree fn, const char *name, tree rtype,
> > +		   tree arg1type, tree arg2type, tree arg3type)
> > +{
> 
> Do we want to skip all of this if DECL_ARTIFICIAL?

Not sure how a DECL_ARTIFICIAL fn could appear there.  This function is
only called 1) the first time we need a particular __cxa_* routine
2) and the declaration exists already (when we create it ourselves,
we don't need to check it).

> > +	  /* Be less strict for __cxa_throw last 2 arguments.  */
> > +	  if (i == 1 && TREE_CODE (TREE_VALUE (targs)) != POINTER_TYPE)
> > +	    goto bad;
> > +	  if (i == 2
> > +	      && (TREE_CODE (TREE_VALUE (targs)) != POINTER_TYPE
> > +		  || (TREE_CODE (TREE_TYPE (TREE_VALUE (targs)))
> > +		      != FUNCTION_TYPE)))
> 
> These seem to assume that any library function with more than one parameter
> will have pointers for the second and third parameters.
> 
> TYPE_PTROBV_P might be useful.

I can do e.g.
	if (i == 0)
	  goto bad;
	/* Be less strict for second and following arguments, __cxa_throw
	   needs to be more permissive.  */
	if (TYPE_PTROBV_P (TREE_VALUE (args)) && TYPE_PTROBV_P (args[i]))
	  /* Both object pointers.  */;
	else if (TYPE_PTRFN_P (TREE_VALUE (args)) && TYPE_PTRFN_P (args[i]))
	  /* Both function pointers.  */;
	else
	  goto bad;

> > @@ -625,10 +677,22 @@ build_throw (tree exp)
> >   		  tree itm_fn = get_global_binding (itm_name);
> >   		  if (!itm_fn)
> >   		    itm_fn = push_throw_library_fn (itm_name, tmp);
> > -		  apply_tm_attr (itm_fn, get_identifier ("transaction_pure"));
> > -		  record_tm_replacement (throw_fn, itm_fn);
> > +		  else if (!verify_library_fn (itm_fn, "_ITM_cxa_throw",
> > +					       void_type_node, ptr_type_node,
> > +					       ptr_type_node, cleanup_type))
> > +		    itm_fn = error_mark_node;
> > +		  if (itm_fn != error_mark_node)
> > +		    {
> > +		      apply_tm_attr (itm_fn,
> > +				     get_identifier ("transaction_pure"));
> > +		      record_tm_replacement (throw_fn, itm_fn);
> > +		    }
> >   		}
> >   	    }
> > +	  else if (!verify_library_fn (throw_fn, "__cxa_throw", void_type_node,
> > +				       ptr_type_node, ptr_type_node,
> > +				       cleanup_type))
> > +	    throw_fn = error_mark_node;
> 
> This should happen whether or not flag_tm.

It does, it is else of:
      if (!throw_fn)
        {
          tree name = get_identifier ("__cxa_throw");
          throw_fn = get_global_binding (name);
          if (!throw_fn)
            {

That said, I think what is wrong is that we have the TM handling solely
in the spots where we create the __cxa_ functions ourselves.  In all the
places, it looks like:
  tree ident = get_identifier (name);
  tree res = get_global_binding (ident);
  if (!res)
    {
      res = build_it_ourselves;
      if (tm_ecf && flag_tm)
        {
          char *tm_name = ...;
          tree tm_ident = get_identifier (tm_name);
          free (tm_name);
          tree tm_fn = get_global_binding (tm_ident);
          if (!tm_fn)
	    tm_fn = build_it_ourselves;
	  else
	    verify;
          if (valid)
            record_tm_replacement (res, tm_fn);
        }
    }
  else
    verify;
IMHO it should look like:
  tree ident = get_identifier (name);
  tree res = get_global_binding (ident);
  if (!res)
    res = build_it_ourselves;
  else
    verify;
  if (valid && tm_ecf && flag_tm)
    {
      char *tm_name = ...;
      tree tm_ident = get_identifier (tm_name);
      tree tm_fn = get_global_binding (tm_ident);
      if (!tm_fn)
	tm_fn = build_it_ourselves;
      else
	verify;
      free (tm_name);
      if (valid)
        record_tm_replacement (res, tm_fn);
    }
So that if we e.g. have the __cxa_* prototypes, but not the TM ones,
we use user's prototypes for the former and create the latter.
Are you ok with those changes?

> Let's avoid repeating the strings "__cxa_throw" and "_ITM_cxa_throw".

Will do.

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++ PATCH] Sanity check __cxa_* user declarations (PR c++/88482)
  2018-12-15 11:22   ` Jakub Jelinek
@ 2018-12-15 13:09     ` Jakub Jelinek
  2018-12-15 22:14       ` Jason Merrill
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Jelinek @ 2018-12-15 13:09 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Sat, Dec 15, 2018 at 12:22:44PM +0100, Jakub Jelinek wrote:
> > Fix libitm.
> 
> Ok, will do.

Hre it is in patch form:

2018-12-15  Jakub Jelinek  <jakub@redhat.com>

	PR c++/88482
	* except.c (verify_library_fn): New function.
	(declare_library_fn): Use it.  Initialize TM even if the non-TM
	library function has been user declared.
	(do_end_catch): Don't set TREE_NOTHROW on error_mark_node.
	(expand_start_catch_block): Don't call initialize_handler_parm
	for error_mark_node.
	(build_throw): Use verify_library_fn.  Initialize TM even if the
	non-TM library function has been user declared.  Don't crash if
	any library fn is error_mark_node.

	* g++.dg/eh/builtin5.C: New test.
	* g++.dg/eh/builtin6.C: New test.
	* g++.dg/eh/builtin7.C: New test.
	* g++.dg/eh/builtin8.C: New test.
	* g++.dg/eh/builtin9.C: New test.
	* g++.dg/eh/builtin10.C: New test.
	* g++.dg/eh/builtin11.C: New test.
	* g++.dg/parse/crash55.C: Adjust expected diagnostics.

	* eh_cpp.cc (__cxa_throw): Change DEST argument type from
	void * to void (*) (void *).
	(_ITM_cxa_throw): Likewise.
	* libitm.h (_ITM_cxa_throw): Likewise.
	* libitm.texi (_ITM_cxa_throw): Likewise.

--- gcc/cp/except.c.jj	2018-12-14 00:32:56.042200543 +0100
+++ gcc/cp/except.c	2018-12-15 13:39:29.301459729 +0100
@@ -132,6 +132,49 @@ build_exc_ptr (void)
 		       1, integer_zero_node);
 }
 
+/* Check that user declared function FN is a function and has return
+   type RTYPE and argument types ARG{1,2,3}TYPE.  */
+
+static bool
+verify_library_fn (tree fn, const char *name, tree rtype,
+		   tree arg1type, tree arg2type, tree arg3type)
+{
+  if (TREE_CODE (fn) != FUNCTION_DECL
+      || TREE_CODE (TREE_TYPE (fn)) != FUNCTION_TYPE)
+    {
+  bad:
+      error_at (DECL_SOURCE_LOCATION (fn), "%qs declared incorrectly", name);
+      return false;
+    }
+  tree fntype = TREE_TYPE (fn);
+  if (!same_type_p (TREE_TYPE (fntype), rtype))
+    goto bad;
+  tree targs = TYPE_ARG_TYPES (fntype);
+  tree args[3] = { arg1type, arg2type, arg3type };
+  for (int i = 0; i < 3 && args[i]; i++)
+    {
+      if (targs == NULL_TREE)
+	goto bad;
+      if (!same_type_p (TREE_VALUE (targs), args[i]))
+	{
+	  if (i == 0)
+	    goto bad;
+	  /* Be less strict for second and following arguments, __cxa_throw
+	     needs to be more permissive.  */
+	  if (TYPE_PTROBV_P (TREE_VALUE (targs)) && TYPE_PTROBV_P (args[i]))
+	    /* Both object pointers.  */;
+	  else if (TYPE_PTRFN_P (TREE_VALUE (targs)) && TYPE_PTRFN_P (args[i]))
+	    /* Both function pointers.  */;
+	  else
+	    goto bad;
+	}
+      targs = TREE_CHAIN (targs);
+    }
+  if (targs != void_list_node)
+    goto bad;
+  return true;
+}
+
 /* 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
@@ -148,21 +191,39 @@ declare_library_fn (const char *name, tr
 {
   tree ident = get_identifier (name);
   tree res = get_global_binding (ident);
+  tree fntype = NULL_TREE;
+  tree except = NULL_TREE;
   if (!res)
     {
-      tree type = build_function_type_list (rtype, ptype, NULL_TREE);
-      tree except = ecf & ECF_NOTHROW ? empty_except_spec : NULL_TREE;
-      res = push_library_fn (ident, type, except, ecf);
-      if (tm_ecf && flag_tm)
+      fntype = build_function_type_list (rtype, ptype, NULL_TREE);
+      if (ecf & ECF_NOTHROW)
+	except = empty_except_spec;
+      res = push_library_fn (ident, fntype, except, ecf);
+    }
+  else if (!verify_library_fn (res, name, rtype, ptype, NULL_TREE, NULL_TREE))
+    return error_mark_node;
+
+  if (tm_ecf && flag_tm)
+    {
+      char *tm_name = concat ("_ITM_", name + 2, NULL_TREE);
+      tree tm_ident = get_identifier (tm_name);
+      tree tm_fn = get_global_binding (tm_ident);
+      if (!tm_fn)
 	{
-	  char *tm_name = concat ("_ITM_", name + 2, NULL_TREE);
-	  tree tm_ident = get_identifier (tm_name);
-	  free (tm_name);
-	  tree tm_fn = get_global_binding (tm_ident);
-	  if (!tm_fn)
-	    tm_fn = push_library_fn (tm_ident, type, except, ecf | tm_ecf);
-	  record_tm_replacement (res, tm_fn);
+	  if (!fntype)
+	    {
+	      fntype = build_function_type_list (rtype, ptype, NULL_TREE);
+	      if (ecf & ECF_NOTHROW)
+		except = empty_except_spec;
+	    }
+	  tm_fn = push_library_fn (tm_ident, fntype, except, ecf | tm_ecf);
 	}
+      else if (!verify_library_fn (tm_fn, tm_name, rtype, ptype,
+				   NULL_TREE, NULL_TREE))
+	tm_fn = error_mark_node;
+      free (tm_name);
+      if (tm_fn != error_mark_node)
+	record_tm_replacement (res, tm_fn);
     }
   return res;
 }
@@ -236,7 +297,8 @@ do_end_catch (tree type)
 
   tree cleanup = cp_build_function_call_vec (end_catch_fn,
 					     NULL, tf_warning_or_error);
-  TREE_NOTHROW (cleanup) = dtor_nothrow (type);
+  if (cleanup != error_mark_node)
+    TREE_NOTHROW (cleanup) = dtor_nothrow (type);
 
   return cleanup;
 }
@@ -400,7 +462,8 @@ expand_start_catch_block (tree decl)
 	   && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
     {
       exp = do_get_exception_ptr ();
-      initialize_handler_parm (decl, exp);
+      if (exp != error_mark_node)
+	initialize_handler_parm (decl, exp);
       finish_expr_stmt (init);
     }
 
@@ -608,23 +671,44 @@ build_throw (tree exp)
 
       if (!throw_fn)
 	{
-	  tree name = get_identifier ("__cxa_throw");
-	  throw_fn = get_global_binding (name);
+	  const char *name = "__cxa_throw";
+	  tree ident = get_identifier (name);
+	  tree fntype = NULL_TREE;
+	  throw_fn = get_global_binding (ident);
 	  if (!throw_fn)
 	    {
 	      /* Declare void __cxa_throw (void*, void*, void (*)(void*)).  */
 	      /* ??? Second argument is supposed to be "std::type_info*".  */
-	      tmp = build_function_type_list (void_type_node,
-					      ptr_type_node, ptr_type_node,
-					      cleanup_type, NULL_TREE);
-	      throw_fn = push_throw_library_fn (name, tmp);
+	      fntype = build_function_type_list (void_type_node,
+						 ptr_type_node, ptr_type_node,
+						 cleanup_type, NULL_TREE);
+	      throw_fn = push_throw_library_fn (ident, fntype);
+	    }
+	  else if (!verify_library_fn (throw_fn, name, void_type_node,
+				       ptr_type_node, ptr_type_node,
+				       cleanup_type))
+	    throw_fn = error_mark_node;
 
-	      if (flag_tm)
+	  if (flag_tm && throw_fn != error_mark_node)
+	    {
+	      const char *itm_name = "_ITM_cxa_throw";
+	      tree itm_ident = get_identifier (itm_name);
+	      tree itm_fn = get_global_binding (itm_ident);
+	      if (!itm_fn)
+		{
+		  if (!fntype)
+		    fntype
+		      = build_function_type_list (void_type_node,
+						  ptr_type_node, ptr_type_node,
+						  cleanup_type, NULL_TREE);
+		  itm_fn = push_throw_library_fn (itm_ident, fntype);
+		}
+	      else if (!verify_library_fn (itm_fn, itm_name, void_type_node,
+					   ptr_type_node, ptr_type_node,
+					   cleanup_type))
+		itm_fn = error_mark_node;
+	      if (itm_fn != error_mark_node)
 		{
-		  tree itm_name = get_identifier ("_ITM_cxa_throw");
-		  tree itm_fn = get_global_binding (itm_name);
-		  if (!itm_fn)
-		    itm_fn = push_throw_library_fn (itm_name, tmp);
 		  apply_tm_attr (itm_fn, get_identifier ("transaction_pure"));
 		  record_tm_replacement (throw_fn, itm_fn);
 		}
@@ -658,6 +742,8 @@ build_throw (tree exp)
 
       /* Allocate the space for the exception.  */
       allocate_expr = do_allocate_exception (temp_type);
+      if (allocate_expr == error_mark_node)
+	return error_mark_node;
       allocate_expr = get_target_expr (allocate_expr);
       ptr = TARGET_EXPR_SLOT (allocate_expr);
       TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr);
@@ -760,14 +846,21 @@ build_throw (tree exp)
       /* Rethrow current exception.  */
       if (!rethrow_fn)
 	{
-	  tree name = get_identifier ("__cxa_rethrow");
-	  rethrow_fn = get_global_binding (name);
+	  const char *name = "__cxa_rethrow";
+	  tree ident = get_identifier (name);
+	  rethrow_fn = get_global_binding (ident);
 	  if (!rethrow_fn)
-	    /* Declare void __cxa_rethrow (void).  */
-	    rethrow_fn = push_throw_library_fn
-	      (name, build_function_type_list (void_type_node, NULL_TREE));
+	    {
+	      /* Declare void __cxa_rethrow (void).  */
+	      tree fntype
+		= build_function_type_list (void_type_node, NULL_TREE);
+	      rethrow_fn = push_throw_library_fn (ident, fntype);
+	    }
+	  else if (!verify_library_fn (rethrow_fn, name, void_type_node,
+				       NULL_TREE, NULL_TREE, NULL_TREE))
+	    rethrow_fn = error_mark_node;
 
-	  if (flag_tm)
+	  if (flag_tm && rethrow_fn != error_mark_node)
 	    apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure"));
 	}
 
--- gcc/testsuite/g++.dg/eh/builtin5.C.jj	2018-12-15 13:00:41.134490069 +0100
+++ gcc/testsuite/g++.dg/eh/builtin5.C	2018-12-15 13:00:41.134490069 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" void __cxa_throw (void *, void *, void (*) (void *));
+extern "C" void *__cxa_get_exception_ptr (void *);
+extern "C" void *__cxa_begin_catch (void *);
+extern "C" void __cxa_end_catch ();
+extern "C" void __cxa_rethrow ();
+extern "C" void *__cxa_allocate_exception (__SIZE_TYPE__);
+extern "C" void __cxa_free_exception (void *);
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin6.C.jj	2018-12-15 13:00:41.134490069 +0100
+++ gcc/testsuite/g++.dg/eh/builtin6.C	2018-12-15 13:00:41.134490069 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+float __cxa_throw;		// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_get_exception_ptr (void *);
+float __cxa_begin_catch;	// { dg-error "declared incorrectly" }
+float __cxa_end_catch;		// { dg-error "declared incorrectly" }
+float __cxa_rethrow;		// { dg-error "declared incorrectly" }
+float __cxa_allocate_exception;	// { dg-error "declared incorrectly" }
+extern "C" void __cxa_free_exception (void *);
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin7.C.jj	2018-12-15 13:00:41.134490069 +0100
+++ gcc/testsuite/g++.dg/eh/builtin7.C	2018-12-15 13:00:41.134490069 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" void __cxa_throw (void *, void *, void (*) (void *));
+int __cxa_get_exception_ptr;		// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_begin_catch (void *);
+extern "C" void __cxa_end_catch ();
+extern "C" void __cxa_rethrow ();
+extern "C" void *__cxa_allocate_exception (__SIZE_TYPE__);
+int __cxa_free_exception;		// { dg-error "declared incorrectly" }
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin8.C.jj	2018-12-15 13:00:41.134490069 +0100
+++ gcc/testsuite/g++.dg/eh/builtin8.C	2018-12-15 13:00:41.134490069 +0100
@@ -0,0 +1,23 @@
+// PR c++/88482
+// { dg-do compile }
+
+#include <cxxabi.h>
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin9.C.jj	2018-12-15 13:00:41.135490052 +0100
+++ gcc/testsuite/g++.dg/eh/builtin9.C	2018-12-15 13:00:41.134490069 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" int __cxa_throw (void *, void *, void (*) (void *));	// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_get_exception_ptr (void *);
+extern "C" double __cxa_begin_catch (void *);			// { dg-error "declared incorrectly" }
+extern "C" long *__cxa_end_catch ();				// { dg-error "declared incorrectly" }
+extern "C" char __cxa_rethrow ();				// { dg-error "declared incorrectly" }
+extern "C" void __cxa_allocate_exception (__SIZE_TYPE__);	// { dg-error "declared incorrectly" }
+extern "C" void __cxa_free_exception (void *);
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin10.C.jj	2018-12-15 13:00:41.135490052 +0100
+++ gcc/testsuite/g++.dg/eh/builtin10.C	2018-12-15 13:00:41.135490052 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" void __cxa_throw (void *, void *, void (*) (void *));
+extern "C" float __cxa_get_exception_ptr (void *);		// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_begin_catch (void *);
+extern "C" void __cxa_end_catch ();
+extern "C" void __cxa_rethrow ();
+extern "C" void *__cxa_allocate_exception (__SIZE_TYPE__);
+extern "C" int __cxa_free_exception (void *);			// { dg-error "declared incorrectly" }
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/eh/builtin11.C.jj	2018-12-15 13:00:41.135490052 +0100
+++ gcc/testsuite/g++.dg/eh/builtin11.C	2018-12-15 13:00:41.135490052 +0100
@@ -0,0 +1,29 @@
+// PR c++/88482
+// { dg-do compile }
+
+extern "C" void __cxa_throw (float, void *, void (*) (void *));	// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_get_exception_ptr (void *);
+extern "C" void *__cxa_begin_catch (int);			// { dg-error "declared incorrectly" }
+extern "C" void __cxa_end_catch (long long);			// { dg-error "declared incorrectly" }
+extern "C" void __cxa_rethrow (int);				// { dg-error "declared incorrectly" }
+extern "C" void *__cxa_allocate_exception (void *);		// { dg-error "declared incorrectly" }
+extern "C" void __cxa_free_exception (void *);
+
+struct S { S (); S (const S &); ~S (); };
+
+int
+foo (int x)
+{
+  if (x > 27)
+    throw 19;
+  try
+    {
+      if (x > 15)
+	throw S ();
+    }
+  catch (S s)
+    {
+      throw;
+    }
+  return x + 3;
+}
--- gcc/testsuite/g++.dg/parse/crash55.C.jj	2018-12-14 00:32:55.998201251 +0100
+++ gcc/testsuite/g++.dg/parse/crash55.C	2018-12-15 13:00:41.156489709 +0100
@@ -1,8 +1,8 @@
 // PR c++/42038
 
-extern int __cxa_begin_catch;
+extern int __cxa_begin_catch;	// { dg-error "declared incorrectly" }
 
 void f(void)
 {
-  try { } catch (int) { } // { dg-error "cannot be used" }
+  try { } catch (int) { }
 }
--- libitm/eh_cpp.cc.jj	2018-01-03 10:42:59.250764052 +0100
+++ libitm/eh_cpp.cc	2018-12-15 13:04:26.787804572 +0100
@@ -89,7 +89,7 @@ struct __cxa_eh_globals
 
 extern void *__cxa_allocate_exception (size_t) WEAK;
 extern void __cxa_free_exception (void *) WEAK;
-extern void __cxa_throw (void *, void *, void *) WEAK;
+extern void __cxa_throw (void *, void *, void (*) (void *)) WEAK;
 extern void *__cxa_begin_catch (void *) WEAK;
 extern void __cxa_end_catch (void) WEAK;
 extern void __cxa_tm_cleanup (void *, void *, unsigned int) WEAK;
@@ -98,7 +98,7 @@ extern __cxa_eh_globals *__cxa_get_globa
 #if !defined (HAVE_ELF_STYLE_WEAKREF) 
 void *__cxa_allocate_exception (size_t) { return NULL; }
 void __cxa_free_exception (void *) { return; }
-void __cxa_throw (void *, void *, void *) { return; }
+void __cxa_throw (void *, void *, void (*) (void *)) { return; }
 void *__cxa_begin_catch (void *) { return NULL; }
 void __cxa_end_catch (void) { return; }
 void __cxa_tm_cleanup (void *, void *, unsigned int) { return; }
@@ -136,7 +136,7 @@ _ITM_cxa_free_exception (void *exc_ptr)
 }
 
 void
-_ITM_cxa_throw (void *obj, void *tinfo, void *dest)
+_ITM_cxa_throw (void *obj, void *tinfo, void (*dest) (void *))
 {
   // This used to be instrumented, but does not need to be anymore.
   __cxa_throw (obj, tinfo, dest);
--- libitm/libitm.h.jj	2018-01-03 10:42:59.249764052 +0100
+++ libitm/libitm.h	2018-12-15 13:01:38.585551744 +0100
@@ -284,7 +284,7 @@ extern void _ITM_deregisterTMCloneTable
 
 extern void *_ITM_cxa_allocate_exception (size_t);
 extern void _ITM_cxa_free_exception (void *exc_ptr);
-extern void _ITM_cxa_throw (void *obj, void *tinfo, void *dest);
+extern void _ITM_cxa_throw (void *obj, void *tinfo, void (*dest) (void *));
 extern void *_ITM_cxa_begin_catch (void *exc_ptr);
 extern void _ITM_cxa_end_catch (void);
 extern void _ITM_commitTransactionEH(void *exc_ptr) ITM_REGPARM;
--- libitm/libitm.texi.jj	2018-01-03 10:10:52.879434767 +0100
+++ libitm/libitm.texi	2018-12-15 13:02:05.535111585 +0100
@@ -269,7 +269,7 @@ transactions.
 void _ITM_commitTransactionEH(void *exc_ptr) ITM_REGPARM;
 void *_ITM_cxa_allocate_exception (size_t);
 void _ITM_cxa_free_exception (void *exc_ptr);
-void _ITM_cxa_throw (void *obj, void *tinfo, void *dest);
+void _ITM_cxa_throw (void *obj, void *tinfo, void (*dest) (void *));
 void *_ITM_cxa_begin_catch (void *exc_ptr);
 void _ITM_cxa_end_catch (void);
 @end example

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++ PATCH] Sanity check __cxa_* user declarations (PR c++/88482)
  2018-12-15 13:09     ` Jakub Jelinek
@ 2018-12-15 22:14       ` Jason Merrill
  0 siblings, 0 replies; 5+ messages in thread
From: Jason Merrill @ 2018-12-15 22:14 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 12/15/18 8:08 AM, Jakub Jelinek wrote:
> On Sat, Dec 15, 2018 at 12:22:44PM +0100, Jakub Jelinek wrote:
>>> Fix libitm.
>>
>> Ok, will do.
> 
> Here it is in patch form:

OK, thanks.

Jason

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-12-15 22:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-13 23:30 [C++ PATCH] Sanity check __cxa_* user declarations (PR c++/88482) Jakub Jelinek
2018-12-14 21:59 ` Jason Merrill
2018-12-15 11:22   ` Jakub Jelinek
2018-12-15 13:09     ` Jakub Jelinek
2018-12-15 22:14       ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).