This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: gcj -vs- largest negative number
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Subject: Patch: gcj -vs- largest negative number
- From: Tom Tromey <tromey at redhat dot com>
- Date: 14 Dec 2000 09:44:11 -0700
- Reply-To: tromey at redhat dot com
According to the JLS, `2147483648' is only valid if it is the argument
of unary `-'. However, gcj also incorrectly accepts it as the
argument of binary `-'.
This patch fixes that error.
This isn't the prettiest patch. In fact it is ugly. I couldn't think
of another way to implement this functionality.
Comments?
Ok to commit?
2000-11-19 Tom Tromey <tromey@cygnus.com>
* parse.y (trap_overflow_corner_case): New rule.
(unary_expression): Use it.
* lex.c (java_init_lex): Don't set minus_seen.
(yylex): Don't use minus_seen. Communicate overflow to parser for
it to handle.
(error_if_numeric_overflow): New function.
* parse.h (minus_seen): Removed field.
(JAVA_RADIX10_FLAG): New define.
Tom
Index: lex.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/lex.c,v
retrieving revision 1.55
diff -u -r1.55 lex.c
--- lex.c 2000/12/13 22:47:13 1.55
+++ lex.c 2000/12/14 16:13:18
@@ -62,6 +62,9 @@
static void java_unget_unicode PARAMS ((void));
static unicode_t java_sneak_unicode PARAMS ((void));
java_lexer *java_new_lexer PARAMS ((FILE *, const char *));
+#ifndef JC1_LITE
+static void error_if_numeric_overflow PARAMS ((tree));
+#endif
/* This is nonzero if we have initialized `need_byteswap'. */
static int byteswap_init = 0;
@@ -126,7 +129,6 @@
ctxp->lineno = lineno = 0;
ctxp->p_line = NULL;
ctxp->c_line = NULL;
- ctxp->minus_seen = 0;
ctxp->java_error_flag = 0;
ctxp->lexer = java_new_lexer (finput, encoding);
}
@@ -967,6 +969,7 @@
int i;
#ifndef JC1_LITE
int number_beginning = ctxp->c_line->current;
+ tree value;
#endif
/* We might have a . separator instead of a FP like .[0-9]* */
@@ -1197,9 +1200,8 @@
expressed using a 10 radix. For other radixes, everything that
fits withing 64 bits is OK. */
int hb = (high >> 31);
- if (overflow || (hb && low && radix == 10) ||
- (hb && high & 0x7fffffff && radix == 10) ||
- (hb && !(high & 0x7fffffff) && !ctxp->minus_seen && radix == 10))
+ if (overflow || (hb && low && radix == 10)
+ || (hb && high & 0x7fffffff && radix == 10))
JAVA_INTEGRAL_RANGE_ERROR ("Numeric overflow for `long' literal");
}
else
@@ -1210,19 +1212,21 @@
that fits within 32 bits is OK. As all literals are
signed, we sign extend here. */
int hb = (low >> 31) & 0x1;
- if (overflow || high || (hb && low & 0x7fffffff && radix == 10) ||
- (hb && !(low & 0x7fffffff) && !ctxp->minus_seen && radix == 10))
+ if (overflow || high || (hb && low & 0x7fffffff && radix == 10))
JAVA_INTEGRAL_RANGE_ERROR ("Numeric overflow for `int' literal");
high = -hb;
}
- ctxp->minus_seen = 0;
+#ifndef JC1_LITE
+ value = build_int_2 (low, high);
+ JAVA_RADIX10_FLAG (value) = radix == 10;
+ SET_LVAL_NODE_TYPE (value, long_suffix ? long_type_node : int_type_node);
+#else
SET_LVAL_NODE_TYPE (build_int_2 (low, high),
- (long_suffix ? long_type_node : int_type_node));
+ long_suffix ? long_type_node : int_type_node);
+#endif
return INT_LIT_TK;
}
- ctxp->minus_seen = 0;
-
/* Character literals */
if (c == '\'')
{
@@ -1439,7 +1443,6 @@
BUILD_OPERATOR2 (MINUS_ASSIGN_TK);
default:
java_unget_unicode ();
- ctxp->minus_seen = 1;
BUILD_OPERATOR (MINUS_TK);
}
@@ -1612,6 +1615,37 @@
}
return 0;
}
+
+#ifndef JC1_LITE
+/* This is called by the parser to see if an error should be generated
+ due to numeric overflow. This function only handles the particular
+ case of the largest negative value, and is only called in the case
+ where this value is not preceeded by `-'. */
+static void
+error_if_numeric_overflow (value)
+ tree value;
+{
+ if (TREE_CODE (value) == INTEGER_CST && JAVA_RADIX10_FLAG (value))
+ {
+ unsigned HOST_WIDE_INT lo, hi;
+
+ lo = TREE_INT_CST_LOW (value);
+ hi = TREE_INT_CST_HIGH (value);
+ if (TREE_TYPE (value) == long_type_node)
+ {
+ int hb = (hi >> 31);
+ if (hb && !(hi & 0x7fffffff))
+ java_lex_error ("Numeric overflow for `long' literal", 0);
+ }
+ else
+ {
+ int hb = (lo >> 31) & 0x1;
+ if (hb && !(lo & 0x7fffffff))
+ java_lex_error ("Numeric overflow for `int' literal", 0);
+ }
+ }
+}
+#endif /* JC1_LITE */
static void
java_unicode_2_utf8 (unicode)
Index: parse.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.h,v
retrieving revision 1.62
diff -u -r1.62 parse.h
--- parse.h 2000/11/22 05:25:15 1.62
+++ parse.h 2000/12/14 16:13:19
@@ -760,8 +760,6 @@
/* Indicates that a context already contains saved data and that the
next save operation will require a new context to be created. */
unsigned saved_data:1;
- /* Integral literal overflow */
- unsigned minus_seen:1;
/* Report error when true */
unsigned java_error_flag:1;
/* @deprecated tag seen */
@@ -922,6 +920,11 @@
#define SET_CPC_INSTANCE_INITIALIZER_STMT(C,S) \
if (CPC_INSTANCE_INITIALIZER_LIST(C)) \
TREE_PURPOSE (CPC_INSTANCE_INITIALIZER_LIST (C)) = (S);
+
+/* This is used by the lexer to communicate with the parser. It is
+ set on an integer constant if the radix is 10, so that the parser
+ can correctly diagnose a numeric overflow. */
+#define JAVA_RADIX10_FLAG(NODE) TREE_LANG_FLAG_0(NODE)
#ifndef JC1_LITE
void java_complete_class PARAMS ((void));
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.y,v
retrieving revision 1.234
diff -u -r1.234 parse.y
--- parse.y 2000/12/13 22:36:24 1.234
+++ parse.y 2000/12/14 16:13:30
@@ -556,7 +556,7 @@
switch_statement synchronized_statement throw_statement
try_statement switch_expression switch_block
catches catch_clause catch_clause_parameter finally
- anonymous_class_creation
+ anonymous_class_creation trap_overflow_corner_case
%type <node> return_statement break_statement continue_statement
%type <operator> ASSIGN_TK MULT_ASSIGN_TK DIV_ASSIGN_TK
@@ -2275,16 +2275,24 @@
{ $$ = build_incdec ($2.token, $2.location, $1, 1); }
;
-unary_expression:
+trap_overflow_corner_case:
pre_increment_expression
| pre_decrement_expression
| PLUS_TK unary_expression
{$$ = build_unaryop ($1.token, $1.location, $2); }
-| MINUS_TK unary_expression
- {$$ = build_unaryop ($1.token, $1.location, $2); }
| unary_expression_not_plus_minus
| PLUS_TK error
{yyerror ("Missing term"); RECOVER}
+;
+
+unary_expression:
+ trap_overflow_corner_case
+ {
+ error_if_numeric_overflow ($1);
+ $$ = $1;
+ }
+| MINUS_TK trap_overflow_corner_case
+ {$$ = build_unaryop ($1.token, $1.location, $2); }
| MINUS_TK error
{yyerror ("Missing term"); RECOVER}
;