X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libcpp%2Fexpr.c;h=96dd2fde24ca93e538b3a40083c4fa59dc70fbce;hb=93a95718dfb728a42772bc2481fb570ae999ff92;hp=73356a966a077fd64a72889abf7af2bd3932a06f;hpb=720aca9227005bb5d8eadd8bd95d630a28568180;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libcpp/expr.c b/libcpp/expr.c index 73356a966a0..96dd2fde24c 100644 --- a/libcpp/expr.c +++ b/libcpp/expr.c @@ -1,11 +1,11 @@ /* Parse C expressions for cpplib. Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001, - 2002, 2004 Free Software Foundation. + 2002, 2004, 2008, 2009 Free Software Foundation. Contributed by Per Bothner, 1994. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any +Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,9 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +along with this program; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -32,6 +31,7 @@ struct op { const cpp_token *token; /* The token forming op (for diagnostics). */ cpp_num value; /* The value logically "right" of op. */ + source_location loc; /* The location of this value. */ enum cpp_ttype op; }; @@ -52,7 +52,8 @@ static cpp_num num_inequality_op (cpp_reader *, cpp_num, cpp_num, static cpp_num num_equality_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype); static cpp_num num_mul (cpp_reader *, cpp_num, cpp_num); -static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype); +static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype, + source_location); static cpp_num num_lshift (cpp_num, size_t, size_t); static cpp_num num_rshift (cpp_num, size_t, size_t); @@ -82,25 +83,106 @@ static void check_promotion (cpp_reader *, const struct op *); static unsigned int interpret_float_suffix (const uchar *s, size_t len) { - size_t f = 0, l = 0, i = 0; + size_t flags; + size_t f, d, l, w, q, i; + flags = 0; + f = d = l = w = q = i = 0; + + /* Process decimal float suffixes, which are two letters starting + with d or D. Order and case are significant. */ + if (len == 2 && (*s == 'd' || *s == 'D')) + { + bool uppercase = (*s == 'D'); + switch (s[1]) + { + case 'f': return (!uppercase ? (CPP_N_DFLOAT | CPP_N_SMALL): 0); break; + case 'F': return (uppercase ? (CPP_N_DFLOAT | CPP_N_SMALL) : 0); break; + case 'd': return (!uppercase ? (CPP_N_DFLOAT | CPP_N_MEDIUM): 0); break; + case 'D': return (uppercase ? (CPP_N_DFLOAT | CPP_N_MEDIUM) : 0); break; + case 'l': return (!uppercase ? (CPP_N_DFLOAT | CPP_N_LARGE) : 0); break; + case 'L': return (uppercase ? (CPP_N_DFLOAT | CPP_N_LARGE) : 0); break; + default: + /* Additional two-character suffixes beginning with D are not + for decimal float constants. */ + break; + } + } + + /* Recognize a fixed-point suffix. */ + switch (s[len-1]) + { + case 'k': case 'K': flags = CPP_N_ACCUM; break; + case 'r': case 'R': flags = CPP_N_FRACT; break; + default: break; + } + + /* Continue processing a fixed-point suffix. The suffix is case + insensitive except for ll or LL. Order is significant. */ + if (flags) + { + if (len == 1) + return flags; + len--; + + if (*s == 'u' || *s == 'U') + { + flags |= CPP_N_UNSIGNED; + if (len == 1) + return flags; + len--; + s++; + } + + switch (*s) + { + case 'h': case 'H': + if (len == 1) + return flags |= CPP_N_SMALL; + break; + case 'l': + if (len == 1) + return flags |= CPP_N_MEDIUM; + if (len == 2 && s[1] == 'l') + return flags |= CPP_N_LARGE; + break; + case 'L': + if (len == 1) + return flags |= CPP_N_MEDIUM; + if (len == 2 && s[1] == 'L') + return flags |= CPP_N_LARGE; + break; + default: + break; + } + /* Anything left at this point is invalid. */ + return 0; + } + + /* In any remaining valid suffix, the case and order don't matter. */ while (len--) switch (s[len]) { case 'f': case 'F': f++; break; + case 'd': case 'D': d++; break; case 'l': case 'L': l++; break; + case 'w': case 'W': w++; break; + case 'q': case 'Q': q++; break; case 'i': case 'I': case 'j': case 'J': i++; break; default: return 0; } - if (f + l > 1 || i > 1) + if (f + d + l + w + q > 1 || i > 1) return 0; return ((i ? CPP_N_IMAGINARY : 0) | (f ? CPP_N_SMALL : - l ? CPP_N_LARGE : CPP_N_MEDIUM)); + d ? CPP_N_MEDIUM : + l ? CPP_N_LARGE : + w ? CPP_N_MD_W : + q ? CPP_N_MD_Q : CPP_N_DEFAULT)); } /* Subroutine of cpp_classify_number. S points to an integer suffix @@ -171,6 +253,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token) radix = 16; str++; } + else if ((*str == 'b' || *str == 'B') && (str[1] == '0' || str[1] == '1')) + { + radix = 2; + str++; + } } /* Now scan for a well-formed integer or float. */ @@ -205,14 +292,46 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token) } } + /* The suffix may be for decimal fixed-point constants without exponent. */ + if (radix != 16 && float_flag == NOT_FLOAT) + { + result = interpret_float_suffix (str, limit - str); + if ((result & CPP_N_FRACT) || (result & CPP_N_ACCUM)) + { + result |= CPP_N_FLOATING; + /* We need to restore the radix to 10, if the radix is 8. */ + if (radix == 8) + radix = 10; + + if (CPP_PEDANTIC (pfile)) + cpp_error (pfile, CPP_DL_PEDWARN, + "fixed-point constants are a GCC extension"); + goto syntax_ok; + } + else + result = 0; + } + if (float_flag != NOT_FLOAT && radix == 8) radix = 10; if (max_digit >= radix) - SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit); + { + if (radix == 2) + SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit); + else + SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit); + } if (float_flag != NOT_FLOAT) { + if (radix == 2) + { + cpp_error (pfile, CPP_DL_ERROR, + "invalid prefix \"0b\" for floating constant"); + return CPP_N_INVALID; + } + if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99)) cpp_error (pfile, CPP_DL_PEDWARN, "use of C99 hexadecimal floating constant"); @@ -250,6 +369,30 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token) "traditional C rejects the \"%.*s\" suffix", (int) (limit - str), str); + /* A suffix for double is a GCC extension via decimal float support. + If the suffix also specifies an imaginary value we'll catch that + later. */ + if ((result == CPP_N_MEDIUM) && CPP_PEDANTIC (pfile)) + cpp_error (pfile, CPP_DL_PEDWARN, + "suffix for double constant is a GCC extension"); + + /* Radix must be 10 for decimal floats. */ + if ((result & CPP_N_DFLOAT) && radix != 10) + { + cpp_error (pfile, CPP_DL_ERROR, + "invalid suffix \"%.*s\" with hexadecimal floating constant", + (int) (limit - str), str); + return CPP_N_INVALID; + } + + if ((result & (CPP_N_FRACT | CPP_N_ACCUM)) && CPP_PEDANTIC (pfile)) + cpp_error (pfile, CPP_DL_PEDWARN, + "fixed-point constants are a GCC extension"); + + if ((result & CPP_N_DFLOAT) && CPP_PEDANTIC (pfile)) + cpp_error (pfile, CPP_DL_PEDWARN, + "decimal float constants are a GCC extension"); + result |= CPP_N_FLOATING; } else @@ -277,22 +420,30 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token) } if ((result & CPP_N_WIDTH) == CPP_N_LARGE - && ! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, warn_long_long)) - cpp_error (pfile, CPP_DL_PEDWARN, - "use of C99 long long integer constant"); + cpp_error (pfile, + CPP_OPTION (pfile, c99) ? CPP_DL_WARNING : CPP_DL_PEDWARN, + CPP_OPTION (pfile, cplusplus) + ? "use of C++0x long long integer constant" + : "use of C99 long long integer constant"); result |= CPP_N_INTEGER; } + syntax_ok: if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile)) cpp_error (pfile, CPP_DL_PEDWARN, "imaginary constants are a GCC extension"); + if (radix == 2 && CPP_PEDANTIC (pfile)) + cpp_error (pfile, CPP_DL_PEDWARN, + "binary constants are a GCC extension"); if (radix == 10) result |= CPP_N_DECIMAL; else if (radix == 16) result |= CPP_N_HEX; + else if (radix == 2) + result |= CPP_N_BINARY; else result |= CPP_N_OCTAL; @@ -343,6 +494,11 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token, base = 16; p += 2; } + else if ((type & CPP_N_RADIX) == CPP_N_BINARY) + { + base = 2; + p += 2; + } /* We can add a digit to numbers strictly less than this without needing the precision and slowness of double integers. */ @@ -383,8 +539,27 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token, && pfile->state.in_directive) && !num_positive (result, precision)) { + /* This is for constants within the range of uintmax_t but + not that of intmax_t. For such decimal constants, a + diagnostic is required for C99 as the selected type must + be signed and not having a type is a constraint violation + (DR#298, TC3), so this must be a pedwarn. For C90, + unsigned long is specified to be used for a constant that + does not fit in signed long; if uintmax_t has the same + range as unsigned long this means only a warning is + appropriate here. C90 permits the preprocessor to use a + wider range than unsigned long in the compiler, so if + uintmax_t is wider than unsigned long no diagnostic is + required for such constants in preprocessor #if + expressions and the compiler will pedwarn for such + constants outside the range of unsigned long that reach + the compiler so a diagnostic is not required there + either; thus, pedwarn for C99 but use a plain warning for + C90. */ if (base == 10) - cpp_error (pfile, CPP_DL_WARNING, + cpp_error (pfile, (CPP_OPTION (pfile, c99) + ? CPP_DL_PEDWARN + : CPP_DL_WARNING), "integer constant is so large that it is unsigned"); result.unsignedp = true; } @@ -398,12 +573,25 @@ static cpp_num append_digit (cpp_num num, int digit, int base, size_t precision) { cpp_num result; - unsigned int shift = 3 + (base == 16); + unsigned int shift; bool overflow; cpp_num_part add_high, add_low; - /* Multiply by 8 or 16. Catching this overflow here means we don't + /* Multiply by 2, 8 or 16. Catching this overflow here means we don't need to worry about add_high overflowing. */ + switch (base) + { + case 2: + shift = 1; + break; + + case 16: + shift = 4; + break; + + default: + shift = 3; + } overflow = !!(num.high >> (PART_PRECISION - shift)); result.high = num.high << shift; result.low = num.low << shift; @@ -421,7 +609,7 @@ append_digit (cpp_num num, int digit, int base, size_t precision) if (add_low + digit < add_low) add_high++; add_low += digit; - + if (result.low + add_low < result.low) add_high++; if (result.high + add_high < result.high) @@ -464,7 +652,7 @@ parse_defined (cpp_reader *pfile) if (token->type == CPP_NAME) { - node = token->val.node; + node = token->val.node.node; if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN) { cpp_error (pfile, CPP_DL_ERROR, "missing ')' after \"defined\""); @@ -495,6 +683,20 @@ parse_defined (cpp_reader *pfile) "this use of \"defined\" may not be portable"); _cpp_mark_macro_used (node); + if (!(node->flags & NODE_USED)) + { + node->flags |= NODE_USED; + if (node->type == NT_MACRO) + { + if (pfile->cb.used_define) + pfile->cb.used_define (pfile, pfile->directive_line, node); + } + else + { + if (pfile->cb.used_undef) + pfile->cb.used_undef (pfile, pfile->directive_line, node); + } + } /* A possible controlling macro of the form #if !defined (). _cpp_parse_expr checks there was no other junk on the line. */ @@ -549,6 +751,8 @@ eval_token (cpp_reader *pfile, const cpp_token *token) case CPP_WCHAR: case CPP_CHAR: + case CPP_CHAR16: + case CPP_CHAR32: { cppchar_t cc = cpp_interpret_charconst (pfile, token, &temp, &unsignedp); @@ -568,14 +772,14 @@ eval_token (cpp_reader *pfile, const cpp_token *token) break; case CPP_NAME: - if (token->val.node == pfile->spec_nodes.n_defined) + if (token->val.node.node == pfile->spec_nodes.n_defined) return parse_defined (pfile); else if (CPP_OPTION (pfile, cplusplus) - && (token->val.node == pfile->spec_nodes.n_true - || token->val.node == pfile->spec_nodes.n_false)) + && (token->val.node.node == pfile->spec_nodes.n_true + || token->val.node.node == pfile->spec_nodes.n_false)) { result.high = 0; - result.low = (token->val.node == pfile->spec_nodes.n_true); + result.low = (token->val.node.node == pfile->spec_nodes.n_true); } else { @@ -583,14 +787,29 @@ eval_token (cpp_reader *pfile, const cpp_token *token) result.low = 0; if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval) cpp_error (pfile, CPP_DL_WARNING, "\"%s\" is not defined", - NODE_NAME (token->val.node)); + NODE_NAME (token->val.node.node)); } break; - default: /* CPP_HASH */ + case CPP_HASH: + if (!pfile->state.skipping) + { + /* A pedantic warning takes precedence over a deprecated + warning here. */ + if (CPP_PEDANTIC (pfile)) + cpp_error (pfile, CPP_DL_PEDWARN, + "assertions are a GCC extension"); + else if (CPP_OPTION (pfile, warn_deprecated)) + cpp_error (pfile, CPP_DL_WARNING, + "assertions are a deprecated extension"); + } _cpp_test_assertion (pfile, &temp); result.high = 0; result.low = temp; + break; + + default: + abort (); } result.unsignedp = !!unsignedp; @@ -648,15 +867,14 @@ static const struct cpp_operator /* RSHIFT */ {13, LEFT_ASSOC}, /* LSHIFT */ {13, LEFT_ASSOC}, - /* MIN */ {10, LEFT_ASSOC | CHECK_PROMOTION}, - /* MAX */ {10, LEFT_ASSOC | CHECK_PROMOTION}, - /* COMPL */ {16, NO_L_OPERAND}, /* AND_AND */ {6, LEFT_ASSOC}, /* OR_OR */ {5, LEFT_ASSOC}, - /* QUERY */ {3, 0}, + /* Note that QUERY, COLON, and COMMA must have the same precedence. + However, there are some special cases for these in reduce(). */ + /* QUERY */ {4, 0}, /* COLON */ {4, LEFT_ASSOC | CHECK_PROMOTION}, - /* COMMA */ {2, LEFT_ASSOC}, + /* COMMA */ {4, LEFT_ASSOC}, /* OPEN_PAREN */ {1, NO_L_OPERAND}, /* CLOSE_PAREN */ {0, 0}, /* EOF */ {0, 0}, @@ -680,7 +898,7 @@ static const struct cpp_operator stored in the 'value' field of the stack element of the operator that precedes it. */ bool -_cpp_parse_expr (cpp_reader *pfile) +_cpp_parse_expr (cpp_reader *pfile, bool is_if) { struct op *top = pfile->op_stack; unsigned int lex_count; @@ -703,6 +921,7 @@ _cpp_parse_expr (cpp_reader *pfile) lex_count++; op.token = cpp_get_token (pfile); op.op = op.token->type; + op.loc = op.token->src_loc; switch (op.op) { @@ -710,6 +929,8 @@ _cpp_parse_expr (cpp_reader *pfile) case CPP_NUMBER: case CPP_CHAR: case CPP_WCHAR: + case CPP_CHAR16: + case CPP_CHAR32: case CPP_NAME: case CPP_HASH: if (!want_value) @@ -753,7 +974,7 @@ _cpp_parse_expr (cpp_reader *pfile) SYNTAX_ERROR ("missing expression between '(' and ')'"); if (op.op == CPP_EOF && top->op == CPP_EOF) - SYNTAX_ERROR ("#if with no expression"); + SYNTAX_ERROR2 ("%s with no expression", is_if ? "#if" : "#elif"); if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN) SYNTAX_ERROR2 ("operator '%s' has no right operand", @@ -804,6 +1025,7 @@ _cpp_parse_expr (cpp_reader *pfile) top->op = op.op; top->token = op.token; + top->loc = op.token->src_loc; } /* The controlling macro expression is only valid if we called lex 3 @@ -814,7 +1036,8 @@ _cpp_parse_expr (cpp_reader *pfile) if (top != pfile->op_stack) { - cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in #if"); + cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in %s", + is_if ? "#if" : "#elif"); syntax_error: return false; /* Return false on syntax error. */ } @@ -856,17 +1079,17 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op) case CPP_NOT: case CPP_COMPL: top[-1].value = num_unary_op (pfile, top->value, top->op); + top[-1].loc = top->loc; break; case CPP_PLUS: case CPP_MINUS: case CPP_RSHIFT: case CPP_LSHIFT: - case CPP_MIN: - case CPP_MAX: case CPP_COMMA: top[-1].value = num_binary_op (pfile, top[-1].value, top->value, top->op); + top[-1].loc = top->loc; break; case CPP_GREATER: @@ -875,12 +1098,14 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op) case CPP_LESS_EQ: top[-1].value = num_inequality_op (pfile, top[-1].value, top->value, top->op); + top[-1].loc = top->loc; break; case CPP_EQ_EQ: case CPP_NOT_EQ: top[-1].value = num_equality_op (pfile, top[-1].value, top->value, top->op); + top[-1].loc = top->loc; break; case CPP_AND: @@ -888,16 +1113,19 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op) case CPP_XOR: top[-1].value = num_bitwise_op (pfile, top[-1].value, top->value, top->op); + top[-1].loc = top->loc; break; case CPP_MULT: top[-1].value = num_mul (pfile, top[-1].value, top->value); + top[-1].loc = top->loc; break; case CPP_DIV: case CPP_MOD: top[-1].value = num_div_op (pfile, top[-1].value, - top->value, top->op); + top->value, top->op, top->loc); + top[-1].loc = top->loc; break; case CPP_OR_OR: @@ -909,6 +1137,7 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op) top->value.high = 0; top->value.unsignedp = false; top->value.overflow = false; + top->loc = top[1].loc; continue; case CPP_AND_AND: @@ -920,16 +1149,20 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op) top->value.high = 0; top->value.unsignedp = false; top->value.overflow = false; + top->loc = top[1].loc; continue; case CPP_OPEN_PAREN: if (op != CPP_CLOSE_PAREN) { - cpp_error (pfile, CPP_DL_ERROR, "missing ')' in expression"); + cpp_error_with_line (pfile, CPP_DL_ERROR, + top->token->src_loc, + 0, "missing ')' in expression"); return 0; } top--; top->value = top[1].value; + top->loc = top[1].loc; return top; case CPP_COLON: @@ -938,14 +1171,21 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op) { pfile->state.skip_eval--; top->value = top[1].value; + top->loc = top[1].loc; } else - top->value = top[2].value; + { + top->value = top[2].value; + top->loc = top[2].loc; + } top->value.unsignedp = (top[1].value.unsignedp || top[2].value.unsignedp); continue; case CPP_QUERY: + /* COMMA and COLON should not reduce a QUERY operator. */ + if (op == CPP_COMMA || op == CPP_COLON) + return top; cpp_error (pfile, CPP_DL_ERROR, "'?' without following ':'"); return 0; @@ -992,12 +1232,12 @@ check_promotion (cpp_reader *pfile, const struct op *op) if (op->value.unsignedp) { if (!num_positive (op[-1].value, CPP_OPTION (pfile, precision))) - cpp_error (pfile, CPP_DL_WARNING, - "the left operand of \"%s\" changes sign when promoted", - cpp_token_as_text (pfile, op->token)); + cpp_error_with_line (pfile, CPP_DL_WARNING, op[-1].loc, 0, + "the left operand of \"%s\" changes sign when promoted", + cpp_token_as_text (pfile, op->token)); } else if (!num_positive (op->value, CPP_OPTION (pfile, precision))) - cpp_error (pfile, CPP_DL_WARNING, + cpp_error_with_line (pfile, CPP_DL_WARNING, op->loc, 0, "the right operand of \"%s\" changes sign when promoted", cpp_token_as_text (pfile, op->token)); } @@ -1289,7 +1529,6 @@ num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op) { cpp_num result; size_t precision = CPP_OPTION (pfile, precision); - bool gte; size_t n; switch (op) @@ -1316,21 +1555,6 @@ num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op) lhs = num_rshift (lhs, precision, n); break; - /* Min / Max. */ - case CPP_MIN: - case CPP_MAX: - { - bool unsignedp = lhs.unsignedp || rhs.unsignedp; - - gte = num_greater_eq (lhs, rhs, precision); - if (op == CPP_MIN) - gte = !gte; - if (!gte) - lhs = rhs; - lhs.unsignedp = unsignedp; - } - break; - /* Arithmetic. */ case CPP_MINUS: rhs = num_negate (rhs, precision); @@ -1445,10 +1669,13 @@ num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs) return result; } -/* Divide two preprocessing numbers, returning the answer or the - remainder depending upon OP. */ +/* Divide two preprocessing numbers, LHS and RHS, returning the answer + or the remainder depending upon OP. LOCATION is the source location + of this operator (for diagnostics). */ + static cpp_num -num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op) +num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op, + source_location location) { cpp_num result, sub; cpp_num_part mask; @@ -1488,7 +1715,8 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op) else { if (!pfile->state.skip_eval) - cpp_error (pfile, CPP_DL_ERROR, "division by zero in #if"); + cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0, + "division by zero in #if"); return lhs; } @@ -1528,7 +1756,8 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op) { if (negate) result = num_negate (result, precision); - result.overflow = num_positive (result, precision) ^ !negate; + result.overflow = (num_positive (result, precision) ^ !negate + && !num_zerop (result)); } return result;