This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Enforce extern "Java" aggregates to be heap allocated (PR c++/30293, c++/30294)


Hi!

gcj.texi says:

All of the listed attributes are also true of C++, though C++ has
extra features (for example in C++ objects may be allocated not just
on the heap, but also statically or in a local stack frame).

There is a couple of ICEs where invalid code defines extern "Java"
aggregates with initializers or returns them from a function.

Tom suggested in the bugzilla that we should enforce that extern "Java"
objects are always heap allocated and the following patch does that
and cures the ICEs at the same time.

The only exception I had to make is for libjava/prims.cc where we have:
// Ensure 8-byte alignment, for hash synchronization.
#define DECLARE_PRIM_TYPE(NAME)                 \
  java::lang::Class _Jv_##NAME##Class __attribute__ ((aligned (8)));

DECLARE_PRIM_TYPE(byte)
DECLARE_PRIM_TYPE(short)
DECLARE_PRIM_TYPE(int)
DECLARE_PRIM_TYPE(long)
DECLARE_PRIM_TYPE(boolean)
DECLARE_PRIM_TYPE(char)
DECLARE_PRIM_TYPE(float)
DECLARE_PRIM_TYPE(double)
DECLARE_PRIM_TYPE(void)

which at least don't have any initializer and thus shouldn't cause ICEs.
Even then I limited this exception for __typeof (*jclass) objects without
initializers only.

The testcase shows what is and is not allowed.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2007-11-22  Jakub Jelinek  <jakub@redhat.com>

	PR c++/30293
	PR c++/30294
	* decl.c (cp_finish_decl): Disallow variable or field
	definitions if extern "Java" aggregates.
	(grokparms): Disallow parameters with extern "Java"
	aggregates.
	(check_function_type): Disallow function return values
	with extern "Java" aggregates.
	* init.c (build_new_1): Disallow placement new with
	extern "Java" aggregates.

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

--- gcc/cp/decl.c.jj	2007-11-19 17:46:41.000000000 +0100
+++ gcc/cp/decl.c	2007-11-22 13:34:52.000000000 +0100
@@ -5468,6 +5468,21 @@ cp_finish_decl (tree decl, tree init, bo
 	     is *not* defined.  */
 	  && (!DECL_EXTERNAL (decl) || init))
 	{
+	  if (TYPE_FOR_JAVA (type) && IS_AGGR_TYPE (type))
+	    {
+	      tree jclass;
+	      /* Allow libjava/prims.cc define primitive classes.  */
+	      if (init != NULL_TREE
+		  || (jclass
+		      = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass")))
+		     == NULL_TREE
+		  || TREE_CODE (jclass) != TYPE_DECL
+		  || !POINTER_TYPE_P (TREE_TYPE (jclass))
+		  || TYPE_MAIN_VARIANT (type)
+		     != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (jclass))))
+		error ("Java object %qD must be heap allocated", decl);
+	      init = NULL_TREE;
+	    }
 	  if (init)
 	    {
 	      DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
@@ -5538,6 +5553,9 @@ cp_finish_decl (tree decl, tree init, bo
       else if (TREE_CODE (type) == ARRAY_TYPE)
 	layout_type (type);
     }
+  else if (TREE_CODE (decl) == FIELD_DECL
+	   && TYPE_FOR_JAVA (type) && IS_AGGR_TYPE (type))
+    error ("field %qD has Java class type", decl);
 
   /* Add this declaration to the statement-tree.  This needs to happen
      after the call to check_initializer so that the DECL_EXPR for a
@@ -9328,6 +9346,16 @@ grokparms (cp_parameter_declarator *firs
 	  TREE_TYPE (decl) = error_mark_node;
 	}
 
+      if (type != error_mark_node
+	  && TYPE_FOR_JAVA (type)
+	  && IS_AGGR_TYPE (type))
+	{
+	  error ("parameter %qD invalidly declared Java class type", decl);
+	  type = error_mark_node;
+	  TREE_TYPE (decl) = error_mark_node;
+	  init = NULL_TREE;
+	}
+
       if (type != error_mark_node)
 	{
 	  /* Top-level qualifiers on the parameters are
@@ -10914,11 +10942,15 @@ check_function_type (tree decl, tree cur
 
   if (dependent_type_p (return_type))
     return;
-  if (!COMPLETE_OR_VOID_TYPE_P (return_type))
+  if (!COMPLETE_OR_VOID_TYPE_P (return_type)
+      || (TYPE_FOR_JAVA (return_type) && IS_AGGR_TYPE (return_type)))
     {
       tree args = TYPE_ARG_TYPES (fntype);
 
-      error ("return type %q#T is incomplete", return_type);
+      if (!COMPLETE_OR_VOID_TYPE_P (return_type))
+	error ("return type %q#T is incomplete", return_type);
+      else
+	error ("returning Java type %q#T by value", return_type);
 
       /* Make it return void instead.  */
       if (TREE_CODE (fntype) == METHOD_TYPE)
--- gcc/cp/init.c.jj	2007-09-20 21:26:48.000000000 +0200
+++ gcc/cp/init.c	2007-11-22 10:49:47.000000000 +0100
@@ -1786,6 +1786,11 @@ build_new_1 (tree placement, tree type, 
 		    (alloc_fn,
 		     build_tree_list (NULL_TREE, class_addr)));
     }
+  else if (TYPE_FOR_JAVA (elt_type))
+    {
+      error ("Java class %q#T object allocated using placement new", elt_type);
+      return error_mark_node;
+    }
   else
     {
       tree fnname;
--- gcc/testsuite/g++.dg/ext/java-2.C.jj	2007-11-22 10:55:10.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/java-2.C	2007-11-22 10:54:59.000000000 +0100
@@ -0,0 +1,79 @@
+// PR c++/30293
+// PR c++/30294
+// { dg-do compile }
+// { dg-options "" }
+
+extern "Java" {
+typedef __java_byte jbyte;
+namespace java {
+namespace lang {
+  class Object {};
+  class Class {};
+}
+}
+typedef struct java::lang::Object* jobject;
+typedef java::lang::Class *jclass;
+}
+extern "C" jobject _Jv_AllocObject (jclass);
+
+extern "Java" {
+  struct A { static java::lang::Class class$; };
+}
+
+struct B {
+  A a;		// { dg-error "has Java class type" }
+};
+
+void* operator new (__SIZE_TYPE__, void*) throw();
+char buf[1024];
+
+A a;		// { dg-error "must be heap allocated" }
+A b = A ();	// { dg-error "must be heap allocated" }
+A *c = new ((void *) buf) A ();	// { dg-error "using placement new" }
+A *d = new A ();
+jbyte e = 6;
+
+const A fn1 ()	// { dg-error "returning Java type" }
+{
+  A a;		// { dg-error "must be heap allocated" }
+  return a;
+}
+
+A fn2 ()	// { dg-error "returning Java type" }
+{
+  A a;		// { dg-error "must be heap allocated" }
+  return a;
+}
+
+A *fn3 ()
+{
+  return new A ();
+}
+
+A &fn4 ()
+{
+  return *c;
+}
+
+jbyte fn5 ()
+{
+  return 7;
+}
+
+void fn6 (A x)	// { dg-error "invalidly declared Java class type" }
+{
+}
+
+void fn7 (const A x)	// { dg-error "invalidly declared Java class type" }
+{
+}
+
+void fn8 (A *x)
+{
+  (void) x;
+}
+
+void fn9 (jbyte x)
+{
+  (void) x;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]