cppexp.c (cpp_num): Move to cpplib.h.
2002-05-29 Neil Booth <neil@daikokuya.demon.co.uk> Zack Weinberg <zack@codesourcery.com> * cppexp.c (cpp_num): Move to cpplib.h. (CPP_ERROR): Remove. (interpret_float_suffix, interpret_int_suffix): New. (struct suffix, vsuf_1, vsuf_2, vsuf_3): Remove. (cpp_classify_number, cpp_interpret_integer): New. (interpret_number): Remove. (eval_token): Update to use new routines. * cpphash.h (cpp_num_part): Move to cpplib.h. * cppinit.c (cpp_post_options): Set warn_long_long. * cpplib.h (struct cpp_options): Add warn_long_long. (cpp_num, cpp_num_part, CPP_N_CATEGORY, CPP_N_INVALID, CPP_N_INTEGER, CPP_N_FLOATING, CPP_N_WIDTH, CPP_N_SMALL, CPP_N_MEDIUM, CPP_N_LARGE, CPP_N_RADIX, CPP_N_DEC, CPP_N_HEX, CPP_N_OCTAL, CPP_N_UNSIGNED, CPP_N_IMAGINARY, cpp_classify_number, cpp_interpret_integer): New. testsuite: * gcc.dg/cpp/c++98-pedantic.c, gcc.dg/cpp/c89-pedantic.c, gcc.dg/cpp/c94-pedantic.c, gcc.dg/cpp/gnuc89-pedantic.c, gcc.dg/cpp/if-1.c: Update for modified diagnostics. Co-Authored-By: Zack Weinberg <zack@codesourcery.com> From-SVN: r54007
This commit is contained in:
parent
61a8515c94
commit
cd7ab83f2d
@ -1,3 +1,22 @@
|
||||
2002-05-29 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
Zack Weinberg <zack@codesourcery.com>
|
||||
|
||||
* cppexp.c (cpp_num): Move to cpplib.h.
|
||||
(CPP_ERROR): Remove.
|
||||
(interpret_float_suffix, interpret_int_suffix): New.
|
||||
(struct suffix, vsuf_1, vsuf_2, vsuf_3): Remove.
|
||||
(cpp_classify_number, cpp_interpret_integer): New.
|
||||
(interpret_number): Remove.
|
||||
(eval_token): Update to use new routines.
|
||||
* cpphash.h (cpp_num_part): Move to cpplib.h.
|
||||
* cppinit.c (cpp_post_options): Set warn_long_long.
|
||||
* cpplib.h (struct cpp_options): Add warn_long_long.
|
||||
(cpp_num, cpp_num_part, CPP_N_CATEGORY, CPP_N_INVALID,
|
||||
CPP_N_INTEGER, CPP_N_FLOATING, CPP_N_WIDTH, CPP_N_SMALL,
|
||||
CPP_N_MEDIUM, CPP_N_LARGE, CPP_N_RADIX, CPP_N_DEC, CPP_N_HEX,
|
||||
CPP_N_OCTAL, CPP_N_UNSIGNED, CPP_N_IMAGINARY, cpp_classify_number,
|
||||
cpp_interpret_integer): New.
|
||||
|
||||
2002-05-29 Joel Sherrill <joel@OARcorp.com>
|
||||
|
||||
* config/rs6000/rs6000.h (ASM_CPU_SPEC): Use -m403 and -m405.
|
||||
|
513
gcc/cppexp.c
513
gcc/cppexp.c
@ -23,23 +23,11 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "cpplib.h"
|
||||
#include "cpphash.h"
|
||||
|
||||
typedef struct cpp_num cpp_num;
|
||||
|
||||
#define PART_PRECISION (sizeof (cpp_num_part) * CHAR_BIT)
|
||||
#define HALF_MASK (~(cpp_num_part) 0 >> (PART_PRECISION / 2))
|
||||
#define LOW_PART(num_part) (num_part & HALF_MASK)
|
||||
#define HIGH_PART(num_part) (num_part >> (PART_PRECISION / 2))
|
||||
|
||||
/* A preprocessing number. Code assumes that any unused high bits of
|
||||
the double integer are set to zero. */
|
||||
struct cpp_num
|
||||
{
|
||||
cpp_num_part high;
|
||||
cpp_num_part low;
|
||||
bool unsignedp; /* True if value should be treated as unsigned. */
|
||||
bool overflow; /* True if the most recent calculation overflowed. */
|
||||
};
|
||||
|
||||
struct op
|
||||
{
|
||||
cpp_num value; /* The value logically "right" of op. */
|
||||
@ -72,15 +60,13 @@ static cpp_num num_lshift PARAMS ((cpp_num, size_t, size_t));
|
||||
static cpp_num num_rshift PARAMS ((cpp_num, size_t, size_t));
|
||||
|
||||
static cpp_num append_digit PARAMS ((cpp_num, int, int, size_t));
|
||||
static cpp_num interpret_number PARAMS ((cpp_reader *, const cpp_token *));
|
||||
static cpp_num parse_defined PARAMS ((cpp_reader *));
|
||||
static cpp_num eval_token PARAMS ((cpp_reader *, const cpp_token *));
|
||||
static struct op *reduce PARAMS ((cpp_reader *, struct op *, enum cpp_ttype));
|
||||
static unsigned int interpret_float_suffix PARAMS ((const uchar *, size_t));
|
||||
static unsigned int interpret_int_suffix PARAMS ((const uchar *, size_t));
|
||||
|
||||
/* Token type abuse. There is no "error" token, but we can't get
|
||||
comments in #if, so we can abuse that token type. Similarly,
|
||||
create unary plus and minus operators. */
|
||||
#define CPP_ERROR CPP_COMMENT
|
||||
/* Token type abuse to create unary plus and minus operators. */
|
||||
#define CPP_UPLUS (CPP_LAST_CPP_OP + 1)
|
||||
#define CPP_UMINUS (CPP_LAST_CPP_OP + 2)
|
||||
|
||||
@ -91,28 +77,317 @@ static struct op *reduce PARAMS ((cpp_reader *, struct op *, enum cpp_ttype));
|
||||
#define SYNTAX_ERROR2(msgid, arg) \
|
||||
do { cpp_error (pfile, DL_ERROR, msgid, arg); goto syntax_error; } while(0)
|
||||
|
||||
struct suffix
|
||||
/* Subroutine of cpp_classify_number. S points to a float suffix of
|
||||
length LEN, possibly zero. Returns 0 for an invalid suffix, or a
|
||||
flag vector describing the suffix. */
|
||||
static unsigned int
|
||||
interpret_float_suffix (s, len)
|
||||
const uchar *s;
|
||||
size_t len;
|
||||
{
|
||||
const unsigned char s[4];
|
||||
const unsigned char u;
|
||||
const unsigned char l;
|
||||
};
|
||||
size_t f = 0, l = 0, i = 0;
|
||||
|
||||
static const struct suffix vsuf_1[] = {
|
||||
{ "u", 1, 0 }, { "U", 1, 0 },
|
||||
{ "l", 0, 1 }, { "L", 0, 1 }
|
||||
};
|
||||
while (len--)
|
||||
switch (s[len])
|
||||
{
|
||||
case 'f': case 'F': f++; break;
|
||||
case 'l': case 'L': l++; break;
|
||||
case 'i': case 'I':
|
||||
case 'j': case 'J': i++; break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct suffix vsuf_2[] = {
|
||||
{ "ul", 1, 1 }, { "UL", 1, 1 }, { "uL", 1, 1 }, { "Ul", 1, 1 },
|
||||
{ "lu", 1, 1 }, { "LU", 1, 1 }, { "Lu", 1, 1 }, { "lU", 1, 1 },
|
||||
{ "ll", 0, 2 }, { "LL", 0, 2 }
|
||||
};
|
||||
if (f + l > 1 || i > 1)
|
||||
return 0;
|
||||
|
||||
static const struct suffix vsuf_3[] = {
|
||||
{ "ull", 1, 2 }, { "ULL", 1, 2 }, { "uLL", 1, 2 }, { "Ull", 1, 2 },
|
||||
{ "llu", 1, 2 }, { "LLU", 1, 2 }, { "LLu", 1, 2 }, { "llU", 1, 2 }
|
||||
};
|
||||
return ((i ? CPP_N_IMAGINARY : 0)
|
||||
| (f ? CPP_N_SMALL :
|
||||
l ? CPP_N_LARGE : CPP_N_MEDIUM));
|
||||
}
|
||||
|
||||
/* Subroutine of cpp_classify_number. S points to an integer suffix
|
||||
of length LEN, possibly zero. Returns 0 for an invalid suffix, or a
|
||||
flag vector describing the suffix. */
|
||||
static unsigned int
|
||||
interpret_int_suffix (s, len)
|
||||
const uchar *s;
|
||||
size_t len;
|
||||
{
|
||||
size_t u, l, i;
|
||||
|
||||
u = l = i = 0;
|
||||
|
||||
while (len--)
|
||||
switch (s[len])
|
||||
{
|
||||
case 'u': case 'U': u++; break;
|
||||
case 'i': case 'I':
|
||||
case 'j': case 'J': i++; break;
|
||||
case 'l': case 'L': l++;
|
||||
/* If there are two Ls, they must be adjacent and the same case. */
|
||||
if (l == 2 && s[len] != s[len + 1])
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (l > 2 || u > 1 || i > 1)
|
||||
return 0;
|
||||
|
||||
return ((i ? CPP_N_IMAGINARY : 0)
|
||||
| (u ? CPP_N_UNSIGNED : 0)
|
||||
| ((l == 0) ? CPP_N_SMALL
|
||||
: (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE));
|
||||
}
|
||||
|
||||
/* Categorize numeric constants according to their field (integer,
|
||||
floating point, or invalid), radix (decimal, octal, hexadecimal),
|
||||
and type suffixes. */
|
||||
unsigned int
|
||||
cpp_classify_number (pfile, token)
|
||||
cpp_reader *pfile;
|
||||
const cpp_token *token;
|
||||
{
|
||||
const uchar *str = token->val.str.text;
|
||||
const uchar *limit;
|
||||
unsigned int max_digit, result, radix;
|
||||
enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
|
||||
|
||||
/* If the lexer has done its job, length one can only be a single
|
||||
digit. Fast-path this very common case. */
|
||||
if (token->val.str.len == 1)
|
||||
return CPP_N_INTEGER | CPP_N_SMALL | CPP_N_DECIMAL;
|
||||
|
||||
limit = str + token->val.str.len;
|
||||
float_flag = NOT_FLOAT;
|
||||
max_digit = 0;
|
||||
radix = 10;
|
||||
|
||||
/* First, interpret the radix. */
|
||||
if (*str == '0')
|
||||
{
|
||||
radix = 8;
|
||||
str++;
|
||||
|
||||
/* Require at least one hex digit to classify it as hex. */
|
||||
if ((*str == 'x' || *str == 'X') && ISXDIGIT (str[1]))
|
||||
{
|
||||
radix = 16;
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now scan for a well-formed integer or float. */
|
||||
for (;;)
|
||||
{
|
||||
unsigned int c = *str++;
|
||||
|
||||
if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
|
||||
{
|
||||
c = hex_value (c);
|
||||
if (c > max_digit)
|
||||
max_digit = c;
|
||||
}
|
||||
else if (c == '.')
|
||||
{
|
||||
if (float_flag == NOT_FLOAT)
|
||||
float_flag = AFTER_POINT;
|
||||
else
|
||||
SYNTAX_ERROR ("too many decimal points in number");
|
||||
}
|
||||
else if ((radix <= 10 && (c == 'e' || c == 'E'))
|
||||
|| (radix == 16 && (c == 'p' || c == 'P')))
|
||||
{
|
||||
float_flag = AFTER_EXPON;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start of suffix. */
|
||||
str--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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 (float_flag != NOT_FLOAT)
|
||||
{
|
||||
if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
|
||||
cpp_error (pfile, DL_PEDWARN,
|
||||
"use of C99 hexadecimal floating constant");
|
||||
|
||||
if (float_flag == AFTER_EXPON)
|
||||
{
|
||||
if (*str == '+' || *str == '-')
|
||||
str++;
|
||||
|
||||
/* Exponent is decimal, even if string is a hex float. */
|
||||
if (!ISDIGIT (*str))
|
||||
SYNTAX_ERROR ("exponent has no digits");
|
||||
|
||||
do
|
||||
str++;
|
||||
while (ISDIGIT (*str));
|
||||
}
|
||||
else if (radix == 16)
|
||||
SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
|
||||
|
||||
result = interpret_float_suffix (str, limit - str);
|
||||
if (result == 0)
|
||||
{
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"invalid suffix \"%.*s\" on floating constant",
|
||||
limit - str, str);
|
||||
return CPP_N_INVALID;
|
||||
}
|
||||
|
||||
/* Traditional C didn't accept any floating suffixes. */
|
||||
if (limit != str
|
||||
&& CPP_WTRADITIONAL (pfile)
|
||||
&& ! cpp_sys_macro_p (pfile))
|
||||
cpp_error (pfile, DL_WARNING,
|
||||
"traditional C rejects the \"%.*s\" suffix",
|
||||
limit - str, str);
|
||||
|
||||
result |= CPP_N_FLOATING;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = interpret_int_suffix (str, limit - str);
|
||||
if (result == 0)
|
||||
{
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"invalid suffix \"%.*s\" on integer constant",
|
||||
limit - str, str);
|
||||
return CPP_N_INVALID;
|
||||
}
|
||||
|
||||
/* Traditional C only accepted the 'L' suffix. */
|
||||
if (result != CPP_N_SMALL && result != CPP_N_MEDIUM
|
||||
&& CPP_WTRADITIONAL (pfile)
|
||||
&& ! cpp_sys_macro_p (pfile))
|
||||
cpp_error (pfile, DL_WARNING,
|
||||
"traditional C rejects the \"%.*s\" suffix",
|
||||
limit - str, str);
|
||||
|
||||
if ((result & CPP_N_WIDTH) == CPP_N_LARGE
|
||||
&& ! CPP_OPTION (pfile, c99)
|
||||
&& CPP_OPTION (pfile, warn_long_long))
|
||||
cpp_error (pfile, DL_PEDWARN, "use of C99 long long integer constant");
|
||||
|
||||
result |= CPP_N_INTEGER;
|
||||
}
|
||||
|
||||
if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
|
||||
cpp_error (pfile, DL_PEDWARN, "imaginary constants are a GCC extension");
|
||||
|
||||
if (radix == 10)
|
||||
result |= CPP_N_DECIMAL;
|
||||
else if (radix == 16)
|
||||
result |= CPP_N_HEX;
|
||||
else
|
||||
result |= CPP_N_OCTAL;
|
||||
|
||||
return result;
|
||||
|
||||
syntax_error:
|
||||
return CPP_N_INVALID;
|
||||
}
|
||||
|
||||
/* cpp_interpret_integer converts an integer constant into a cpp_num,
|
||||
of precision options->precision.
|
||||
|
||||
We do not provide any interface for decimal->float conversion,
|
||||
because the preprocessor doesn't need it and the floating point
|
||||
handling in GCC proper is too ugly to speak of. */
|
||||
cpp_num
|
||||
cpp_interpret_integer (pfile, token, type)
|
||||
cpp_reader *pfile;
|
||||
const cpp_token *token;
|
||||
unsigned int type;
|
||||
{
|
||||
const uchar *p, *end;
|
||||
cpp_num result;
|
||||
|
||||
result.low = 0;
|
||||
result.high = 0;
|
||||
result.unsignedp = type & CPP_N_UNSIGNED;
|
||||
result.overflow = 0;
|
||||
|
||||
p = token->val.str.text;
|
||||
end = p + token->val.str.len;
|
||||
|
||||
/* Common case of a single digit. */
|
||||
if (token->val.str.len == 1)
|
||||
result.low = p[0] - '0';
|
||||
else
|
||||
{
|
||||
cpp_num_part max;
|
||||
size_t precision = CPP_OPTION (pfile, precision);
|
||||
unsigned int base = 10, c = 0;
|
||||
bool overflow = false;
|
||||
|
||||
if ((type & CPP_N_RADIX) == CPP_N_OCTAL)
|
||||
{
|
||||
base = 8;
|
||||
p++;
|
||||
}
|
||||
else if ((type & CPP_N_RADIX) == CPP_N_HEX)
|
||||
{
|
||||
base = 16;
|
||||
p += 2;
|
||||
}
|
||||
|
||||
/* We can add a digit to numbers strictly less than this without
|
||||
needing the precision and slowness of double integers. */
|
||||
max = ~(cpp_num_part) 0;
|
||||
if (precision < PART_PRECISION)
|
||||
max >>= PART_PRECISION - precision;
|
||||
max = (max - base + 1) / base + 1;
|
||||
|
||||
for (; p < end; p++)
|
||||
{
|
||||
c = *p;
|
||||
|
||||
if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
|
||||
c = hex_value (c);
|
||||
else
|
||||
break;
|
||||
|
||||
/* Strict inequality for when max is set to zero. */
|
||||
if (result.low < max)
|
||||
result.low = result.low * base + c;
|
||||
else
|
||||
{
|
||||
result = append_digit (result, c, base, precision);
|
||||
overflow |= result.overflow;
|
||||
max = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (overflow)
|
||||
cpp_error (pfile, DL_PEDWARN,
|
||||
"integer constant is too large for its type");
|
||||
else if (!result.unsignedp && !num_positive (result, precision))
|
||||
{
|
||||
/* If too big to be signed, consider it unsigned. Only warn
|
||||
for decimal numbers. */
|
||||
if (base == 10)
|
||||
cpp_error (pfile, DL_WARNING,
|
||||
"integer constant is so large that it is unsigned");
|
||||
result.unsignedp = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Append DIGIT to NUM, a number of PRECISION bits being read in base
|
||||
BASE. */
|
||||
@ -167,149 +442,6 @@ append_digit (num, digit, base, precision)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Parse and convert what is presumably an integer in TOK. Accepts
|
||||
decimal, hex, or octal with or without size suffixes. Returned op
|
||||
is CPP_ERROR on error, otherwise it is a CPP_NUMBER. */
|
||||
static cpp_num
|
||||
interpret_number (pfile, tok)
|
||||
cpp_reader *pfile;
|
||||
const cpp_token *tok;
|
||||
{
|
||||
cpp_num result;
|
||||
cpp_num_part max;
|
||||
const uchar *p = tok->val.str.text;
|
||||
const uchar *end;
|
||||
const struct suffix *sufftab;
|
||||
size_t precision;
|
||||
unsigned int i, nsuff, base, c;
|
||||
bool overflow, big_digit;
|
||||
|
||||
result.low = 0;
|
||||
result.high = 0;
|
||||
result.unsignedp = 0;
|
||||
result.overflow = 0;
|
||||
|
||||
/* Common case of a single digit. */
|
||||
end = p + tok->val.str.len;
|
||||
if (tok->val.str.len == 1 && (unsigned int) (p[0] - '0') <= 9)
|
||||
{
|
||||
result.low = p[0] - '0';
|
||||
return result;
|
||||
}
|
||||
|
||||
base = 10;
|
||||
if (p[0] == '0')
|
||||
{
|
||||
if (end - p >= 3 && (p[1] == 'x' || p[1] == 'X'))
|
||||
{
|
||||
p += 2;
|
||||
base = 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
p += 1;
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
|
||||
c = 0;
|
||||
overflow = big_digit = false;
|
||||
precision = CPP_OPTION (pfile, precision);
|
||||
|
||||
/* We can add a digit to numbers less than this without needing
|
||||
double integers. 9 is the maximum digit for octal and decimal;
|
||||
for hex it is annihilated by the division anyway. */
|
||||
max = ~(cpp_num_part) 0;
|
||||
if (precision < PART_PRECISION)
|
||||
max >>= PART_PRECISION - precision;
|
||||
max = (max - 9) / base + 1;
|
||||
|
||||
for(; p < end; p++)
|
||||
{
|
||||
c = *p;
|
||||
|
||||
if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
|
||||
c = hex_value (c);
|
||||
else
|
||||
break;
|
||||
|
||||
if (c >= base)
|
||||
big_digit = true;
|
||||
|
||||
/* Strict inequality for when max is set to zero. */
|
||||
if (result.low < max)
|
||||
result.low = result.low * base + c;
|
||||
else
|
||||
{
|
||||
result = append_digit (result, c, base, precision);
|
||||
overflow |= result.overflow;
|
||||
max = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (p < end)
|
||||
{
|
||||
/* Check for a floating point constant. Note that float constants
|
||||
with an exponent or suffix but no decimal point are technically
|
||||
invalid (C99 6.4.4.2) but accepted elsewhere. */
|
||||
if ((c == '.' || c == 'F' || c == 'f')
|
||||
|| (base == 10 && (c == 'E' || c == 'e')
|
||||
&& p+1 < end && (p[1] == '+' || p[1] == '-'))
|
||||
|| (base == 16 && (c == 'P' || c == 'p')
|
||||
&& p+1 < end && (p[1] == '+' || p[1] == '-')))
|
||||
SYNTAX_ERROR ("floating point numbers are not valid in #if");
|
||||
|
||||
/* Determine the suffix. l means long, and u means unsigned.
|
||||
See the suffix tables, above. */
|
||||
switch (end - p)
|
||||
{
|
||||
case 1: sufftab = vsuf_1; nsuff = ARRAY_SIZE (vsuf_1); break;
|
||||
case 2: sufftab = vsuf_2; nsuff = ARRAY_SIZE (vsuf_2); break;
|
||||
case 3: sufftab = vsuf_3; nsuff = ARRAY_SIZE (vsuf_3); break;
|
||||
default: goto invalid_suffix;
|
||||
}
|
||||
|
||||
for (i = 0; i < nsuff; i++)
|
||||
if (memcmp (p, sufftab[i].s, end - p) == 0)
|
||||
break;
|
||||
if (i == nsuff)
|
||||
goto invalid_suffix;
|
||||
result.unsignedp = sufftab[i].u;
|
||||
|
||||
if (CPP_WTRADITIONAL (pfile)
|
||||
&& sufftab[i].u
|
||||
&& ! cpp_sys_macro_p (pfile))
|
||||
cpp_error (pfile, DL_WARNING, "traditional C rejects the `U' suffix");
|
||||
if (sufftab[i].l == 2 && CPP_OPTION (pfile, pedantic)
|
||||
&& ! CPP_OPTION (pfile, c99))
|
||||
cpp_error (pfile, DL_PEDWARN,
|
||||
"too many 'l' suffixes in integer constant");
|
||||
}
|
||||
|
||||
if (big_digit)
|
||||
cpp_error (pfile, DL_PEDWARN,
|
||||
"integer constant contains digits beyond the radix");
|
||||
|
||||
if (overflow)
|
||||
cpp_error (pfile, DL_PEDWARN, "integer constant too large for its type");
|
||||
/* If too big to be signed, consider it unsigned. */
|
||||
else if (!result.unsignedp && !num_positive (result, precision))
|
||||
{
|
||||
if (base == 10)
|
||||
cpp_error (pfile, DL_WARNING,
|
||||
"integer constant is so large that it is unsigned");
|
||||
result.unsignedp = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
invalid_suffix:
|
||||
cpp_error (pfile, DL_ERROR, "invalid suffix '%.*s' on integer constant",
|
||||
(int) (end - p), p);
|
||||
syntax_error:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Handle meeting "defined" in a preprocessor expression. */
|
||||
static cpp_num
|
||||
parse_defined (pfile)
|
||||
@ -379,7 +511,7 @@ parse_defined (pfile)
|
||||
|
||||
/* Convert a token into a CPP_NUMBER (an interpreted preprocessing
|
||||
number or character constant, or the result of the "defined" or "#"
|
||||
operators), or CPP_ERROR on error. */
|
||||
operators). */
|
||||
static cpp_num
|
||||
eval_token (pfile, token)
|
||||
cpp_reader *pfile;
|
||||
@ -392,7 +524,26 @@ eval_token (pfile, token)
|
||||
switch (token->type)
|
||||
{
|
||||
case CPP_NUMBER:
|
||||
return interpret_number (pfile, token);
|
||||
temp = cpp_classify_number (pfile, token);
|
||||
switch (temp & CPP_N_CATEGORY)
|
||||
{
|
||||
case CPP_N_FLOATING:
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"floating constant in preprocessor expression");
|
||||
break;
|
||||
case CPP_N_INTEGER:
|
||||
if (!(temp & CPP_N_IMAGINARY))
|
||||
return cpp_interpret_integer (pfile, token, temp);
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"imaginary number in preprocessor expression");
|
||||
break;
|
||||
|
||||
case CPP_N_INVALID:
|
||||
/* Error already issued. */
|
||||
break;
|
||||
}
|
||||
result.high = result.low = 0;
|
||||
break;
|
||||
|
||||
case CPP_WCHAR:
|
||||
case CPP_CHAR:
|
||||
@ -604,7 +755,7 @@ _cpp_parse_expr (pfile)
|
||||
|
||||
default:
|
||||
if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ)
|
||||
SYNTAX_ERROR2 ("token \"%s\" is not valid in #if expressions",
|
||||
SYNTAX_ERROR2 ("token \"%s\" is not valid in preprocessor expressions",
|
||||
cpp_token_as_text (pfile, token));
|
||||
break;
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ struct directive; /* Deliberately incomplete. */
|
||||
struct pending_option;
|
||||
struct op;
|
||||
|
||||
typedef unsigned HOST_WIDE_INT cpp_num_part;
|
||||
typedef unsigned char uchar;
|
||||
#define U (const uchar *) /* Intended use: U"string" */
|
||||
|
||||
|
@ -1774,6 +1774,9 @@ cpp_post_options (pfile)
|
||||
if (CPP_OPTION (pfile, cplusplus))
|
||||
CPP_OPTION (pfile, warn_traditional) = 0;
|
||||
|
||||
CPP_OPTION (pfile, warn_long_long) = (CPP_OPTION (pfile, pedantic)
|
||||
&& !CPP_OPTION (pfile, c99));
|
||||
|
||||
/* Permanently disable macro expansion if we are rescanning
|
||||
preprocessed text. Read preprocesed source in ISO mode. */
|
||||
if (CPP_OPTION (pfile, preprocessed))
|
||||
|
48
gcc/cpplib.h
48
gcc/cpplib.h
@ -327,6 +327,9 @@ struct cpp_options
|
||||
traditional C. */
|
||||
unsigned char warn_traditional;
|
||||
|
||||
/* Nonzero means warn about long long numeric constants. */
|
||||
unsigned char warn_long_long;
|
||||
|
||||
/* Nonzero means warn about text after an #endif (or #else). */
|
||||
unsigned char warn_endif_labels;
|
||||
|
||||
@ -577,6 +580,51 @@ extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *,
|
||||
int, int));
|
||||
extern int cpp_defined PARAMS ((cpp_reader *, const unsigned char *, int));
|
||||
|
||||
/* A preprocessing number. Code assumes that any unused high bits of
|
||||
the double integer are set to zero. */
|
||||
typedef unsigned HOST_WIDE_INT cpp_num_part;
|
||||
typedef struct cpp_num cpp_num;
|
||||
struct cpp_num
|
||||
{
|
||||
cpp_num_part high;
|
||||
cpp_num_part low;
|
||||
bool unsignedp; /* True if value should be treated as unsigned. */
|
||||
bool overflow; /* True if the most recent calculation overflowed. */
|
||||
};
|
||||
|
||||
/* cpplib provides two interfaces for interpretation of preprocessing
|
||||
numbers.
|
||||
|
||||
cpp_classify_number categorizes numeric constants according to
|
||||
their field (integer, floating point, or invalid), radix (decimal,
|
||||
octal, hexadecimal), and type suffixes. */
|
||||
|
||||
#define CPP_N_CATEGORY 0x000F
|
||||
#define CPP_N_INVALID 0x0000
|
||||
#define CPP_N_INTEGER 0x0001
|
||||
#define CPP_N_FLOATING 0x0002
|
||||
|
||||
#define CPP_N_WIDTH 0x00F0
|
||||
#define CPP_N_SMALL 0x0010 /* int, float. */
|
||||
#define CPP_N_MEDIUM 0x0020 /* long, double. */
|
||||
#define CPP_N_LARGE 0x0040 /* long long, long double. */
|
||||
|
||||
#define CPP_N_RADIX 0x0F00
|
||||
#define CPP_N_DECIMAL 0x0100
|
||||
#define CPP_N_HEX 0x0200
|
||||
#define CPP_N_OCTAL 0x0400
|
||||
|
||||
#define CPP_N_UNSIGNED 0x1000 /* Properties. */
|
||||
#define CPP_N_IMAGINARY 0x2000
|
||||
|
||||
/* Classify a CPP_NUMBER token. The return value is a combination of
|
||||
the flags from the above sets. */
|
||||
extern unsigned cpp_classify_number PARAMS ((cpp_reader *, const cpp_token *));
|
||||
|
||||
/* Evaluate a token classified as category CPP_N_INTEGER. */
|
||||
extern cpp_num cpp_interpret_integer PARAMS ((cpp_reader *, const cpp_token *,
|
||||
unsigned int type));
|
||||
|
||||
/* Diagnostic levels. To get a dianostic without associating a
|
||||
position in the translation unit with it, use cpp_error_with_line
|
||||
with a line number of zero. */
|
||||
|
@ -1,3 +1,9 @@
|
||||
2002-05-29 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
|
||||
* gcc.dg/cpp/c++98-pedantic.c, gcc.dg/cpp/c89-pedantic.c,
|
||||
gcc.dg/cpp/c94-pedantic.c, gcc.dg/cpp/gnuc89-pedantic.c,
|
||||
gcc.dg/cpp/if-1.c: Update for modified diagnostics.
|
||||
|
||||
2002-05-29 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
* gcc.c-torture/execute/20020529-1.c: New test.
|
||||
|
@ -6,5 +6,5 @@
|
||||
/* This file is for testing the preprocessor in -std=c++98 -pedantic mode.
|
||||
Neil Booth, 2 Dec 2000. */
|
||||
|
||||
#if 1LL /* { dg-warning "too many" } */
|
||||
#if 1LL /* { dg-warning "long long" } */
|
||||
#endif
|
||||
|
@ -6,5 +6,5 @@
|
||||
/* This file is for testing the preprocessor in -std=c89 -pedantic mode.
|
||||
Neil Booth, 2 Dec 2000. */
|
||||
|
||||
#if 1LL /* { dg-warning "too many" } */
|
||||
#if 1LL /* { dg-warning "long long" } */
|
||||
#endif
|
||||
|
@ -6,5 +6,5 @@
|
||||
/* This file is for testing the preprocessor in -std=iso9899:199409
|
||||
-pedantic mode. Neil Booth, 2 Dec 2000. */
|
||||
|
||||
#if 1LL /* { dg-warning "too many" } */
|
||||
#if 1LL /* { dg-warning "long long" } */
|
||||
#endif
|
||||
|
@ -6,5 +6,5 @@
|
||||
/* This file is for testing the preprocessor in -std=gnu89 -pedantic mode.
|
||||
Neil Booth, 2 Dec 2000. */
|
||||
|
||||
#if 1LL /* { dg-warning "too many" } */
|
||||
#if 1LL /* { dg-warning "long long" } */
|
||||
#endif
|
||||
|
@ -22,7 +22,7 @@
|
||||
#error 0xabc /* { dg-bogus "#error" "normal conversion" } */
|
||||
#endif
|
||||
|
||||
#if 1.2 /* { dg-error "loating point numbers" "floating point in #if" } */
|
||||
#if 1.2 /* { dg-error "loating constant" "floating point in #if" } */
|
||||
#endif
|
||||
|
||||
#if 4uu /* { dg-error "invalid suffix" "too many suffixes" } */
|
||||
@ -34,7 +34,7 @@
|
||||
#if 1234lul /* { dg-error "invalid suffix" "u between ls" } */
|
||||
#endif
|
||||
|
||||
#if 099 /* { dg-error "digits beyond the radix" "decimal in octal constant" } */
|
||||
#if 099 /* { dg-error "invalid digit" "decimal in octal constant" } */
|
||||
#endif
|
||||
|
||||
#if 0xfffffffffffffffff /* { dg-error "integer constant" "range error" } */
|
||||
|
Loading…
Reference in New Issue
Block a user