C++ and Java CNI: Check Java references

Andrew Haley aph@cambridge.redhat.com
Mon Apr 23 11:46:00 GMT 2001


The semantics of Java require dereferencing a null pointer to an
object to throw a NullPointerException.  We already generate code to
do this in the Java compiler; this patch is for CNI code that is
written in C++.

An alternative way to do this is to trap SEGV and throw an exception
from a signal handler but not every processor/OS combination allows
this, and we haven't ported code to do this to many systems.

This patch only throws a NullPointerException from references to Java
objects, not for arbitrary pointer dereferencing.  People writing CNI
code had better check non-Java pointers themselves.

I'm not absolutely sure where this option should be documented.
Should it be documented anywhere other than in the gcj docs?

There is an associated patch for libgcj that is required in order to
use this option.

Andrew.



2001-04-23  Andrew Haley  <aph@cambridge.redhat.com>

	* lang-options.h: Document "-fcheck-java-references".
	* decl2.c (flag_check_java_references): New flag.
	* cp-tree.h (flag_check_java_references): New flag.
	(lang_f_options): Set lang_check_java_references.
	(check_java_reference): New function.
	* call.c (check_java_reference): New function.
	* typeck.c (build_indirect_ref): Call check_java_reference on Java
	objects.

Index: call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.265
diff -p -2 -c -r1.265 call.c
*** call.c	2001/03/23 01:49:10	1.265
--- call.c	2001/04/23 17:18:18
*************** initialize_reference (type, expr)
*** 5534,5535 ****
--- 5534,5591 ----
    return convert_like (conv, expr);
  }
+ 
+ static tree java_nullpointer_exception;
+ 
+ tree
+ check_java_reference (exp)
+      tree exp;
+ {
+   tree e = exp;
+   
+   if (!flag_check_java_references)
+     return exp;
+   
+   /* Strip off all pointer conversions and if the thing at the root is
+      an integer we won't bother to check it.  The main reason for this
+      is that offsetof is often defined as
+ 
+      ((size_t)&((type *)0)->memb)
+ 
+      which implicitly dereferences a null pointer.  Let's not check that.  */
+ 
+   while (TREE_CODE (e) == NOP_EXPR
+ 	 && TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE)
+     (e) = TREE_OPERAND (e, 0);
+   
+   if (TREE_CODE (e) == INTEGER_CST)
+     return exp;
+ 
+   if (java_nullpointer_exception == NULL_TREE)
+     {
+       tree endlink = build_void_list_node ();
+       java_nullpointer_exception
+ 	= builtin_function ("_Jv_ThrowNullPointerException",
+ 			    build_function_type (void_type_node, endlink),
+ 			    0, NOT_BUILT_IN, NULL_PTR);
+       TREE_THIS_VOLATILE (java_nullpointer_exception) = 1;
+       TREE_SIDE_EFFECTS (java_nullpointer_exception) = 1;
+       java_nullpointer_exception 
+ 	= build1 (ADDR_EXPR, 
+ 		  build_pointer_type 
+ 		  (TREE_TYPE (java_nullpointer_exception)), 
+ 		  java_nullpointer_exception);
+       ggc_add_tree_root (&java_nullpointer_exception, 1);
+     }
+ 
+   exp = stabilize_reference (exp);
+   {
+     tree cond = build (NE_EXPR, boolean_type_node, exp, integer_zero_node);
+     tree bad = 
+       build (CALL_EXPR, void_type_node, 
+ 	     java_nullpointer_exception,
+ 	     NULL_TREE, NULL_TREE);
+     exp = build (COND_EXPR, TREE_TYPE (exp), cond, exp, bad);
+   }
+      
+   return exp;
+ }
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.590
diff -p -2 -c -r1.590 cp-tree.h
*** cp-tree.h	2001/03/26 08:37:24	1.590
--- cp-tree.h	2001/04/23 17:18:28
*************** extern int flag_access_control;
*** 1146,1149 ****
--- 1146,1153 ----
  extern int flag_check_new;
  
+ /* Java objects: when non zero, generate checks for references to
+    NULL.  */
+ extern int flag_check_java_references;
+ 
  /* Nonnull if we want to dump class heirarchies. */
  
*************** extern tree initialize_reference        
*** 3699,3702 ****
--- 3703,3707 ----
  extern tree strip_top_quals                     PARAMS ((tree));
  extern tree perform_implicit_conversion         PARAMS ((tree, tree));
+ extern tree check_java_reference		PARAMS ((tree));
  
  /* in class.c */
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.448
diff -p -2 -c -r1.448 decl2.c
*** decl2.c	2001/03/22 00:55:11	1.448
--- decl2.c	2001/04/23 17:18:38
*************** int flag_enforce_eh_specs = 1;
*** 448,451 ****
--- 448,455 ----
  c_language_kind c_language = clk_cplusplus;
  
+ /* Java objects: when non zero, generate checks for references to
+    NULL.  */
+ int flag_check_java_references = 0;
+ 
  /* Table of language-dependent -f options.
     STRING is the option name.  VARIABLE is the address of the variable.
*************** lang_f_options[] =
*** 471,474 ****
--- 475,479 ----
    {"access-control", &flag_access_control, 1},
    {"check-new", &flag_check_new, 1},
+   {"check-java-references", &flag_check_java_references, 1},
    {"conserve-space", &flag_conserve_space, 1},
    {"const-strings", &flag_const_strings, 1},
Index: lang-options.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/lang-options.h,v
retrieving revision 1.37
diff -p -2 -c -r1.37 lang-options.h
*** lang-options.h	2001/01/05 19:12:19	1.37
--- lang-options.h	2001/04/23 17:18:40
*************** DEFINE_LANG_NAME ("C++")
*** 112,115 ****
--- 112,116 ----
    { "-fxref", "Emit cross referencing information" },
    { "-fno-xref", "" },
+   { "-fcheck-java-references", "Generate null pointer checks for Java objects" },
  
    { "-Wreturn-type", "Warn about inconsistent return types" },
Index: typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.342
diff -p -2 -c -r1.342 typeck.c
*** typeck.c	2001/03/06 20:45:05	1.342
--- typeck.c	2001/04/23 17:18:45
*************** build_indirect_ref (ptr, errorstring)
*** 2380,2384 ****
        else
  	{
! 	  tree ref = build1 (INDIRECT_REF, t, pointer);
  
  	  /* We *must* set TREE_READONLY when dereferencing a pointer to const,
--- 2380,2388 ----
        else
  	{
! 	  tree ref 
! 	    = build1 (INDIRECT_REF, t, 
! 		      TYPE_FOR_JAVA (t) && AGGREGATE_TYPE_P (t)
! 		      ? check_java_reference (pointer) 
! 		      : pointer);
  
  	  /* We *must* set TREE_READONLY when dereferencing a pointer to const,



More information about the Gcc-patches mailing list