summaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authordodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-16 10:51:15 +0000
committerdodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-16 10:51:15 +0000
commita60f3e81774f3ca9957f9693db03ec651a0f7ad9 (patch)
tree866b6e9e6346cbd21ad2a4974753e1735d1f01b6 /libcpp
parente54ce7078fcc30fe6aabeb9d372343d7435b6eb2 (diff)
downloadgcc-a60f3e81774f3ca9957f9693db03ec651a0f7ad9.tar.gz
PR preprocessor/7263 - Avoid pedantic warnings on system headers macro tokens
Now that we track token locations accross macro expansions, it would be cool to be able to fix PR preprocessor/7263 for real. That is, consider this example where we have a system header named header.h like this: #define _Complex __complex__ #define _Complex_I 1.0iF and then a normal C file like this: #include "header.h" static _Complex float c = _Complex_I; If we compile the file with -pedantic, the usages of _Complex or _Complex_I should not trigger any warning, even though __complex__ and the complex literal are extensions to the standard C. They shouldn't trigger any warning because _Complex and _Complex_I are defined in a system header (and expanded in normal user code). To be able to handle this, we must address two separate concerns. First, warnings about non-standard usage of numerical literals are emitted directly from within libcpp. So we must teach libcpp's parser for numerical literals to use virtual locations, instead of the spelling location it uses today. Once we have that, as the diagnostics machinery already knows how to avoid emitting errors happening on tokens that come from system headers, we win. Second, there is the issue of tracking locations for declaration specifiers, like the "_Complex" in the declaration: static _Complex float c; For that, we need to arrange for each possible declaration specifier to have its own location, because otherwise, we'd warn on e.g, on: _Complex float c; but not on: static _Complex float c; So this patch addresses the two concerns above. It's actually a follow-up on an earlier patch[1] I wrote as part of my initial work on virtual locations. We then agreed[2] that the second concern was important to address before the patch could get a chance to go in. [1]: http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00957.html [2]: http://gcc.gnu.org/ml/gcc-patches/2011-10/msg00264.html Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk. libcpp/ PR preprocessor/7263 * include/cpplib.h (cpp_classify_number): Take a location parameter. * expr.c (SYNTAX_ERROR_AT, SYNTAX_ERROR2_AT): New diagnostic macros that take a location parameter. (cpp_classify_number): Take a (virtual) location parameter. Use it for diagnostics. Adjust comments. (eval_token): Take a location parameter. Pass it to cpp_classify_number and to diagnostic routines. (_cpp_parse_expr): Use virtual locations of tokens when parsing expressions. Pass a virtual location to eval_token and to diagnostic routines. gcc/c-family/ PR preprocessor/7263 * c-lex.c (c_lex_with_flags): Pass a virtual location to the call to cpp_classify_number. For diagnostics, use the precise location instead of the global input_location. gcc/ PR preprocessor/7263 * c-tree.h (enum c_declspec_word): Declare new enum. (struct c_declspecs::locations): New member. (declspecs_add_qual, declspecs_add_scspec) (declspecs_add_addrspace, declspecs_add_alignas): Take a new location parameter. * c-decl.c (build_null_declspecs): Initialize the new struct c_declspecs::locations member. (declspecs_add_addrspace): Take a location parameter for the address space. Store it onto declaration specifiers. (declspecs_add_qual): Likewise, take a location parameter for the qualifier. (declspecs_add_type): Likewise, take a location parameter for the type specifier. (declspecs_add_scspec): Likewise, take a location parameter for the storage class specifier. (declspecs_add_attrs): Likewise, take a location parameter for the first attribute. (declspecs_add_alignas): Likewise, take a location parameter for the alignas token. (finish_declspecs): For diagnostics, use the location of the relevant declspec, instead of the global input_location. * c-parser.c (c_parser_parameter_declaration): Pass the precise virtual location of the declspec to the declspecs-setters. (c_parser_declspecs): Likewise. Avoid calling c_parser_peek_token repeatedly. gcc/cp/ PR preprocessor/7263 * cp-tree.h (enum cp_decl_spec): Add new enumerators to cover all the possible declarator specifiers so far. (struct cp_decl_specifier_seq::locations): Declare new member. (cp_decl_specifier_seq::{specs, type_location}): Remove. (decl_spec_seq_has_spec_p): Declare new function. * parser.c (cp_parser_check_decl_spec): Remove. (set_and_check_decl_spec_loc): Define new static function. (decl_spec_seq_has_spec_p): Define new public function. (cp_parser_decl_specifier_seq, cp_parser_function_specifier_opt) (cp_parser_type_specifier, cp_parser_simple_type_specifier) (cp_parser_set_storage_class, cp_parser_set_decl_spec_type) (cp_parser_alias_declaration): Set the locations for each declspec, using set_and_check_decl_spec_loc. (cp_parser_explicit_instantiation, cp_parser_init_declarator) (cp_parser_member_declaration, cp_parser_init_declarator): Use the new declspec location for specifiers. Use the new decl_spec_seq_has_spec_p. (cp_parser_type_specifier_seq): Use the new set_and_check_decl_spec_loc. Stop using cp_parser_check_decl_spec. Use the new decl_spec_seq_has_spec_p. (, cp_parser_init_declarator): Use the new set_and_check_decl_spec_loc. (cp_parser_single_declaration, cp_parser_friend_p) (cp_parser_objc_class_ivars, cp_parser_objc_struct_declaration): Use the new decl_spec_seq_has_spec_p. * decl.c (check_tag_decl): Use new decl_spec_seq_has_spec_p. Use the more precise ds_redefined_builtin_type_spec location for diagnostics about re-declaring C++ built-in types. (start_decl, grokvardecl, grokdeclarator): Use the new decl_spec_seq_has_spec_p. gcc/testsuite/ PR preprocessor/7263 * gcc.dg/binary-constants-2.c: Run without tracking locations accross macro expansion. * gcc.dg/binary-constants-3.c: Likewise. * gcc.dg/cpp/sysmac2.c: Likewise. * testsuite/gcc.dg/nofixed-point-2.c: Adjust for more precise location. * gcc.dg/cpp/syshdr3.c: New test. * gcc.dg/cpp/syshdr3.h: New header for the new test above. * gcc.dg/system-binary-constants-1.c: New test. * gcc.dg/system-binary-constants-1.h: New header for the new test above. * g++.dg/cpp/syshdr3.C: New test. * g++.dg/cpp/syshdr3.h: New header the new test above. * g++.dg/system-binary-constants-1.C: New test. * g++.dg/system-binary-constants-1.h: New header the new test above. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187587 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/ChangeLog15
-rw-r--r--libcpp/expr.c182
-rw-r--r--libcpp/include/cpplib.h2
3 files changed, 124 insertions, 75 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 07ef2437834..842f834aff1 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,18 @@
+2012-05-16 Dodji Seketeli <dodji@redhat.com>
+
+ PR preprocessor/7263
+ * include/cpplib.h (cpp_classify_number): Take a location
+ parameter.
+ * expr.c (SYNTAX_ERROR_AT, SYNTAX_ERROR2_AT): New diagnostic
+ macros that take a location parameter.
+ (cpp_classify_number): Take a (virtual) location parameter. Use
+ it for diagnostics. Adjust comments.
+ (eval_token): Take a location parameter. Pass it to
+ cpp_classify_number and to diagnostic routines.
+ (_cpp_parse_expr): Use virtual locations of tokens when parsing
+ expressions. Pass a virtual location to eval_token and to
+ diagnostic routines.
+
2012-05-10 Tristan Gingold <gingold@adacore.com>
* expr.c (interpret_float_suffix): Add a guard.
diff --git a/libcpp/expr.c b/libcpp/expr.c
index ca1c3d1928a..cd6e7d4eca6 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -59,7 +59,7 @@ static cpp_num num_rshift (cpp_num, size_t, size_t);
static cpp_num append_digit (cpp_num, int, int, size_t);
static cpp_num parse_defined (cpp_reader *);
-static cpp_num eval_token (cpp_reader *, const cpp_token *);
+static cpp_num eval_token (cpp_reader *, const cpp_token *, source_location);
static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype);
static unsigned int interpret_float_suffix (const uchar *, size_t);
static unsigned int interpret_int_suffix (const uchar *, size_t);
@@ -76,6 +76,12 @@ static void check_promotion (cpp_reader *, const struct op *);
#define SYNTAX_ERROR2(msgid, arg) \
do { cpp_error (pfile, CPP_DL_ERROR, msgid, arg); goto syntax_error; } \
while(0)
+#define SYNTAX_ERROR_AT(loc, msgid) \
+ do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid); goto syntax_error; } \
+ while(0)
+#define SYNTAX_ERROR2_AT(loc, msgid, arg) \
+ do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid, arg); goto syntax_error; } \
+ while(0)
/* Subroutine of cpp_classify_number. S points to a float suffix of
length LEN, possibly zero. Returns 0 for an invalid suffix, or a
@@ -359,11 +365,18 @@ cpp_get_userdef_suffix (const cpp_token *tok)
/* Categorize numeric constants according to their field (integer,
floating point, or invalid), radix (decimal, octal, hexadecimal),
- and type suffixes. In C++0X if UD_SUFFIX is non null it will be
- assigned any unrecognized suffix for a user-defined literal. */
+ and type suffixes.
+
+ TOKEN is the token that represents the numeric constant to
+ classify.
+
+ In C++0X if UD_SUFFIX is non null it will be assigned
+ any unrecognized suffix for a user-defined literal.
+
+ VIRTUAL_LOCATION is the virtual location for TOKEN. */
unsigned int
cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
- const char **ud_suffix)
+ const char **ud_suffix, source_location virtual_location)
{
const uchar *str = token->val.str.text;
const uchar *limit;
@@ -422,7 +435,8 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
if (float_flag == NOT_FLOAT)
float_flag = AFTER_POINT;
else
- SYNTAX_ERROR ("too many decimal points in number");
+ SYNTAX_ERROR_AT (virtual_location,
+ "too many decimal points in number");
}
else if ((radix <= 10 && (c == 'e' || c == 'E'))
|| (radix == 16 && (c == 'p' || c == 'P')))
@@ -450,8 +464,8 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
radix = 10;
if (CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "fixed-point constants are a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "fixed-point constants are a GCC extension");
goto syntax_ok;
}
else
@@ -464,26 +478,29 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
if (max_digit >= radix)
{
if (radix == 2)
- SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit);
+ SYNTAX_ERROR2_AT (virtual_location,
+ "invalid digit \"%c\" in binary constant", '0' + max_digit);
else
- SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
+ SYNTAX_ERROR2_AT (virtual_location,
+ "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");
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "invalid prefix \"0b\" for floating constant");
return CPP_N_INVALID;
}
if (radix == 16 && !seen_digit)
- SYNTAX_ERROR ("no digits in hexadecimal floating constant");
+ SYNTAX_ERROR_AT (virtual_location,
+ "no digits in hexadecimal floating constant");
if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "use of C99 hexadecimal floating constant");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "use of C99 hexadecimal floating constant");
if (float_flag == AFTER_EXPON)
{
@@ -492,14 +509,15 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
/* Exponent is decimal, even if string is a hex float. */
if (!ISDIGIT (*str))
- SYNTAX_ERROR ("exponent has no digits");
+ SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
do
str++;
while (ISDIGIT (*str));
}
else if (radix == 16)
- SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
+ SYNTAX_ERROR_AT (virtual_location,
+ "hexadecimal floating constants require an exponent");
result = interpret_float_suffix (str, limit - str);
if (result == 0)
@@ -512,9 +530,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
}
else
{
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid suffix \"%.*s\" on floating constant",
- (int) (limit - str), str);
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "invalid suffix \"%.*s\" on floating constant",
+ (int) (limit - str), str);
return CPP_N_INVALID;
}
}
@@ -523,33 +541,33 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
if (limit != str
&& CPP_WTRADITIONAL (pfile)
&& ! cpp_sys_macro_p (pfile))
- cpp_warning (pfile, CPP_W_TRADITIONAL,
- "traditional C rejects the \"%.*s\" suffix",
- (int) (limit - str), str);
+ cpp_warning_with_line (pfile, CPP_W_TRADITIONAL, virtual_location, 0,
+ "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");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "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);
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "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");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "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");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "decimal float constants are a GCC extension");
result |= CPP_N_FLOATING;
}
@@ -566,9 +584,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
}
else
{
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid suffix \"%.*s\" on integer constant",
- (int) (limit - str), str);
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "invalid suffix \"%.*s\" on integer constant",
+ (int) (limit - str), str);
return CPP_N_INVALID;
}
}
@@ -582,9 +600,10 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
&& CPP_OPTION (pfile, cpp_warn_long_long);
if (u_or_i || large)
- cpp_warning (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
- "traditional C rejects the \"%.*s\" suffix",
- (int) (limit - str), str);
+ cpp_warning_with_line (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
+ virtual_location, 0,
+ "traditional C rejects the \"%.*s\" suffix",
+ (int) (limit - str), str);
}
if ((result & CPP_N_WIDTH) == CPP_N_LARGE
@@ -595,9 +614,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
: N_("use of C99 long long integer constant");
if (CPP_OPTION (pfile, c99))
- cpp_warning (pfile, CPP_W_LONG_LONG, message);
+ cpp_warning_with_line (pfile, CPP_W_LONG_LONG, virtual_location,
+ 0, message);
else
- cpp_pedwarning (pfile, CPP_W_LONG_LONG, message);
+ cpp_pedwarning_with_line (pfile, CPP_W_LONG_LONG,
+ virtual_location, 0, message);
}
result |= CPP_N_INTEGER;
@@ -605,11 +626,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
syntax_ok:
if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "imaginary constants are a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "imaginary constants are a GCC extension");
if (radix == 2 && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "binary constants are a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "binary constants are a GCC extension");
if (radix == 10)
result |= CPP_N_DECIMAL;
@@ -897,7 +918,8 @@ parse_defined (cpp_reader *pfile)
number or character constant, or the result of the "defined" or "#"
operators). */
static cpp_num
-eval_token (cpp_reader *pfile, const cpp_token *token)
+eval_token (cpp_reader *pfile, const cpp_token *token,
+ source_location virtual_location)
{
cpp_num result;
unsigned int temp;
@@ -909,21 +931,21 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
switch (token->type)
{
case CPP_NUMBER:
- temp = cpp_classify_number (pfile, token, NULL);
+ temp = cpp_classify_number (pfile, token, NULL, virtual_location);
if (temp & CPP_N_USERDEF)
cpp_error (pfile, CPP_DL_ERROR,
"user-defined literal in preprocessor expression");
switch (temp & CPP_N_CATEGORY)
{
case CPP_N_FLOATING:
- cpp_error (pfile, CPP_DL_ERROR,
- "floating constant in preprocessor expression");
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "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, CPP_DL_ERROR,
- "imaginary number in preprocessor expression");
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "imaginary number in preprocessor expression");
break;
case CPP_N_INVALID:
@@ -970,8 +992,9 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
result.high = 0;
result.low = 0;
if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
- cpp_warning (pfile, CPP_W_UNDEF, "\"%s\" is not defined",
- NODE_NAME (token->val.node.node));
+ cpp_warning_with_line (pfile, CPP_W_UNDEF, virtual_location, 0,
+ "\"%s\" is not defined",
+ NODE_NAME (token->val.node.node));
}
break;
@@ -981,11 +1004,12 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
/* 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");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN,
+ virtual_location, 0,
+ "assertions are a GCC extension");
else if (CPP_OPTION (pfile, cpp_warn_deprecated))
- cpp_warning (pfile, CPP_W_DEPRECATED,
- "assertions are a deprecated extension");
+ cpp_warning_with_line (pfile, CPP_W_DEPRECATED, virtual_location, 0,
+ "assertions are a deprecated extension");
}
_cpp_test_assertion (pfile, &temp);
result.high = 0;
@@ -1087,6 +1111,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
struct op *top = pfile->op_stack;
unsigned int lex_count;
bool saw_leading_not, want_value = true;
+ source_location virtual_location = 0;
pfile->state.skip_eval = 0;
@@ -1103,9 +1128,9 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
struct op op;
lex_count++;
- op.token = cpp_get_token (pfile);
+ op.token = cpp_get_token_with_location (pfile, &virtual_location);
op.op = op.token->type;
- op.loc = op.token->src_loc;
+ op.loc = virtual_location;
switch (op.op)
{
@@ -1118,10 +1143,11 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
case CPP_NAME:
case CPP_HASH:
if (!want_value)
- SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
- cpp_token_as_text (pfile, op.token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "missing binary operator before token \"%s\"",
+ cpp_token_as_text (pfile, op.token));
want_value = false;
- top->value = eval_token (pfile, op.token);
+ top->value = eval_token (pfile, op.token, op.loc);
continue;
case CPP_NOT:
@@ -1138,8 +1164,9 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
default:
if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ)
- SYNTAX_ERROR2 ("token \"%s\" is not valid in preprocessor expressions",
- cpp_token_as_text (pfile, op.token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "token \"%s\" is not valid in preprocessor expressions",
+ cpp_token_as_text (pfile, op.token));
break;
}
@@ -1147,27 +1174,32 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
if (optab[op.op].flags & NO_L_OPERAND)
{
if (!want_value)
- SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
- cpp_token_as_text (pfile, op.token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "missing binary operator before token \"%s\"",
+ cpp_token_as_text (pfile, op.token));
}
else if (want_value)
{
/* We want a number (or expression) and haven't got one.
Try to emit a specific diagnostic. */
if (op.op == CPP_CLOSE_PAREN && top->op == CPP_OPEN_PAREN)
- SYNTAX_ERROR ("missing expression between '(' and ')'");
+ SYNTAX_ERROR_AT (op.loc,
+ "missing expression between '(' and ')'");
if (op.op == CPP_EOF && top->op == CPP_EOF)
- SYNTAX_ERROR2 ("%s with no expression", is_if ? "#if" : "#elif");
+ SYNTAX_ERROR2_AT (op.loc,
+ "%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",
- cpp_token_as_text (pfile, top->token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "operator '%s' has no right operand",
+ cpp_token_as_text (pfile, top->token));
else if (op.op == CPP_CLOSE_PAREN || op.op == CPP_EOF)
/* Complain about missing paren during reduction. */;
else
- SYNTAX_ERROR2 ("operator '%s' has no left operand",
- cpp_token_as_text (pfile, op.token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "operator '%s' has no left operand",
+ cpp_token_as_text (pfile, op.token));
}
top = reduce (pfile, top, op.op);
@@ -1192,7 +1224,8 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
break;
case CPP_COLON:
if (top->op != CPP_QUERY)
- SYNTAX_ERROR (" ':' without preceding '?'");
+ SYNTAX_ERROR_AT (op.loc,
+ " ':' without preceding '?'");
if (!num_zerop (top[-1].value)) /* Was '?' condition true? */
pfile->state.skip_eval++;
else
@@ -1209,7 +1242,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
top->op = op.op;
top->token = op.token;
- top->loc = op.token->src_loc;
+ top->loc = op.loc;
}
/* The controlling macro expression is only valid if we called lex 3
@@ -1220,8 +1253,9 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
if (top != pfile->op_stack)
{
- cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in %s",
- is_if ? "#if" : "#elif");
+ cpp_error_with_line (pfile, CPP_DL_ICE, top->loc, 0,
+ "unbalanced stack in %s",
+ is_if ? "#if" : "#elif");
syntax_error:
return false; /* Return false on syntax error. */
}
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 9dbc477b61e..2ec7eaaae2f 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -851,7 +851,7 @@ struct cpp_num
/* Classify a CPP_NUMBER token. The return value is a combination of
the flags from the above sets. */
extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *,
- const char **);
+ const char **, source_location);
/* Return the classification flags for a float suffix. */
extern unsigned int cpp_interpret_float_suffix (const char *, size_t);