diff mbox

[C++] Diagnose invalid _Jv_AllocObject prototype (PR c++/70267)

Message ID 20160317193544.GP3017@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek March 17, 2016, 7:35 p.m. UTC
Hi!

_Jv_AllocObject returns a pointer, and as the testcase below shows,
we easily ICE if a wrong prototype is provided for it instead.
There is already other diagnostics (e.g. when it is missing, or when
it is overloaded function), so this ensures at least the return type
is sane.

Wonder about all the other spots where the C++ FE relies on user prototypes
for __cxa* etc. functions, perhaps some sanity checking will be needed too
to avoid ICEs on invalid stuff.

Bootstrapped/regtested on x86_64-linux and i686-linux (including java on
both as usually), ok for trunk?

2016-03-17  Jakub Jelinek  <jakub@redhat.com>

	PR c++/70267
	* init.c (build_new_1): Complain and return error_mark_node
	if alloc_fn is not _Jv_AllocObject function returning pointer.

	* g++.dg/ext/java-3.C: New test.


	Jakub

Comments

Jason Merrill March 18, 2016, 2:30 a.m. UTC | #1
On 03/17/2016 03:35 PM, Jakub Jelinek wrote:
> _Jv_AllocObject returns a pointer, and as the testcase below shows,
> we easily ICE if a wrong prototype is provided for it instead.
> There is already other diagnostics (e.g. when it is missing, or when
> it is overloaded function), so this ensures at least the return type
> is sane.

OK.

> Wonder about all the other spots where the C++ FE relies on user prototypes
> for __cxa* etc. functions, perhaps some sanity checking will be needed too
> to avoid ICEs on invalid stuff.

I think the compiler generates internal declarations for all the __cxa* 
functions.  We've run into issues with broken definitions of 
std::initializer_list, but we have sanity checks on that now.

Jason
diff mbox

Patch

--- gcc/cp/init.c.jj	2016-03-05 07:46:50.000000000 +0100
+++ gcc/cp/init.c	2016-03-17 17:18:21.326917746 +0100
@@ -2872,6 +2872,14 @@  build_new_1 (vec<tree, va_gc> **placemen
 	  return error_mark_node;
 	}
       alloc_fn = OVL_CURRENT (alloc_fn);
+      if (TREE_CODE (alloc_fn) != FUNCTION_DECL
+	  || TREE_CODE (TREE_TYPE (alloc_fn)) != FUNCTION_TYPE
+	  || !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (alloc_fn))))
+	{
+	  if (complain & tf_error)
+	    error ("%qD is not a function returning a pointer", alloc_fn);
+	  return error_mark_node;
+	}
       class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
       alloc_call = cp_build_function_call_nary (alloc_fn, complain,
 						class_addr, NULL_TREE);
--- gcc/testsuite/g++.dg/ext/java-3.C.jj	2016-03-17 18:25:26.417381245 +0100
+++ gcc/testsuite/g++.dg/ext/java-3.C	2016-03-17 18:24:48.000000000 +0100
@@ -0,0 +1,39 @@ 
+// PR c++/70267
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern "Java"
+{
+  typedef __java_int jint;
+  namespace java
+  {
+    namespace lang
+    {
+      class Class;
+      class Object;
+      class Throwable {};
+      class Foo;
+    }
+  }
+} 
+
+typedef struct java::lang::Object * jobject;
+typedef struct java::lang::Throwable * jthrowable;
+typedef class  java::lang::Class * jclass;
+
+using java::lang::Foo;
+
+class Foo: public java::lang::Throwable
+{
+  public:static::java::lang::Class class$;
+};
+
+extern "C" Foo _Jv_AllocObject (jclass);
+extern "C" void _Jv_Throw (jthrowable) __attribute__ ((__noreturn__));
+
+void 
+Bar4 (void)
+{
+  Foo * f = new java::lang::Foo;	// { dg-error "is not a function returning a pointer" }
+  throw (f);
+}