This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[CPP] fix some diagnostic locations
- From: "Manuel López-Ibáñez" <lopezibanez at gmail dot com>
- To: "Gcc Patch List" <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 31 Oct 2008 03:25:48 +0100
- Subject: [CPP] fix some diagnostic locations
The way CPP builds expressions loses track of the locations of
subexpressions. The result is that CPP often points to the wrong
location, typically the end of the line. This patch propagates the
correct locations.
Bootstrapped and regression tested on x86_64-unknown-linux-gnu with
--enable-languages=all,obj-c++.
OK for trunk?
2008-10-31 Manuel López-Ibáñez <manu@gcc.gnu.org>
libcpp/
* expr.c (struct op): Add location.
(_cpp_parse_expr): Propagate locations throught the stack
of expressions.
(reduce): Likewise.
(check_promotion): Use explicit location in errors.
testsuite/
* gcc.dg/cpp/Wsignprom.c: Add column numbers.
* gcc.dg/cpp/if-mpar.c: Likewise.
Index: gcc/testsuite/gcc.dg/cpp/Wsignprom.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/Wsignprom.c (revision 141458)
+++ gcc/testsuite/gcc.dg/cpp/Wsignprom.c (working copy)
@@ -1,26 +1,26 @@
/* { dg-do preprocess } */
-/* { dg-options "-Wall" } */
+/* { dg-options "-Wall -fshow-column" } */
/* Test that -Wall emits the warnings about integer promotion changing
the sign of an operand. */
-#if -1 > 0U /* { dg-warning "changes sign when promoted" } */
+#if -1 > 0U /* { dg-warning "5:changes sign when promoted" } */
#endif
-#if 0U + -1 /* { dg-warning "changes sign when promoted" } */
+#if 0U + -1 /* { dg-warning "10:changes sign when promoted" } */
#endif
-#if 0U * -1 /* { dg-warning "changes sign when promoted" } */
+#if 0U * -1 /* { dg-warning "10:changes sign when promoted" } */
#endif
-#if 1U / -2 /* { dg-warning "changes sign when promoted" } */
+#if 1U / -2 /* { dg-warning "10:changes sign when promoted" } */
#endif
-#if -1 % 1U /* { dg-warning "changes sign when promoted" } */
+#if -1 % 1U /* { dg-warning "5:changes sign when promoted" } */
#endif
-#if 1 ? 0U : -1 /* { dg-warning "changes sign when promoted" } */
+#if 1 ? 0U : -1 /* { dg-warning "14:changes sign when promoted" } */
#endif
-#if 1 ? -1 : 0U /* { dg-warning "changes sign when promoted" } */
+#if 1 ? -1 : 0U /* { dg-warning "9:changes sign when promoted" } */
#endif
Index: gcc/testsuite/gcc.dg/cpp/if-mpar.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/if-mpar.c (revision 141458)
+++ gcc/testsuite/gcc.dg/cpp/if-mpar.c (working copy)
@@ -2,23 +2,29 @@
/* Test various combinations of missing parentheses give the correct
missing parenthesis message. */
/* { dg-do preprocess } */
+/* { dg-options "-fshow-column" } */
+#if (1 /* { dg-error "5:missing '\\)'" "missing ')' no. 1" } */
+#endif
+
+#if 2 * (3 + 4 /* { dg-error "9:missing '\\)'" "missing ')' no. 2" } */
+#endif
-#if (1 /* { dg-error "missing '\\)'" "missing ')' no. 1" } */
+#if (2)) /* { dg-error "8:missing '\\('" "missing '(' no. 1" } */
#endif
-#if 2 * (3 + 4 /* { dg-error "missing '\\)'" "missing ')' no. 2" } */
+#if ) /* { dg-error "5:missing '\\('" "missing '(' no. 2" } */
#endif
-#if (2)) /* { dg-error "missing '\\('" "missing '(' no. 1" } */
+#if 4) /* { dg-error "6:missing '\\('" "missing '(' no. 3" } */
#endif
-#if ) /* { dg-error "missing '\\('" "missing '(' no. 2" } */
+#if ( /* { dg-error "5:missing '\\)'" "missing ')' no. 3" } */
#endif
-#if 4) /* { dg-error "missing '\\('" "missing '(' no. 3" } */
+#if ((2 + 3) + 5 /* { dg-error "5:missing '\\)'" "missing ')' no. 3" } */
#endif
-#if ( /* { dg-error "missing '\\)'" "missing ')' no. 3" } */
+#if ((2 + 3 + 5 /* { dg-error "6:missing '\\)'" "missing ')' no. 3" } */
#endif
Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c (revision 141458)
+++ libcpp/expr.c (working copy)
@@ -30,10 +30,11 @@ Boston, MA 02110-1301, USA. */
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;
};
/* Some simple utility routines on double integers. */
#define num_zerop(num) ((num.low | num.high) == 0)
@@ -873,10 +874,11 @@ _cpp_parse_expr (cpp_reader *pfile, bool
struct op op;
lex_count++;
op.token = cpp_get_token (pfile);
op.op = op.token->type;
+ op.loc = op.token->src_loc;
switch (op.op)
{
/* These tokens convert into values. */
case CPP_NUMBER:
@@ -976,10 +978,11 @@ _cpp_parse_expr (cpp_reader *pfile, bool
if (++top == pfile->op_limit)
top = _cpp_expand_op_stack (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
times: <!> <defined expression> and <EOF>. push_conditional ()
checks that we are at top-of-file. */
@@ -1029,50 +1032,57 @@ 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].loc = top->loc;
break;
case CPP_PLUS:
case CPP_MINUS:
case CPP_RSHIFT:
case CPP_LSHIFT:
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:
case CPP_LESS:
case CPP_GREATER_EQ:
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:
case CPP_OR:
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[-1].loc = top->loc;
break;
case CPP_OR_OR:
top--;
if (!num_zerop (top->value))
@@ -1080,10 +1090,11 @@ reduce (cpp_reader *pfile, struct op *to
top->value.low = (!num_zerop (top->value)
|| !num_zerop (top[1].value));
top->value.high = 0;
top->value.unsignedp = false;
top->value.overflow = false;
+ top->loc = top[1].loc;
continue;
case CPP_AND_AND:
top--;
if (num_zerop (top->value))
@@ -1091,31 +1102,39 @@ reduce (cpp_reader *pfile, struct op *to
top->value.low = (!num_zerop (top->value)
&& !num_zerop (top[1].value));
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:
top -= 2;
if (!num_zerop (top->value))
{
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:
@@ -1166,16 +1185,16 @@ check_promotion (cpp_reader *pfile, cons
return;
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));
}
/* Clears the unused high order bits of the number pointed to by PNUM. */