summaryrefslogtreecommitdiff
path: root/support/cpp/libcpp/expr.c
diff options
context:
space:
mode:
authorborutr <borutr@4a8a32a2-be11-0410-ad9d-d568d2c75423>2009-04-28 17:29:31 +0000
committerborutr <borutr@4a8a32a2-be11-0410-ad9d-d568d2c75423>2009-04-28 17:29:31 +0000
commit2ec965f8b4ec0c6e9fa87fad32ffcd775d0995bf (patch)
tree15f912b340aebe3c12e678283015112ee0fddde5 /support/cpp/libcpp/expr.c
parentfdbef79070d96a1d526e490132b6a33a3046d974 (diff)
* support/cpp/output.h, support/cpp/opts-common.c,
support/cpp/c-ppoutput.c, support/cpp/cppdefault.c, support/cpp/system.h, support/cpp/cppdefault.h, support/cpp/prefix.c, support/cpp/except.h, support/cpp/hwint.h, support/cpp/prefix.h, support/cpp/libiberty/safe-ctype.h, support/cpp/libiberty/filenames.h, support/cpp/libiberty/xstrdup.c, support/cpp/libiberty/md5.c, support/cpp/libiberty/obstack.h, support/cpp/sdcpp.c, support/cpp/intl.h, support/cpp/sdcpp.h support/cpp/libcpp/symtab.c, support/cpp/libcpp/directives.c, support/cpp/libcpp/macro.c, support/cpp/libcpp/include/cpplib.h, support/cpp/libcpp/include/symtab.h, support/cpp/libcpp/include/line-map.h, support/cpp/libcpp/include/cpp-id-data.h, support/cpp/libcpp/include/mkdeps.h, support/cpp/libcpp/files.c, support/cpp/libcpp/line-map.c, support/cpp/libcpp/init.c, support/cpp/libcpp/identifiers.c, support/cpp/libcpp/ucnid.h, support/cpp/libcpp/traditional.c, support/cpp/libcpp/errors.c, support/cpp/libcpp/expr.c, support/cpp/libcpp/internal.h, support/cpp/libcpp/mkdeps.c, support/cpp/libcpp/lex.c, support/cpp/libcpp/system.h, support/cpp/libcpp/charset.c, support/cpp/opts.h, support/cpp/sdcpp-opts.c: SDCPP synchronized with GCC CPP release version 4.4.0 git-svn-id: https://svn.code.sourceforge.net/p/sdcc/code/trunk/sdcc@5444 4a8a32a2-be11-0410-ad9d-d568d2c75423
Diffstat (limited to 'support/cpp/libcpp/expr.c')
-rw-r--r--support/cpp/libcpp/expr.c91
1 files changed, 74 insertions, 17 deletions
diff --git a/support/cpp/libcpp/expr.c b/support/cpp/libcpp/expr.c
index 8ac901086..539663c19 100644
--- a/support/cpp/libcpp/expr.c
+++ b/support/cpp/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, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with this program; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#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;
};
@@ -637,6 +637,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. */
@@ -691,6 +705,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);
@@ -729,10 +745,25 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
}
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;
@@ -793,9 +824,11 @@ static const struct cpp_operator
/* 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},
@@ -819,7 +852,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;
@@ -842,6 +875,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)
{
@@ -849,6 +883,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)
@@ -892,7 +928,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",
@@ -943,6 +979,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
@@ -953,7 +990,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. */
}
@@ -995,6 +1033,7 @@ 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:
@@ -1004,6 +1043,7 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
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:
@@ -1012,12 +1052,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:
@@ -1025,16 +1067,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[-1].loc = top->loc;
break;
case CPP_OR_OR:
@@ -1046,6 +1091,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:
@@ -1057,16 +1103,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:
@@ -1075,14 +1125,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;
@@ -1129,12 +1186,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));
}