diff options
Diffstat (limited to 'libcpp/expr.cc')
-rw-r--r-- | libcpp/expr.cc | 55 |
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; } |