This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ PATCH] Enforce extern "Java" aggregates to be heap allocated (PR c++/30293, c++/30294)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Mark Mitchell <mark at codesourcery dot com>
- Cc: Jason Merrill <jason at redhat dot com>, Tom Tromey <tromey at redhat dot com>, Andrew Haley <aph at redhat dot com>, gcc-patches at gcc dot gnu dot org
- Date: Fri, 23 Nov 2007 14:52:04 -0500
- Subject: Re: [C++ PATCH] Enforce extern "Java" aggregates to be heap allocated (PR c++/30293, c++/30294)
- References: <20071122125107.GX5451@devserv.devel.redhat.com> <474720A0.3050102@codesourcery.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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