aboutsummaryrefslogtreecommitdiff
path: root/libcpp/expr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libcpp/expr.cc')
-rw-r--r--libcpp/expr.cc55
1 files changed, 47 insertions, 8 deletions
diff --git a/libcpp/expr.cc b/libcpp/expr.cc
index 815eb13..3202d8e 100644
--- a/libcpp/expr.cc
+++ b/libcpp/expr.cc
@@ -1106,6 +1106,9 @@ parse_defined (cpp_reader *pfile)
const cpp_token *token;
cpp_context *initial_context = pfile->context;
+ if (pfile->state.in_directive == 3)
+ cpp_error (pfile, CPP_DL_ERROR, "'defined' in #embed parameter");
+
/* Don't expand macros. */
pfile->state.prevent_expansion++;
@@ -1356,7 +1359,9 @@ static const struct cpp_operator
};
/* Parse and evaluate a C expression, reading from PFILE.
- Returns the truth value of the expression.
+ Returns the truth value of the expression if OPEN_PAREN
+ is NULL, otherwise the low 64-bits of the result (when parsing
+ #embed/__has_embed parameters).
The implementation is an operator precedence parser, i.e. a
bottom-up parser, using a stack for not-yet-reduced tokens.
@@ -1366,8 +1371,9 @@ static const struct cpp_operator
recently pushed operator is 'top->op'. An operand (value) is
stored in the 'value' field of the stack element of the operator
that precedes it. */
-bool
-_cpp_parse_expr (cpp_reader *pfile, bool is_if)
+cpp_num_part
+_cpp_parse_expr (cpp_reader *pfile, const char *dir,
+ const cpp_token *open_paren)
{
struct op *top = pfile->op_stack;
unsigned int lex_count;
@@ -1384,6 +1390,14 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
/* Lowest priority operator prevents further reductions. */
top->op = CPP_EOF;
+ if (pfile->state.in_directive == 3)
+ {
+ ++top;
+ top->op = CPP_OPEN_PAREN;
+ top->token = open_paren;
+ top->loc = open_paren->src_loc;
+ }
+
for (;;)
{
struct op op;
@@ -1454,7 +1468,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
if (op.op == CPP_EOF && top->op == CPP_EOF)
SYNTAX_ERROR2_AT (op.loc,
- "%s with no expression", is_if ? "#if" : "#elif");
+ "%s with no expression", dir);
if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
SYNTAX_ERROR2_AT (op.loc,
@@ -1478,6 +1492,8 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
switch (op.op)
{
case CPP_CLOSE_PAREN:
+ if (pfile->state.in_directive == 3 && top == pfile->op_stack)
+ goto embed_done;
continue;
case CPP_OR_OR:
if (!num_zerop (top->value))
@@ -1520,12 +1536,31 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
if (top != pfile->op_stack)
{
cpp_error_with_line (pfile, CPP_DL_ICE, top->loc, 0,
- "unbalanced stack in %s",
- is_if ? "#if" : "#elif");
+ "unbalanced stack in %s", dir);
syntax_error:
return false; /* Return false on syntax error. */
}
+ if (pfile->state.in_directive == 3)
+ {
+ embed_done:
+ if (num_zerop (top->value))
+ return 0;
+ if (!top->value.unsignedp
+ && !num_positive (top->value, CPP_OPTION (pfile, precision)))
+ {
+ cpp_error_with_line (pfile, CPP_DL_ERROR, top->loc, 0,
+ "negative embed parameter operand");
+ return 1;
+ }
+ if (top->value.high)
+ {
+ cpp_error_with_line (pfile, CPP_DL_ERROR, top->loc, 0,
+ "too large embed parameter operand");
+ return 1;
+ }
+ return top->value.low;
+ }
return !num_zerop (top->value);
}
@@ -2079,7 +2114,9 @@ num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
if (CPP_PEDANTIC (pfile) && (!CPP_OPTION (pfile, c99)
|| !pfile->state.skip_eval))
cpp_pedwarning (pfile, CPP_W_PEDANTIC,
- "comma operator in operand of #if");
+ "comma operator in operand of #%s",
+ pfile->state.in_directive == 3
+ ? "embed" : "if");
lhs = rhs;
break;
}
@@ -2215,7 +2252,9 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
{
if (!pfile->state.skip_eval)
cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0,
- "division by zero in #if");
+ "division by zero in #%s",
+ pfile->state.in_directive == 3
+ ? "embed" : "if");
lhs.unsignedp = unsignedp;
return lhs;
}