/* Parse C expressions for cpplib.
- Copyright (C) 1987-2017 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994.
This program is free software; you can redistribute it and/or modify it
{
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. */
+ location_t loc; /* The location of this value. */
enum cpp_ttype op;
};
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,
- source_location);
+ location_t);
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 *);
-static cpp_num eval_token (cpp_reader *, const cpp_token *, source_location);
+static cpp_num eval_token (cpp_reader *, const cpp_token *, location_t);
static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype);
static unsigned int interpret_float_suffix (cpp_reader *, const uchar *, size_t);
static unsigned int interpret_int_suffix (cpp_reader *, const uchar *, size_t);
static void check_promotion (cpp_reader *, const struct op *);
-static cpp_num parse_has_include (cpp_reader *, enum include_type);
-
/* Token type abuse to create unary plus and minus operators. */
#define CPP_UPLUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 1))
#define CPP_UMINUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 2))
static unsigned int
interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
{
+ size_t orig_len = len;
+ const uchar *orig_s = s;
size_t flags;
size_t f, d, l, w, q, i, fn, fnx, fn_bits;
flags = 0;
f = d = l = w = q = i = fn = fnx = fn_bits = 0;
- /* The following decimal float suffixes, from TR 24732:2009 and TS
- 18661-2:2015, are supported:
+ /* The following decimal float suffixes, from TR 24732:2009, TS
+ 18661-2:2015 and C2X, are supported:
df, DF - _Decimal32.
dd, DD - _Decimal64.
if (fn && fn_bits == 96)
return 0;
- if (i && !CPP_OPTION (pfile, ext_numeric_literals))
- return 0;
+ if (i)
+ {
+ if (!CPP_OPTION (pfile, ext_numeric_literals))
+ return 0;
+
+ /* In C++14 and up these suffixes are in the standard library, so treat
+ them as user-defined literals. */
+ if (CPP_OPTION (pfile, cplusplus)
+ && CPP_OPTION (pfile, lang) > CLK_CXX11
+ && orig_s[0] == 'i'
+ && (orig_len == 1
+ || (orig_len == 2
+ && (orig_s[1] == 'f' || orig_s[1] == 'l'))))
+ return 0;
+ }
if ((w || q) && !CPP_OPTION (pfile, ext_numeric_literals))
return 0;
static unsigned int
interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
{
+ size_t orig_len = len;
size_t u, l, i;
u = l = i = 0;
if (l > 2 || u > 1 || i > 1)
return 0;
- if (i && !CPP_OPTION (pfile, ext_numeric_literals))
- return 0;
+ if (i)
+ {
+ if (!CPP_OPTION (pfile, ext_numeric_literals))
+ return 0;
+
+ /* In C++14 and up these suffixes are in the standard library, so treat
+ them as user-defined literals. */
+ if (CPP_OPTION (pfile, cplusplus)
+ && CPP_OPTION (pfile, lang) > CLK_CXX11
+ && s[0] == 'i'
+ && (orig_len == 1 || (orig_len == 2 && s[1] == 'l')))
+ return 0;
+ }
return ((i ? CPP_N_IMAGINARY : 0)
| (u ? CPP_N_UNSIGNED : 0)
VIRTUAL_LOCATION is the virtual location for TOKEN. */
unsigned int
cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
- const char **ud_suffix, source_location virtual_location)
+ const char **ud_suffix, location_t virtual_location)
{
const uchar *str = token->val.str.text;
const uchar *limit;
cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
"fixed-point constants are a GCC extension");
- if ((result & CPP_N_DFLOAT) && CPP_PEDANTIC (pfile))
- cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
- "decimal float constants are a GCC extension");
+ if (result & CPP_N_DFLOAT)
+ {
+ if (CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, dfp_constants))
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "decimal float constants are a C2X feature");
+ else if (CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) > 0)
+ cpp_warning_with_line (pfile, CPP_W_C11_C2X_COMPAT,
+ virtual_location, 0,
+ "decimal float constants are a C2X feature");
+ }
result |= CPP_N_FLOATING;
}
if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
"imaginary constants are a GCC extension");
- if (radix == 2
- && !CPP_OPTION (pfile, binary_constants)
- && CPP_PEDANTIC (pfile))
- cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
- CPP_OPTION (pfile, cplusplus)
- ? N_("binary constants are a C++14 feature "
- "or GCC extension")
- : N_("binary constants are a GCC extension"));
+ if (radix == 2)
+ {
+ if (!CPP_OPTION (pfile, binary_constants)
+ && CPP_PEDANTIC (pfile))
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ CPP_OPTION (pfile, cplusplus)
+ ? N_("binary constants are a C++14 feature "
+ "or GCC extension")
+ : N_("binary constants are a C2X feature "
+ "or GCC extension"));
+ else if (CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) > 0)
+ cpp_warning_with_line (pfile, CPP_W_C11_C2X_COMPAT,
+ virtual_location, 0,
+ "binary constants are a C2X feature");
+ }
if (radix == 10)
result |= CPP_N_DECIMAL;
}
}
+ bool is_defined = false;
if (node)
{
if ((pfile->context != initial_context
&& CPP_OPTION (pfile, warn_expansion_to_defined))
cpp_pedwarning (pfile, CPP_W_EXPANSION_TO_DEFINED,
"this use of \"defined\" may not be portable");
-
+ is_defined = _cpp_defined_macro_p (node);
+ if (!_cpp_maybe_notify_macro_use (pfile, node, token->src_loc))
+ /* It wasn't a macro after all. */
+ is_defined = false;
_cpp_mark_macro_used (node);
- if (!(node->flags & NODE_USED))
- {
- node->flags |= NODE_USED;
- if (node->type == NT_MACRO)
- {
- if ((node->flags & NODE_BUILTIN)
- && pfile->cb.user_builtin_macro)
- pfile->cb.user_builtin_macro (pfile, node);
- 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. */
pfile->state.prevent_expansion--;
/* Do not treat conditional macros as being defined. This is due to the
- powerpc and spu ports using conditional macros for 'vector', 'bool', and
- 'pixel' to act as conditional keywords. This messes up tests like #ifndef
+ powerpc port using conditional macros for 'vector', 'bool', and 'pixel'
+ to act as conditional keywords. This messes up tests like #ifndef
bool. */
result.unsignedp = false;
result.high = 0;
result.overflow = false;
- result.low = (node && node->type == NT_MACRO
- && (node->flags & NODE_CONDITIONAL) == 0);
+ result.low = is_defined;
return result;
}
operators). */
static cpp_num
eval_token (cpp_reader *pfile, const cpp_token *token,
- source_location virtual_location)
+ location_t virtual_location)
{
cpp_num result;
unsigned int temp;
case CPP_NAME:
if (token->val.node.node == pfile->spec_nodes.n_defined)
return parse_defined (pfile);
- else if (token->val.node.node == pfile->spec_nodes.n__has_include__)
- return parse_has_include (pfile, IT_INCLUDE);
- else if (token->val.node.node == pfile->spec_nodes.n__has_include_next__)
- return parse_has_include (pfile, IT_INCLUDE_NEXT);
else if (CPP_OPTION (pfile, cplusplus)
&& (token->val.node.node == pfile->spec_nodes.n_true
|| token->val.node.node == pfile->spec_nodes.n_false))
struct op *top = pfile->op_stack;
unsigned int lex_count;
bool saw_leading_not, want_value = true;
- source_location virtual_location = 0;
+ location_t virtual_location = 0;
pfile->state.skip_eval = 0;
static cpp_num
num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
- source_location location)
+ location_t location)
{
cpp_num result, sub;
cpp_num_part mask;
return lhs;
}
-/* Handle meeting "__has_include__" in a preprocessor expression. */
-static cpp_num
-parse_has_include (cpp_reader *pfile, enum include_type type)
-{
- cpp_num result;
- bool paren = false;
- cpp_hashnode *node = 0;
- const cpp_token *token;
- bool bracket = false;
- char *fname = 0;
-
- result.unsignedp = false;
- result.high = 0;
- result.overflow = false;
- result.low = 0;
-
- pfile->state.in__has_include__++;
-
- token = cpp_get_token (pfile);
- if (token->type == CPP_OPEN_PAREN)
- {
- paren = true;
- token = cpp_get_token (pfile);
- }
-
- if (token->type == CPP_STRING || token->type == CPP_HEADER_NAME)
- {
- if (token->type == CPP_HEADER_NAME)
- bracket = true;
- fname = XNEWVEC (char, token->val.str.len - 1);
- memcpy (fname, token->val.str.text + 1, token->val.str.len - 2);
- fname[token->val.str.len - 2] = '\0';
- node = token->val.node.node;
- }
- else if (token->type == CPP_LESS)
- {
- bracket = true;
- fname = _cpp_bracket_include (pfile);
- }
- else
- cpp_error (pfile, CPP_DL_ERROR,
- "operator \"__has_include__\" requires a header string");
-
- if (fname)
- {
- int angle_brackets = (bracket ? 1 : 0);
-
- if (_cpp_has_header (pfile, fname, angle_brackets, type))
- result.low = 1;
- else
- result.low = 0;
-
- XDELETEVEC (fname);
- }
-
- if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
- cpp_error (pfile, CPP_DL_ERROR,
- "missing ')' after \"__has_include__\"");
-
- /* A possible controlling macro of the form #if !__has_include__ ().
- _cpp_parse_expr checks there was no other junk on the line. */
- if (node)
- pfile->mi_ind_cmacro = node;
-
- pfile->state.in__has_include__--;
-
- return result;
-}