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]

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


On Fri, Nov 23, 2007 at 10:49:04AM -0800, Mark Mitchell wrote:
> Jakub Jelinek wrote:
> 
> > 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).
> 
> This looks OK, but I've picked some nits.  I'd also like one of the Java
> maintainers to sign off on the concept, just to be sure that we don't
> break Java CNI code in the field.

Already got one from Andrew Haley.
http://gcc.gnu.org/ml/gcc-patches/2007-11/msg01155.html

Thanks for your comments, incorporated below.

> > +  else if (TYPE_FOR_JAVA (elt_type))
> > +    {
> > +      error ("Java class %q#T object allocated using placement new", elt_type);
> > +      return error_mark_node;
> > +    }
> 
> I don't think this one is safe.  We can't know that placement new
> doesn't do heap allocation.

Yeah, placement new might allocate on the heap, but libjava doesn't care as
much if it was heap allocated or not, but if it was allocated by libjava
itself as a Java object, which is something non-placement new code in
build_new_1 takes care of.  For placement new there is no such code, libjava
is not interested in users allocating one object and then through placement
new claim it is a different one, etc.  So I think it is desirable to
disallow that.

Ok?

2007-11-23  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-23 20:33:02.000000000 +0100
+++ gcc/cp/decl.c	2007-11-23 20:38:21.000000000 +0100
@@ -5468,6 +5468,20 @@ 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
+		= IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
+	      /* Allow libjava/prims.cc define primitive classes.  */
+	      if (init != NULL_TREE
+		  || jclass == NULL_TREE
+		  || TREE_CODE (jclass) != TYPE_DECL
+		  || !POINTER_TYPE_P (TREE_TYPE (jclass))
+		  || !same_type_ignoring_top_level_qualifiers_p
+					(type, TREE_TYPE (TREE_TYPE (jclass))))
+		error ("Java object %qD not allocated with %<new%>", decl);
+	      init = NULL_TREE;
+	    }
 	  if (init)
 	    {
 	      DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
@@ -5538,6 +5552,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 ("non-static data member %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 +9345,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 has 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 +10941,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 ("return type has Java class type %q#T", return_type);
 
       /* Make it return void instead.  */
       if (TREE_CODE (fntype) == METHOD_TYPE)
--- gcc/cp/init.c.jj	2007-11-23 20:33:02.000000000 +0100
+++ gcc/cp/init.c	2007-11-23 20:33:49.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-23 20:33:49.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/java-2.C	2007-11-23 20:33:49.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 "not allocated with" }
+A b = A ();	// { dg-error "not allocated with" }
+A *c = new ((void *) buf) A ();	// { dg-error "using placement new" }
+A *d = new A ();
+jbyte e = 6;
+
+const A fn1 ()	// { dg-error "return type has Java class type" }
+{
+  A a;		// { dg-error "not allocated with" }
+  return a;
+}
+
+A fn2 ()	// { dg-error "return type has Java class type" }
+{
+  A a;		// { dg-error "not allocated with" }
+  return a;
+}
+
+A *fn3 ()
+{
+  return new A ();
+}
+
+A &fn4 ()
+{
+  return *c;
+}
+
+jbyte fn5 ()
+{
+  return 7;
+}
+
+void fn6 (A x)	// { dg-error "has Java class type" }
+{
+}
+
+void fn7 (const A x)	// { dg-error "has 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]