summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2000-04-28 00:21:06 +0000
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2000-04-28 00:21:06 +0000
commitd31bba8b87a06bf99851897c356d5c1161aebd4f (patch)
tree8b68598e702242c042747ef9d9b00aed4e7d7ab0
parentc2f99343ee5eab9521d49d7ec7ec1ea85a6d728d (diff)
downloadgcc-d31bba8b87a06bf99851897c356d5c1161aebd4f.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@33495 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/java/ChangeLog12
-rw-r--r--gcc/java/decl.c10
-rw-r--r--gcc/java/expr.c44
-rw-r--r--gcc/java/java-tree.h1
-rw-r--r--gcc/java/parse.c452
-rw-r--r--gcc/java/parse.y58
6 files changed, 326 insertions, 251 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 <tromey@cygnus.com>
+
+ 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 <apbianco@cygnus.com>
* 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(&current_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,66 +2404,46 @@ 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. */
-/* 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 */
+#ifndef alloca
#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
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
#include <alloca.h>
#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. */
+#if defined (MSDOS) && !defined (__TURBOC__)
#include <malloc.h>
-#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 <malloc.h> */
+#include <malloc.h>
#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
+#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
#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 */
+#endif /* not sparc. */
+#endif /* not GNU C. */
+#endif /* alloca not defined. */
-#ifdef YYSTACK_USE_ALLOCA
-#define YYSTACK_ALLOC alloca
-#else
-#define YYSTACK_ALLOC malloc
-#endif
+/* 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. */
/* Note: there must be only one dollar sign in this file.
It is replaced by the list of actions, each action
@@ -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,17 +12430,22 @@ 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))))
+ /* 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;
-
- if (DECL_CONSTRUCTOR_P (method))
- return INVOKE_STATIC;
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,17 +9798,22 @@ 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))))
+ /* 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;
-
- if (DECL_CONSTRUCTOR_P (method))
- return INVOKE_STATIC;
return INVOKE_VIRTUAL;
}