From e815887f4d7e3aaa8e68584729c18c9b3c5fef05 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 28 Apr 2000 00:21:06 +0000 Subject: [PATCH] re GNATS gcj/2 (Method call on null instance should throw NullPointerException) Fix for PR gcj/2: * expr.c (expand_invoke): Generate check to see if object pointer is null in nonvirtual invocation case. * java-tree.h (soft_nullpointer_node): Declare. * decl.c (soft_nullpointer_node): New global. (init_decl_processing): Initialize soft_nullpointer_node. * parse.y (invocation_mode): Return INVOKE_NONVIRTUAL for `final' or `private' methods. (patch_invoke): Handle INVOKE_NONVIRTUAL case. From-SVN: r33495 --- gcc/java/ChangeLog | 12 ++ gcc/java/decl.c | 10 + gcc/java/expr.c | 44 +++- gcc/java/java-tree.h | 1 + gcc/java/parse.c | 472 ++++++++++++++++++++----------------------- gcc/java/parse.y | 60 +++++- 6 files changed, 337 insertions(+), 262 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index daa3776d903..2f9190e1096 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,15 @@ +2000-04-27 Tom Tromey + + Fix for PR gcj/2: + * expr.c (expand_invoke): Generate check to see if object pointer + is null in nonvirtual invocation case. + * java-tree.h (soft_nullpointer_node): Declare. + * decl.c (soft_nullpointer_node): New global. + (init_decl_processing): Initialize soft_nullpointer_node. + * parse.y (invocation_mode): Return INVOKE_NONVIRTUAL for `final' + or `private' methods. + (patch_invoke): Handle INVOKE_NONVIRTUAL case. + Wed Apr 26 14:29:33 2000 Alexandre Petit-Bianco * decl.c (complete_start_java_method): Don't call _Jv_InitClass diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 659d4196838..385a8aa03ff 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -375,6 +375,7 @@ tree soft_newarray_node; tree soft_anewarray_node; tree soft_multianewarray_node; tree soft_badarrayindex_node; +tree soft_nullpointer_node; tree throw_node [2]; tree soft_checkarraystore_node; tree soft_monitorenter_node; @@ -813,6 +814,15 @@ init_decl_processing () TREE_THIS_VOLATILE (soft_badarrayindex_node) = 1; TREE_SIDE_EFFECTS (soft_badarrayindex_node) = 1; + soft_nullpointer_node + = builtin_function ("_Jv_ThrowNullPointerException", + build_function_type (void_type_node, endlink), + 0, NOT_BUILT_IN, NULL_PTR); + /* Mark soft_nullpointer_node as a `noreturn' function with side + effects. */ + TREE_THIS_VOLATILE (soft_nullpointer_node) = 1; + TREE_SIDE_EFFECTS (soft_nullpointer_node) = 1; + t = tree_cons (NULL_TREE, class_ptr_type, tree_cons (NULL_TREE, object_ptr_type_node, endlink)); soft_checkcast_node diff --git a/gcc/java/expr.c b/gcc/java/expr.c index c5fe6690a2c..5666502605e 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -1719,6 +1719,7 @@ expand_invoke (opcode, method_ref_index, nargs) (current_jcf, COMPONENT_REF_CLASS_INDEX(¤t_jcf->cpool, method_ref_index)); const char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type))); tree call, func, method, arg_list, method_type; + tree cond = NULL_TREE; if (! CLASS_LOADED_P (self_type)) { @@ -1781,13 +1782,29 @@ expand_invoke (opcode, method_ref_index, nargs) flush_quick_stack (); func = NULL_TREE; - if (opcode == OPCODE_invokestatic || opcode == OPCODE_invokespecial - || (opcode == OPCODE_invokevirtual - && (METHOD_PRIVATE (method) - || METHOD_FINAL (method) - || CLASS_FINAL (TYPE_NAME (self_type))))) + if (opcode == OPCODE_invokestatic) func = build_known_method_ref (method, method_type, self_type, method_signature, arg_list); + else if (opcode == OPCODE_invokespecial + || (opcode == OPCODE_invokevirtual + && (METHOD_PRIVATE (method) + || METHOD_FINAL (method) + || CLASS_FINAL (TYPE_NAME (self_type))))) + { + /* If the object for the method call is null, we throw an + exception. We don't do this if the object is the current + method's `this'. In other cases we just rely on an + optimization pass to eliminate redundant checks. FIXME: + Unfortunately there doesn't seem to be a way to determine + what the current method is right now. */ + /* We use a SAVE_EXPR here to make sure we only evaluate + the new `self' expression once. */ + tree save_arg = save_expr (TREE_VALUE (arg_list)); + TREE_VALUE (arg_list) = save_arg; + cond = build (EQ_EXPR, boolean_type_node, save_arg, null_pointer_node); + func = build_known_method_ref (method, method_type, self_type, + method_signature, arg_list); + } else { tree dtable = invoke_build_dtable (opcode == OPCODE_invokeinterface, @@ -1801,6 +1818,23 @@ expand_invoke (opcode, method_ref_index, nargs) call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE); TREE_SIDE_EFFECTS (call) = 1; + if (cond != NULL_TREE) + { + /* We have to make the `then' branch a compound expression to + make the types turn out right. This seems bizarre. */ + call = build (COND_EXPR, TREE_TYPE (call), cond, + build (COMPOUND_EXPR, TREE_TYPE (call), + build (CALL_EXPR, void_type_node, + build_address_of (soft_nullpointer_node), + NULL_TREE, NULL_TREE), + (FLOAT_TYPE_P (TREE_TYPE (call)) + ? build_real (TREE_TYPE (call), dconst0) + : build1 (CONVERT_EXPR, TREE_TYPE (call), + integer_zero_node))), + call); + TREE_SIDE_EFFECTS (call) = 1; + } + if (TREE_CODE (TREE_TYPE (method_type)) == VOID_TYPE) expand_expr_stmt (call); else diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index e38ed81b105..5e56a17da32 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -290,6 +290,7 @@ extern tree soft_newarray_node; extern tree soft_anewarray_node; extern tree soft_multianewarray_node; extern tree soft_badarrayindex_node; +extern tree soft_nullpointer_node; extern tree throw_node[]; extern tree soft_checkarraystore_node; extern tree soft_monitorenter_node; diff --git a/gcc/java/parse.c b/gcc/java/parse.c index 92598a5dd2a..f426eb984b1 100644 --- a/gcc/java/parse.c +++ b/gcc/java/parse.c @@ -1,6 +1,7 @@ /* A Bison parser, made from ./parse.y - by GNU Bison version 1.28 */ + by GNU Bison version 1.25 + */ #define YYBISON 1 /* Identify Bison output. */ @@ -11,113 +12,113 @@ #define yychar java_char #define yydebug java_debug #define yynerrs java_nerrs -#define PLUS_TK 257 -#define MINUS_TK 258 -#define MULT_TK 259 -#define DIV_TK 260 -#define REM_TK 261 -#define LS_TK 262 -#define SRS_TK 263 -#define ZRS_TK 264 -#define AND_TK 265 -#define XOR_TK 266 -#define OR_TK 267 -#define BOOL_AND_TK 268 -#define BOOL_OR_TK 269 -#define EQ_TK 270 -#define NEQ_TK 271 -#define GT_TK 272 -#define GTE_TK 273 -#define LT_TK 274 -#define LTE_TK 275 -#define PLUS_ASSIGN_TK 276 -#define MINUS_ASSIGN_TK 277 -#define MULT_ASSIGN_TK 278 -#define DIV_ASSIGN_TK 279 -#define REM_ASSIGN_TK 280 -#define LS_ASSIGN_TK 281 -#define SRS_ASSIGN_TK 282 -#define ZRS_ASSIGN_TK 283 -#define AND_ASSIGN_TK 284 -#define XOR_ASSIGN_TK 285 -#define OR_ASSIGN_TK 286 -#define PUBLIC_TK 287 -#define PRIVATE_TK 288 -#define PROTECTED_TK 289 -#define STATIC_TK 290 -#define FINAL_TK 291 -#define SYNCHRONIZED_TK 292 -#define VOLATILE_TK 293 -#define TRANSIENT_TK 294 -#define NATIVE_TK 295 -#define PAD_TK 296 -#define ABSTRACT_TK 297 -#define MODIFIER_TK 298 -#define DECR_TK 299 -#define INCR_TK 300 -#define DEFAULT_TK 301 -#define IF_TK 302 -#define THROW_TK 303 -#define BOOLEAN_TK 304 -#define DO_TK 305 -#define IMPLEMENTS_TK 306 -#define THROWS_TK 307 -#define BREAK_TK 308 -#define IMPORT_TK 309 -#define ELSE_TK 310 -#define INSTANCEOF_TK 311 -#define RETURN_TK 312 -#define VOID_TK 313 -#define CATCH_TK 314 -#define INTERFACE_TK 315 -#define CASE_TK 316 -#define EXTENDS_TK 317 -#define FINALLY_TK 318 -#define SUPER_TK 319 -#define WHILE_TK 320 -#define CLASS_TK 321 -#define SWITCH_TK 322 -#define CONST_TK 323 -#define TRY_TK 324 -#define FOR_TK 325 -#define NEW_TK 326 -#define CONTINUE_TK 327 -#define GOTO_TK 328 -#define PACKAGE_TK 329 -#define THIS_TK 330 -#define BYTE_TK 331 -#define SHORT_TK 332 -#define INT_TK 333 -#define LONG_TK 334 -#define CHAR_TK 335 -#define INTEGRAL_TK 336 -#define FLOAT_TK 337 -#define DOUBLE_TK 338 -#define FP_TK 339 -#define ID_TK 340 -#define REL_QM_TK 341 -#define REL_CL_TK 342 -#define NOT_TK 343 -#define NEG_TK 344 -#define ASSIGN_ANY_TK 345 -#define ASSIGN_TK 346 -#define OP_TK 347 -#define CP_TK 348 -#define OCB_TK 349 -#define CCB_TK 350 -#define OSB_TK 351 -#define CSB_TK 352 -#define SC_TK 353 -#define C_TK 354 -#define DOT_TK 355 -#define STRING_LIT_TK 356 -#define CHAR_LIT_TK 357 -#define INT_LIT_TK 358 -#define FP_LIT_TK 359 -#define TRUE_TK 360 -#define FALSE_TK 361 -#define BOOL_LIT_TK 362 -#define NULL_TK 363 +#define PLUS_TK 258 +#define MINUS_TK 259 +#define MULT_TK 260 +#define DIV_TK 261 +#define REM_TK 262 +#define LS_TK 263 +#define SRS_TK 264 +#define ZRS_TK 265 +#define AND_TK 266 +#define XOR_TK 267 +#define OR_TK 268 +#define BOOL_AND_TK 269 +#define BOOL_OR_TK 270 +#define EQ_TK 271 +#define NEQ_TK 272 +#define GT_TK 273 +#define GTE_TK 274 +#define LT_TK 275 +#define LTE_TK 276 +#define PLUS_ASSIGN_TK 277 +#define MINUS_ASSIGN_TK 278 +#define MULT_ASSIGN_TK 279 +#define DIV_ASSIGN_TK 280 +#define REM_ASSIGN_TK 281 +#define LS_ASSIGN_TK 282 +#define SRS_ASSIGN_TK 283 +#define ZRS_ASSIGN_TK 284 +#define AND_ASSIGN_TK 285 +#define XOR_ASSIGN_TK 286 +#define OR_ASSIGN_TK 287 +#define PUBLIC_TK 288 +#define PRIVATE_TK 289 +#define PROTECTED_TK 290 +#define STATIC_TK 291 +#define FINAL_TK 292 +#define SYNCHRONIZED_TK 293 +#define VOLATILE_TK 294 +#define TRANSIENT_TK 295 +#define NATIVE_TK 296 +#define PAD_TK 297 +#define ABSTRACT_TK 298 +#define MODIFIER_TK 299 +#define DECR_TK 300 +#define INCR_TK 301 +#define DEFAULT_TK 302 +#define IF_TK 303 +#define THROW_TK 304 +#define BOOLEAN_TK 305 +#define DO_TK 306 +#define IMPLEMENTS_TK 307 +#define THROWS_TK 308 +#define BREAK_TK 309 +#define IMPORT_TK 310 +#define ELSE_TK 311 +#define INSTANCEOF_TK 312 +#define RETURN_TK 313 +#define VOID_TK 314 +#define CATCH_TK 315 +#define INTERFACE_TK 316 +#define CASE_TK 317 +#define EXTENDS_TK 318 +#define FINALLY_TK 319 +#define SUPER_TK 320 +#define WHILE_TK 321 +#define CLASS_TK 322 +#define SWITCH_TK 323 +#define CONST_TK 324 +#define TRY_TK 325 +#define FOR_TK 326 +#define NEW_TK 327 +#define CONTINUE_TK 328 +#define GOTO_TK 329 +#define PACKAGE_TK 330 +#define THIS_TK 331 +#define BYTE_TK 332 +#define SHORT_TK 333 +#define INT_TK 334 +#define LONG_TK 335 +#define CHAR_TK 336 +#define INTEGRAL_TK 337 +#define FLOAT_TK 338 +#define DOUBLE_TK 339 +#define FP_TK 340 +#define ID_TK 341 +#define REL_QM_TK 342 +#define REL_CL_TK 343 +#define NOT_TK 344 +#define NEG_TK 345 +#define ASSIGN_ANY_TK 346 +#define ASSIGN_TK 347 +#define OP_TK 348 +#define CP_TK 349 +#define OCB_TK 350 +#define CCB_TK 351 +#define OSB_TK 352 +#define CSB_TK 353 +#define SC_TK 354 +#define C_TK 355 +#define DOT_TK 356 +#define STRING_LIT_TK 357 +#define CHAR_LIT_TK 358 +#define INT_LIT_TK 359 +#define FP_LIT_TK 360 +#define TRUE_TK 361 +#define FALSE_TK 362 +#define BOOL_LIT_TK 363 +#define NULL_TK 364 #line 48 "./parse.y" @@ -516,7 +517,7 @@ typedef union { #define YYFLAG -32768 #define YYNTBASE 110 -#define YYTRANSLATE(x) ((unsigned)(x) <= 363 ? yytranslate[x] : 272) +#define YYTRANSLATE(x) ((unsigned)(x) <= 364 ? yytranslate[x] : 272) static const char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -544,18 +545,18 @@ static const char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109 + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109 }; #if YYDEBUG != 0 @@ -2386,8 +2387,7 @@ static const short yycheck[] = { 3, #define YYPURE 1 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/lib/bison.simple" -/* This file comes from bison-1.28. */ +#line 3 "/usr/share/misc/bison.simple" /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. @@ -2404,67 +2404,47 @@ static const short yycheck[] = { 3, You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + /* This is the parser code that is written into each bison parser when the %semantic_parser declaration is not specified in the grammar. It was written by Richard Stallman by simplifying the hairy parser used when %semantic_parser is specified. */ -#ifndef YYSTACK_USE_ALLOCA -#ifdef alloca -#define YYSTACK_USE_ALLOCA -#else /* alloca not defined */ -#ifdef __GNUC__ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#else /* not GNU C. */ -#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) -#define YYSTACK_USE_ALLOCA -#include -#else /* not sparc */ -/* We think this test detects Watcom and Microsoft C. */ -/* This used to test MSDOS, but that is a bad idea - since that symbol is in the user namespace. */ -#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) -#if 0 /* No need for malloc.h, which pollutes the namespace; - instead, just don't use alloca. */ -#include -#endif -#else /* not MSDOS, or __TURBOC__ */ -#if defined(_AIX) -/* I don't know what this was needed for, but it pollutes the namespace. - So I turned it off. rms, 2 May 1997. */ -/* #include */ - #pragma alloca -#define YYSTACK_USE_ALLOCA -#else /* not MSDOS, or __TURBOC__, or _AIX */ -#if 0 -#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, - and on HPUX 10. Eventually we can turn this on. */ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#endif /* __hpux */ -#endif -#endif /* not _AIX */ -#endif /* not MSDOS, or __TURBOC__ */ -#endif /* not sparc */ -#endif /* not GNU C */ -#endif /* alloca not defined */ -#endif /* YYSTACK_USE_ALLOCA not defined */ - -#ifdef YYSTACK_USE_ALLOCA -#define YYSTACK_ALLOC alloca -#else -#define YYSTACK_ALLOC malloc -#endif - /* Note: there must be only one dollar sign in this file. It is replaced by the list of actions, each action as one case of the switch. */ @@ -2473,8 +2453,8 @@ static const short yycheck[] = { 3, #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab +#define YYACCEPT return(0) +#define YYABORT return(1) #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the @@ -2555,12 +2535,14 @@ int yydebug; /* nonzero means print parse trace */ #ifndef YYMAXDEPTH #define YYMAXDEPTH 10000 #endif - -/* Define __yy_memcpy. Note that the size argument - should be passed with type unsigned int, because that is what the non-GCC - definitions require. With GCC, __builtin_memcpy takes an arg - of type size_t, but it can handle unsigned int. */ +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +#ifndef YYPARSE_PARAM +int yyparse (void); +#endif +#endif + #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) #else /* not GNU C or C++ */ @@ -2572,7 +2554,7 @@ static void __yy_memcpy (to, from, count) char *to; char *from; - unsigned int count; + int count; { register char *f = from; register char *t = to; @@ -2587,10 +2569,10 @@ __yy_memcpy (to, from, count) /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void -__yy_memcpy (char *to, char *from, unsigned int count) +__yy_memcpy (char *to, char *from, int count) { - register char *t = to; register char *f = from; + register char *t = to; register int i = count; while (i-- > 0) @@ -2600,7 +2582,7 @@ __yy_memcpy (char *to, char *from, unsigned int count) #endif #endif -#line 217 "/usr/lib/bison.simple" +#line 196 "/usr/share/misc/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed into yyparse. The argument should have type void *. @@ -2621,15 +2603,6 @@ __yy_memcpy (char *to, char *from, unsigned int count) #define YYPARSE_PARAM_DECL #endif /* not YYPARSE_PARAM */ -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ -#ifdef YYPARSE_PARAM -int yyparse (void *); -#else -int yyparse (void); -#endif -#endif - int yyparse(YYPARSE_PARAM_ARG) YYPARSE_PARAM_DECL @@ -2658,7 +2631,6 @@ yyparse(YYPARSE_PARAM_ARG) #endif int yystacksize = YYINITDEPTH; - int yyfree_stacks = 0; #ifdef YYPURE int yychar; @@ -2743,32 +2715,18 @@ yynewstate: if (yystacksize >= YYMAXDEPTH) { yyerror("parser stack overflow"); - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } return 2; } yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; -#ifndef YYSTACK_USE_ALLOCA - yyfree_stacks = 1; -#endif - yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); - __yy_memcpy ((char *)yyss, (char *)yyss1, - size * (unsigned int) sizeof (*yyssp)); - yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); - __yy_memcpy ((char *)yyvs, (char *)yyvs1, - size * (unsigned int) sizeof (*yyvsp)); + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp)); #ifdef YYLSP_NEEDED - yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); - __yy_memcpy ((char *)yyls, (char *)yyls1, - size * (unsigned int) sizeof (*yylsp)); + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp)); #endif #endif /* no yyoverflow */ @@ -5020,7 +4978,7 @@ case 503: break;} } /* the action file gets copied in in place of this dollarsign */ -#line 543 "/usr/lib/bison.simple" +#line 498 "/usr/share/misc/bison.simple" yyvsp -= yylen; yyssp -= yylen; @@ -5215,30 +5173,6 @@ yyerrhandle: yystate = yyn; goto yynewstate; - - yyacceptlab: - /* YYACCEPT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 0; - - yyabortlab: - /* YYABORT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 1; } #line 2546 "./parse.y" @@ -12360,10 +12294,11 @@ patch_invoke (patch, method, args) { tree dtable, func; tree original_call, t, ta; + tree cond = NULL_TREE; /* Last step for args: convert build-in types. If we're dealing with a new TYPE() type call, the first argument to the constructor - isn't found in the incomming argument list, but delivered by + isn't found in the incoming argument list, but delivered by `new' */ t = TYPE_ARG_TYPES (TREE_TYPE (method)); if (TREE_CODE (patch) == NEW_CLASS_EXPR) @@ -12391,6 +12326,22 @@ patch_invoke (patch, method, args) func = build_invokevirtual (dtable, method); break; + case INVOKE_NONVIRTUAL: + /* If the object for the method call is null, we throw an + exception. We don't do this if the object is the current + method's `this'. In other cases we just rely on an + optimization pass to eliminate redundant checks. */ + if (TREE_VALUE (args) != current_this) + { + /* We use a SAVE_EXPR here to make sure we only evaluate + the new `self' expression once. */ + tree save_arg = save_expr (TREE_VALUE (args)); + TREE_VALUE (args) = save_arg; + cond = build (EQ_EXPR, boolean_type_node, save_arg, + null_pointer_node); + } + /* Fall through. */ + case INVOKE_SUPER: case INVOKE_STATIC: func = build_known_method_ref (method, TREE_TYPE (method), @@ -12416,7 +12367,7 @@ patch_invoke (patch, method, args) TREE_OPERAND (patch, 1) = args; original_call = patch; - /* We're processing a `new TYPE ()' form. New is called an its + /* We're processing a `new TYPE ()' form. New is called and its returned value is the first argument to the constructor. We build a COMPOUND_EXPR and use saved expression so that the overall NEW expression value is a pointer to a newly created and initialized @@ -12446,6 +12397,26 @@ patch_invoke (patch, method, args) TREE_SET_CODE (original_call, CALL_EXPR); patch = build (COMPOUND_EXPR, TREE_TYPE (new), patch, saved_new); } + + /* If COND is set, then we are building a check to see if the object + is NULL. */ + if (cond != NULL_TREE) + { + /* We have to make the `then' branch a compound expression to + make the types turn out right. This seems bizarre. */ + patch = build (COND_EXPR, TREE_TYPE (patch), cond, + build (COMPOUND_EXPR, TREE_TYPE (patch), + build (CALL_EXPR, void_type_node, + build_address_of (soft_nullpointer_node), + NULL_TREE, NULL_TREE), + (FLOAT_TYPE_P (TREE_TYPE (patch)) + ? build_real (TREE_TYPE (patch), dconst0) + : build1 (CONVERT_EXPR, TREE_TYPE (patch), + integer_zero_node))), + patch); + TREE_SIDE_EFFECTS (patch) = 1; + } + return patch; } @@ -12459,18 +12430,23 @@ invocation_mode (method, super) if (super) return INVOKE_SUPER; - if (access & ACC_STATIC || access & ACC_FINAL || access & ACC_PRIVATE) + if (access & ACC_STATIC) return INVOKE_STATIC; - if (CLASS_FINAL (TYPE_NAME (DECL_CONTEXT (method)))) - return INVOKE_STATIC; - - if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method)))) - return INVOKE_INTERFACE; - + /* We have to look for a constructor before we handle nonvirtual + calls; otherwise the constructor will look nonvirtual. */ if (DECL_CONSTRUCTOR_P (method)) return INVOKE_STATIC; + if (access & ACC_FINAL || access & ACC_PRIVATE) + return INVOKE_NONVIRTUAL; + + if (CLASS_FINAL (TYPE_NAME (DECL_CONTEXT (method)))) + return INVOKE_NONVIRTUAL; + + if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method)))) + return INVOKE_INTERFACE; + return INVOKE_VIRTUAL; } diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 13cbab8d671..576e624c9ff 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -9662,10 +9662,11 @@ patch_invoke (patch, method, args) { tree dtable, func; tree original_call, t, ta; + tree cond = NULL_TREE; /* Last step for args: convert build-in types. If we're dealing with a new TYPE() type call, the first argument to the constructor - isn't found in the incomming argument list, but delivered by + isn't found in the incoming argument list, but delivered by `new' */ t = TYPE_ARG_TYPES (TREE_TYPE (method)); if (TREE_CODE (patch) == NEW_CLASS_EXPR) @@ -9693,6 +9694,22 @@ patch_invoke (patch, method, args) func = build_invokevirtual (dtable, method); break; + case INVOKE_NONVIRTUAL: + /* If the object for the method call is null, we throw an + exception. We don't do this if the object is the current + method's `this'. In other cases we just rely on an + optimization pass to eliminate redundant checks. */ + if (TREE_VALUE (args) != current_this) + { + /* We use a SAVE_EXPR here to make sure we only evaluate + the new `self' expression once. */ + tree save_arg = save_expr (TREE_VALUE (args)); + TREE_VALUE (args) = save_arg; + cond = build (EQ_EXPR, boolean_type_node, save_arg, + null_pointer_node); + } + /* Fall through. */ + case INVOKE_SUPER: case INVOKE_STATIC: func = build_known_method_ref (method, TREE_TYPE (method), @@ -9718,7 +9735,7 @@ patch_invoke (patch, method, args) TREE_OPERAND (patch, 1) = args; original_call = patch; - /* We're processing a `new TYPE ()' form. New is called an its + /* We're processing a `new TYPE ()' form. New is called and its returned value is the first argument to the constructor. We build a COMPOUND_EXPR and use saved expression so that the overall NEW expression value is a pointer to a newly created and initialized @@ -9748,6 +9765,26 @@ patch_invoke (patch, method, args) TREE_SET_CODE (original_call, CALL_EXPR); patch = build (COMPOUND_EXPR, TREE_TYPE (new), patch, saved_new); } + + /* If COND is set, then we are building a check to see if the object + is NULL. */ + if (cond != NULL_TREE) + { + /* We have to make the `then' branch a compound expression to + make the types turn out right. This seems bizarre. */ + patch = build (COND_EXPR, TREE_TYPE (patch), cond, + build (COMPOUND_EXPR, TREE_TYPE (patch), + build (CALL_EXPR, void_type_node, + build_address_of (soft_nullpointer_node), + NULL_TREE, NULL_TREE), + (FLOAT_TYPE_P (TREE_TYPE (patch)) + ? build_real (TREE_TYPE (patch), dconst0) + : build1 (CONVERT_EXPR, TREE_TYPE (patch), + integer_zero_node))), + patch); + TREE_SIDE_EFFECTS (patch) = 1; + } + return patch; } @@ -9761,18 +9798,23 @@ invocation_mode (method, super) if (super) return INVOKE_SUPER; - if (access & ACC_STATIC || access & ACC_FINAL || access & ACC_PRIVATE) + if (access & ACC_STATIC) return INVOKE_STATIC; - if (CLASS_FINAL (TYPE_NAME (DECL_CONTEXT (method)))) - return INVOKE_STATIC; - - if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method)))) - return INVOKE_INTERFACE; - + /* We have to look for a constructor before we handle nonvirtual + calls; otherwise the constructor will look nonvirtual. */ if (DECL_CONSTRUCTOR_P (method)) return INVOKE_STATIC; + if (access & ACC_FINAL || access & ACC_PRIVATE) + return INVOKE_NONVIRTUAL; + + if (CLASS_FINAL (TYPE_NAME (DECL_CONTEXT (method)))) + return INVOKE_NONVIRTUAL; + + if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method)))) + return INVOKE_INTERFACE; + return INVOKE_VIRTUAL; }