Index: gcc/testsuite/gcc.dg/cpp/pr35322.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/pr35322.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/pr35322.c (working copy) @@ -1,4 +1,5 @@ /* Test case for PR 35322 -- _Pragma ICE. */ /* { dg-do preprocess } */ -_Pragma("GCC dependency") /* { dg-error "#pragma dependency expects" } */ +/* { dg-options "-fshow-column" } */ +_Pragma("GCC dependency") /* { dg-error "1:#pragma dependency expects" } */ Index: gcc/testsuite/gcc.dg/cpp/pr36320.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/pr36320.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/pr36320.c (working copy) @@ -1,8 +1,8 @@ /* PR 36320 - #elif still requires valid expression. */ /* { dg-do preprocess } */ - +/* { dg-options "-fshow-column" } */ int z; #if 1 -#elif /* { dg-error "with no expression" } */ +#elif /* { dg-error "1:with no expression" } */ #endif Index: gcc/testsuite/gcc.dg/cpp/pr34602.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/pr34602.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/pr34602.c (working copy) @@ -1,6 +1,6 @@ /* PR preprocessor/34602 - no internal error trying to spell EOF. */ /* { dg-do preprocess } */ - -/* { dg-error "unexpected end" "" { target *-*-* } 6 } */ +/* { dg-options "-fshow-column" } */ +/* { dg-error "1:unexpected end" "" { target *-*-* } 6 } */ #line Index: gcc/testsuite/gcc.dg/cpp/macsyntx.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/macsyntx.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/macsyntx.c (working copy) @@ -1,9 +1,9 @@ /* Copyright (C) 2000 Free Software Foundation, Inc. */ /* { dg-do preprocess } */ -/* { dg-options "-pedantic -std=gnu99" } */ +/* { dg-options "-pedantic -std=gnu99 -fshow-column" } */ /* Tests macro syntax, for both definition and invocation, including:- o Full range of macro definition semantics. o No. of arguments supplied to function-like macros. @@ -17,26 +17,26 @@ despite being an error. Split a couple of the lines to check that the errors appear on the right line (i.e. are associated with the correct token). */ -#define ; /* { dg-error "identifier" } */ -#define SEMI; /* { dg-warning "space" } */ -#define foo(X /* { dg-error "missing" } */ +#define ; /* { dg-error "9:identifier" } */ +#define SEMI; /* { dg-warning "13:space" } */ +#define foo(X /* { dg-error "12:missing" } */ #define foo\ -(X,) /* { dg-error "parameter name" } */ -#define foo(, X) /* { dg-error "parameter name" } */ -#define foo(X, X) /* { dg-error "duplicate" } */ -#define foo(X Y) /* { dg-error "comma" } */ -#define foo(() /* { dg-error "may not appear" } */ -#define foo(..., X) /* { dg-error "missing" } */ +(X,) /* { dg-error "4:parameter name" } */ +#define foo(, X) /* { dg-error "13:parameter name" } */ +#define foo(X, X) /* { dg-error "16:duplicate" } */ +#define foo(X Y) /* { dg-error "15:comma" } */ +#define foo(() /* { dg-error "13:may not appear" } */ +#define foo(..., X) /* { dg-error "16:missing" } */ #define foo \ -__VA_ARGS__ /* { dg-warning "__VA_ARGS__" } */ -#define goo(__VA_ARGS__) /* { dg-warning "__VA_ARGS__" } */ +__VA_ARGS__ /* { dg-warning "1:__VA_ARGS__" } */ +#define goo(__VA_ARGS__) /* { dg-warning "13:__VA_ARGS__" } */ #define hoo(...) __VA_ARGS__ /* OK. */ -#define __VA_ARGS__ /* { dg-warning "__VA_ARGS__" } */ -__VA_ARGS__ /* { dg-warning "__VA_ARGS__" } */ +#define __VA_ARGS__ /* { dg-warning "9:__VA_ARGS__" } */ +__VA_ARGS__ /* { dg-warning "1:__VA_ARGS__" } */ /* test # of supplied arguments. */ #define none() #define one(x) #define two(x, y) @@ -55,13 +55,13 @@ var1() /* { dg-warning "rest argument var1(ichi) /* { dg-warning "rest arguments to be used" } */ var1(ichi, ni) /* OK. */ /* This tests two oddities of GNU rest args - omitting a comma is OK, and backtracking a token on pasting an empty rest args. */ -#define rest(x, y...) x ## y /* { dg-warning "ISO C" } */ +#define rest(x, y...) x ## y /* { dg-warning "18:ISO C" } */ rest(ichi,) /* OK. */ -rest(ichi) /* { dg-warning "rest arguments to be used" } */ +rest(ichi) /* { dg-warning "10:rest arguments to be used" } */ #if 23 != rest(2, 3) /* OK, no warning. */ #error 23 != 23 !! #endif /* Test that we don't allow arguments to flow into the rest of the Index: gcc/testsuite/gcc.dg/cpp/arith-3.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/arith-3.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/arith-3.c (working copy) @@ -7,11 +7,11 @@ arithmetic that are dependent on target precision. Please keep changes to arith-2.c and arith-3.c in sync. */ /* { dg-do preprocess } */ -/* { dg-options "-std=c99 -fno-show-column" } */ +/* { dg-options "-std=c99 -fshow-column" } */ #include #define APPEND2(NUM, SUFF) NUM ## SUFF #define APPEND(NUM, SUFF) APPEND2(NUM, SUFF) @@ -272,11 +272,11 @@ #if -TARG_MAX_PLUS_1_U / -1 != 0 /* { dg-bogus "overflow" } */ # error /* { dg-bogus "error" } */ #endif -#if -5 / (2 - 2) /* { dg-error "division by zero" } */ +#if -5 / (2 - 2) /* { dg-error "13:division by zero" } */ #endif #if LONG_UDIVISION != LONG_UDIVISION_ANSWER # error /* { dg-bogus "error" } */ #endif @@ -284,11 +284,11 @@ #if LONG_SDIVISION != LONG_SDIVISION_ANSWER # error /* { dg-bogus "error" } */ #endif /* Binary %. Cannot overflow. */ -#if -5 % (2 - 2) /* { dg-error "division by zero" } */ +#if -5 % (2 - 2) /* { dg-error "13:division by zero" } */ #endif #if TARG_MIN % 1 /* { dg-bogus "overflow" } */ # error /* { dg-bogus "error" } */ #endif Index: gcc/testsuite/gcc.dg/cpp/tr-warn5.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/tr-warn5.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/tr-warn5.c (working copy) @@ -1,12 +1,12 @@ /* Test for -Wtraditional warnings on the unary plus operator. Note, gcc should omit these warnings in system header files. By Kaveh R. Ghazi 8/22/2000. */ /* { dg-do preprocess } */ -/* { dg-options "-Wtraditional -fno-show-column" } */ +/* { dg-options "-Wtraditional -fshow-column" } */ -#if +1 /* { dg-warning "unary plus operator" "unary plus operator" } */ +#if +1 /* { dg-warning "5:unary plus operator" "unary plus operator" } */ #endif # 11 "sys-header.h" 3 /* We are in system headers now, no -Wtraditional warnings should issue. */ Index: gcc/testsuite/gcc.dg/cpp/multiline.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/multiline.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/multiline.c (working copy) @@ -1,8 +1,8 @@ /* Copyright (C) 2000, 2003 Free Software Foundation, Inc. */ /* { dg-do preprocess } */ -/* { dg-options "-C" } */ +/* { dg-options "-C -fshow-column" } */ /* Test that multi-line tokens are recognized by cpp0 as being multiline . Source: Neil Booth, 17 Dec 2000. */ /* Line 1 Line 2 Line 3 @@ -17,9 +17,9 @@ L"line 1 line 3 line 4" /* Nowhere in the output of this file should there be a blank line. We check for that in the .i file. { dg-final { scan-file-not multiline.i "(^|\\n)\\n" } } */ -/* { dg-warning "missing term" "multiline strings" { target *-*-* } 11 } */ -/* { dg-warning "missing term" "multiline strings" { target *-*-* } 14 } */ -/* { dg-warning "missing term" "multiline strings" { target *-*-* } 15 } */ -/* { dg-warning "missing term" "multiline strings" { target *-*-* } 18 } */ +/* { dg-warning "1:missing term" "multiline strings" { target *-*-* } 11 } */ +/* { dg-warning "8:missing term" "multiline strings" { target *-*-* } 14 } */ +/* { dg-warning "1:missing term" "multiline strings" { target *-*-* } 15 } */ +/* { dg-warning "9:missing term" "multiline strings" { target *-*-* } 18 } */ Index: gcc/testsuite/gcc.dg/cpp/empty-include.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/empty-include.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/empty-include.c (working copy) @@ -7,7 +7,8 @@ * * We should get an error. */ /* { dg-do preprocess } */ -#include "" /* { dg-error "empty" "error on empty filename in include" } */ +/* { dg-options "-fshow-column" } */ +#include "" /* { dg-error "10:empty" "error on empty filename in include" } */ int x; /* Otherwise we have an empty file and get more errors. */ Index: gcc/testsuite/gcc.dg/cpp/assert2.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/assert2.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/assert2.c (working copy) @@ -1,24 +1,24 @@ /* Malformed assertion tests. */ /* { dg-do preprocess } */ -/* { dg-options "-fno-show-column -Wno-deprecated" } */ +/* { dg-options "-fshow-column -Wno-deprecated" } */ -#assert /* { dg-error "without predicate" "assert w/o predicate" } */ -#assert % /* { dg-error "an identifier" "assert punctuation" } */ -#assert 12 /* { dg-error "an identifier" "assert number" } */ -#assert abc /* { dg-error "missing" "assert w/o answer" } */ +#assert /* { dg-error "1:without predicate" "assert w/o predicate" } */ +#assert % /* { dg-error "9:an identifier" "assert punctuation" } */ +#assert 12 /* { dg-error "9:an identifier" "assert number" } */ +#assert abc /* { dg-error "9:missing" "assert w/o answer" } */ -#if # /* { dg-error "without predicate" "test w/o predicate" } */ +#if # /* { dg-error "1:without predicate" "test w/o predicate" } */ #endif -#if #% /* { dg-error "an identifier" "test punctuation" } */ +#if #% /* { dg-error "6:an identifier" "test punctuation" } */ #endif -#if #12 /* { dg-error "an identifier" "test number" } */ +#if #12 /* { dg-error "6:an identifier" "test number" } */ #endif #if #abc #error /* { dg-bogus "error" "test w/o answer" } */ #endif -#if #abc[def] /* { dg-error "is not valid" "test with malformed answer" } */ +#if #abc[def] /* { dg-error "9:is not valid" "test with malformed answer" } */ #endif Index: gcc/testsuite/gcc.dg/cpp/if-mop.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/if-mop.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/if-mop.c (working copy) @@ -1,31 +1,31 @@ /* Copyright (C) 2000 Free Software Foundation, Inc. */ /* { dg-do preprocess } */ - +/* { dg-options "-fshow-column" } /* Source: Neil Booth. */ /* Various illegal expressions with missing components. */ #if /* { dg-error "no expression" "empty #if" } */ #endif -#if ~ /* { dg-error "no right op" "no unary operand" } */ +#if ~ /* { dg-error "5:no right op" "no unary operand" } */ #endif -#if 3 + * 6 + 4 /* { dg-error "no right op" "no right operand" } */ +#if 3 + * 6 + 4 /* { dg-error "7:no right op" "no right operand" } */ #endif -#if 2 ~2 /* { dg-error "missing bin" "no binary operator" } */ +#if 2 ~2 /* { dg-error "7:missing bin" "no binary operator" } */ #endif -#if 1 + 2 (3) /* { dg-error "missing bin" "immediate then open paren" } */ +#if 1 + 2 (3) /* { dg-error "11:missing bin" "immediate then open paren" } */ #endif -#if (2) 4 * 2 /* { dg-error "missing bin" "close paren then immediate" } */ +#if (2) 4 * 2 /* { dg-error "9:missing bin" "close paren then immediate" } */ #endif -#if == 2 /* { dg-error "no left op" } */ +#if == 2 /* { dg-error "5:no left op" } */ #endif -#if (==2) /* { dg-error "no left op" } */ +#if (==2) /* { dg-error "6:no left op" } */ #endif Index: gcc/testsuite/gcc.dg/cpp/trad/literals-2.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/trad/literals-2.c (revision 141538) +++ gcc/testsuite/gcc.dg/cpp/trad/literals-2.c (working copy) @@ -1,8 +1,8 @@ /* Test that unterminated quotes in CPP expressions are recognized. */ - /* { dg-do preprocess } */ -/* { dg-warning "missing terminating" "bad charconst" { target *-*-* } 7 } */ -/* { dg-error "not valid" "bad charconst" { target *-*-* } 7 } */ +/* { dg-options "-fshow-column" } */ +/* { dg-warning "5:missing terminating" "bad charconst" { target *-*-* } 7 } */ +/* { dg-error "5:not valid" "bad charconst" { target *-*-* } 7 } */ #if 'x #endif Index: libcpp/macro.c =================================================================== --- libcpp/macro.c (revision 141538) +++ libcpp/macro.c (working copy) @@ -65,11 +65,11 @@ static bool create_iso_definition (cpp_r static cpp_token *alloc_expansion_token (cpp_reader *, cpp_macro *); static cpp_token *lex_expansion_token (cpp_reader *, cpp_macro *); static bool warn_of_redefinition (cpp_reader *, const cpp_hashnode *, const cpp_macro *); -static bool parse_params (cpp_reader *, cpp_macro *); +static bool parse_params (cpp_reader *, cpp_macro *, source_location); static void check_trad_stringification (cpp_reader *, const cpp_macro *, const cpp_string *); /* Emits a warning if NODE is a macro defined in the main file that has not been used. */ @@ -1474,13 +1474,14 @@ _cpp_save_parameter (cpp_reader *pfile, node->value.arg_index = macro->paramc; return false; } /* Check the syntax of the parameters in a MACRO definition. Returns - false if an error occurs. */ + false if an error occurs. LOCATION is the location of the open + paren. */ static bool -parse_params (cpp_reader *pfile, cpp_macro *macro) +parse_params (cpp_reader *pfile, cpp_macro *macro, source_location location) { unsigned int prev_ident = 0; for (;;) { @@ -1547,14 +1548,18 @@ parse_params (cpp_reader *pfile, cpp_mac /* We're at the end, and just expect a closing parenthesis. */ token = _cpp_lex_token (pfile); if (token->type == CPP_CLOSE_PAREN) return true; + /* Put the error on the token after the ellipsis in this + case. */ + location = token->src_loc; /* Fall through. */ case CPP_EOF: - cpp_error (pfile, CPP_DL_ERROR, "missing ')' in macro parameter list"); + cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0, + "missing ')' in macro parameter list"); return false; } } } @@ -1607,11 +1612,11 @@ create_iso_definition (cpp_reader *pfile function-like macro). */ ctoken = _cpp_lex_token (pfile); if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE)) { - bool ok = parse_params (pfile, macro); + bool ok = parse_params (pfile, macro, ctoken->src_loc); macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); if (!ok) return false; /* Success. Commit or allocate the parameter array. */ Index: libcpp/directives.c =================================================================== --- libcpp/directives.c (revision 141538) +++ libcpp/directives.c (working copy) @@ -97,11 +97,12 @@ static void start_directive (cpp_reader static void prepare_directive_trad (cpp_reader *); static void end_directive (cpp_reader *, int); static void directive_diagnostics (cpp_reader *, const directive *, int); static void run_directive (cpp_reader *, int, const char *, size_t); static char *glue_header_name (cpp_reader *); -static const char *parse_include (cpp_reader *, int *, const cpp_token ***); +static const char *parse_include (cpp_reader *, int *, const cpp_token ***, + source_location *); static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *); static unsigned int read_flag (cpp_reader *, unsigned int); static bool strtolinenum (const uchar *, size_t, linenum_type *, bool *); static void do_diagnostic (cpp_reader *, int, int); static cpp_hashnode *lex_macro_node (cpp_reader *, bool); @@ -119,11 +120,11 @@ static void do_pragma_system_header (cpp static void do_pragma_dependency (cpp_reader *); static void do_linemarker (cpp_reader *); static const cpp_token *get_token_no_padding (cpp_reader *); static const cpp_token *get__Pragma_string (cpp_reader *); static void destringize_and_run (cpp_reader *, const cpp_string *); -static int parse_answer (cpp_reader *, struct answer **, int); +static int parse_answer (cpp_reader *, struct answer **, int, source_location); static cpp_hashnode *parse_assertion (cpp_reader *, struct answer **, int); static struct answer ** find_answer (cpp_hashnode *, const struct answer *); static void handle_assertion (cpp_reader *, const char *, int); /* This is the table of directive handlers. It is ordered by @@ -678,20 +679,23 @@ glue_header_name (cpp_reader *pfile) return buffer; } /* Returns the file name of #include, #include_next, #import and #pragma dependency. The string is malloced and the caller should - free it. Returns NULL on error. */ + free it. Returns NULL on error. LOCATION is the source location + of the file name. */ + static const char * parse_include (cpp_reader *pfile, int *pangle_brackets, - const cpp_token ***buf) + const cpp_token ***buf, source_location *location) { char *fname; const cpp_token *header; /* Allow macro expansion. */ header = get_token_no_padding (pfile); + *location = header->src_loc; if (header->type == CPP_STRING || header->type == CPP_HEADER_NAME) { fname = XNEWVEC (char, header->val.str.len - 1); memcpy (fname, header->val.str.text + 1, header->val.str.len - 2); fname[header->val.str.len - 2] = '\0'; @@ -708,13 +712,12 @@ parse_include (cpp_reader *pfile, int *p if (pfile->directive == &dtable[T_PRAGMA]) dir = UC"pragma dependency"; else dir = pfile->directive->name; - cpp_error (pfile, CPP_DL_ERROR, "#%s expects \"FILENAME\" or ", - dir); - + cpp_error_with_line (pfile, CPP_DL_ERROR, pfile->directive_line, 0, + "#%s expects \"FILENAME\" or ", dir); return NULL; } if (pfile->directive == &dtable[T_PRAGMA]) { @@ -737,27 +740,29 @@ static void do_include_common (cpp_reader *pfile, enum include_type type) { const char *fname; int angle_brackets; const cpp_token **buf = NULL; + source_location location; /* Re-enable saving of comments if requested, so that the include callback can dump comments which follow #include. */ pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); - fname = parse_include (pfile, &angle_brackets, &buf); + fname = parse_include (pfile, &angle_brackets, &buf, &location); if (!fname) { if (buf) XDELETEVEC (buf); return; } if (!*fname) { - cpp_error (pfile, CPP_DL_ERROR, "empty filename in #%s", - pfile->directive->name); + cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0, + "empty filename in #%s", + pfile->directive->name); XDELETEVEC (fname); if (buf) XDELETEVEC (buf); return; } @@ -889,11 +894,12 @@ do_line (cpp_reader *pfile) if (token->type != CPP_NUMBER || strtolinenum (token->val.str.text, token->val.str.len, &new_lineno, &wrapped)) { if (token->type == CPP_EOF) - cpp_error (pfile, CPP_DL_ERROR, "unexpected end of file after #line"); + cpp_error_with_line (pfile, CPP_DL_ERROR, pfile->directive_line, 0, + "unexpected end of file after #line"); else cpp_error (pfile, CPP_DL_ERROR, "\"%s\" after #line is not a positive integer", cpp_token_as_text (pfile, token)); return; @@ -1465,22 +1471,24 @@ do_pragma_system_header (cpp_reader *pfi static void do_pragma_dependency (cpp_reader *pfile) { const char *fname; int angle_brackets, ordering; + source_location location; - fname = parse_include (pfile, &angle_brackets, NULL); + fname = parse_include (pfile, &angle_brackets, NULL, &location); if (!fname) return; ordering = _cpp_compare_file_date (pfile, fname, angle_brackets); if (ordering < 0) - cpp_error (pfile, CPP_DL_WARNING, "cannot find source file %s", fname); + cpp_error_with_line (pfile, CPP_DL_WARNING, location, 0, + "cannot find source file %s", fname); else if (ordering > 0) { - cpp_error (pfile, CPP_DL_WARNING, - "current file is older than %s", fname); + cpp_error_with_line (pfile, CPP_DL_WARNING, location, 0, + "current file is older than %s", fname); if (cpp_get_token (pfile)->type != CPP_EOF) { _cpp_backup_tokens (pfile, 1); do_diagnostic (pfile, CPP_DL_WARNING, 0); } @@ -1887,13 +1895,15 @@ push_conditional (cpp_reader *pfile, int } /* Read the tokens of the answer into the macro pool, in a directive of type TYPE. Only commit the memory if we intend it as permanent storage, i.e. the #assert case. Returns 0 on success, and sets - ANSWERP to point to the answer. */ + ANSWERP to point to the answer. PRED_LOC is the location of the + predicate. */ static int -parse_answer (cpp_reader *pfile, struct answer **answerp, int type) +parse_answer (cpp_reader *pfile, struct answer **answerp, int type, + source_location pred_loc) { const cpp_token *paren; struct answer *answer; unsigned int acount; @@ -1914,11 +1924,12 @@ parse_answer (cpp_reader *pfile, struct /* #unassert with no answer is valid - it removes all answers. */ if (type == T_UNASSERT && paren->type == CPP_EOF) return 0; - cpp_error (pfile, CPP_DL_ERROR, "missing '(' after predicate"); + cpp_error_with_line (pfile, CPP_DL_ERROR, pred_loc, 0, + "missing '(' after predicate"); return 1; } for (acount = 0;; acount++) { @@ -1976,14 +1987,16 @@ parse_assertion (cpp_reader *pfile, stru pfile->state.prevent_expansion++; *answerp = 0; predicate = cpp_get_token (pfile); if (predicate->type == CPP_EOF) - cpp_error (pfile, CPP_DL_ERROR, "assertion without predicate"); + cpp_error_with_line (pfile, CPP_DL_ERROR, pfile->directive_line, 0, + "assertion without predicate"); else if (predicate->type != CPP_NAME) - cpp_error (pfile, CPP_DL_ERROR, "predicate must be an identifier"); - else if (parse_answer (pfile, answerp, type) == 0) + cpp_error_with_line (pfile, CPP_DL_ERROR, predicate->src_loc, 0, + "predicate must be an identifier"); + else if (parse_answer (pfile, answerp, type, predicate->src_loc) == 0) { unsigned int len = NODE_LEN (predicate->val.node); unsigned char *sym = (unsigned char *) alloca (len + 1); /* Prefix '#' to get it out of macro namespace. */ Index: libcpp/expr.c =================================================================== --- libcpp/expr.c (revision 141538) +++ libcpp/expr.c (working copy) @@ -42,20 +42,22 @@ struct op static bool num_positive (cpp_num, size_t); static bool num_greater_eq (cpp_num, cpp_num, size_t); static cpp_num num_trim (cpp_num, size_t); static cpp_num num_part_mul (cpp_num_part, cpp_num_part); -static cpp_num num_unary_op (cpp_reader *, cpp_num, enum cpp_ttype); +static cpp_num num_unary_op (cpp_reader *, cpp_num, enum cpp_ttype, + source_location); static cpp_num num_binary_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype); static cpp_num num_negate (cpp_num, size_t); static cpp_num num_bitwise_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype); static cpp_num num_inequality_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype); 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); static cpp_num append_digit (cpp_num, int, int, size_t); static cpp_num parse_defined (cpp_reader *); @@ -74,10 +76,13 @@ static void check_promotion (cpp_reader #define SYNTAX_ERROR(msgid) \ do { cpp_error (pfile, CPP_DL_ERROR, msgid); goto syntax_error; } while(0) #define SYNTAX_ERROR2(msgid, arg) \ do { cpp_error (pfile, CPP_DL_ERROR, msgid, arg); goto syntax_error; } \ while(0) +#define SYNTAX_ERROR2_LOC(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 flag vector describing the suffix. */ static unsigned int @@ -927,15 +932,16 @@ _cpp_parse_expr (cpp_reader *pfile, bool Try to emit a specific diagnostic. */ if (op.op == CPP_CLOSE_PAREN && top->op == CPP_OPEN_PAREN) SYNTAX_ERROR ("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_LOC (pfile->directive_line, "%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_LOC (top->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)); @@ -1031,11 +1037,11 @@ reduce (cpp_reader *pfile, struct op *to { case CPP_UPLUS: case CPP_UMINUS: case CPP_NOT: case CPP_COMPL: - top[-1].value = num_unary_op (pfile, top->value, top->op); + top[-1].value = num_unary_op (pfile, top->value, top->op, top->loc); top[-1].loc = top->loc; break; case CPP_PLUS: case CPP_MINUS: @@ -1077,11 +1083,11 @@ reduce (cpp_reader *pfile, struct op *to 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: top--; @@ -1443,18 +1449,19 @@ num_lshift (cpp_num num, size_t precisio return num; } /* The four unary operators: +, -, ! and ~. */ static cpp_num -num_unary_op (cpp_reader *pfile, cpp_num num, enum cpp_ttype op) +num_unary_op (cpp_reader *pfile, cpp_num num, enum cpp_ttype op, + source_location loc) { switch (op) { case CPP_UPLUS: if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval) - cpp_error (pfile, CPP_DL_WARNING, - "traditional C rejects the unary plus operator"); + cpp_error_with_line (pfile, CPP_DL_WARNING, loc, 0, + "traditional C rejects the unary plus operator"); num.overflow = false; break; case CPP_UMINUS: num = num_negate (num, CPP_OPTION (pfile, precision)); @@ -1622,14 +1629,17 @@ num_mul (cpp_reader *pfile, cpp_num lhs, result.unsignedp = unsignedp; 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; bool unsignedp = lhs.unsignedp || rhs.unsignedp; bool negate = false, lhs_neg = false; @@ -1665,11 +1675,12 @@ num_div_op (cpp_reader *pfile, cpp_num l break; } 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; } /* First nonzero bit of RHS is bit I. Do naive division by shifting the RHS fully left, and subtracting from LHS if LHS is Index: libcpp/lex.c =================================================================== --- libcpp/lex.c (revision 141538) +++ libcpp/lex.c (working copy) @@ -662,12 +662,15 @@ lex_string (cpp_reader *pfile, cpp_token if (saw_NUL && !pfile->state.skipping) cpp_error (pfile, CPP_DL_WARNING, "null character(s) preserved in literal"); if (type == CPP_OTHER && CPP_OPTION (pfile, lang) != CLK_ASM) - cpp_error (pfile, CPP_DL_PEDWARN, "missing terminating %c character", - (int) terminator); + /* It seems nicer to use the location of the starting quote for + this error. */ + cpp_error_with_line (pfile, CPP_DL_PEDWARN, token->src_loc, 0, + "missing terminating %c character", + (int) terminator); pfile->buffer->cur = cur; create_literal (pfile, token, base, cur - base, type); }