diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-04-28 00:21:06 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-04-28 00:21:06 +0000 |
commit | d31bba8b87a06bf99851897c356d5c1161aebd4f (patch) | |
tree | 8b68598e702242c042747ef9d9b00aed4e7d7ab0 /gcc/java/parse.y | |
parent | c2f99343ee5eab9521d49d7ec7ec1ea85a6d728d (diff) | |
download | gcc-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
Diffstat (limited to 'gcc/java/parse.y')
-rw-r--r-- | gcc/java/parse.y | 58 |
1 files changed, 50 insertions, 8 deletions
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; } |