Commit 92936ecf by Zack Weinberg

cpplib.h (TTYPE_TABLE): Move CPP_MIN and CPP_MAX into block of operators allowed in #if...

	* cpplib.h (TTYPE_TABLE): Move CPP_MIN and CPP_MAX into block
	of operators allowed in #if and having an _EQ variant.  Add
	CPP_MIN_EQ, CPP_MAX_EQ, and CPP_DEFINED.
	(cpp_token flags): Add NAMED_OP.
	(enum node_type): Add T_OPERATOR.
	(struct cpp_hashnode): Add code slot to value union.
	* cpphash.h (spec_nodes): Remove n_defined.

	* cpplex.c (lex_line): Convert T_OPERATOR nodes to their proper types.
	(spell_token, can_paste, maybe_paste_with_next): Handle named operators.
	(is_macro_disabled): Tweak error messages.

	* cpplib.c (get_define_node): Disallow all named operators as
	macro names.  Tweak error messages.
	(_cpp_init_stacks): Don't set up spec_nodes->n_defined.

	* cppinit.c (builtin_array): Add entries for the named operators.
	* cppexp.c (lex): Check for CPP_DEFINED token.
	(priority table): Add entries for CPP_MIN and CPP_MAX.
	(_cpp_parse_expr): Handle CPP_MIN and CPP_MAX.

testsuite:
	* gcc.dg/cpp/directiv.c, gcc.dg/cpp/macsyntx.c,
	gcc.dg/cpp/undef1.c: Tweak error regexps.

From-SVN: r35137
parent b86db3eb
2000-07-19 Zack Weinberg <zack@wolery.cumb.org>
Implement C++ named operators.
* cpplib.h (TTYPE_TABLE): Move CPP_MIN and CPP_MAX into block
of operators allowed in #if and having an _EQ variant. Add
CPP_MIN_EQ, CPP_MAX_EQ, and CPP_DEFINED.
(cpp_token flags): Add NAMED_OP.
(enum node_type): Add T_OPERATOR.
(struct cpp_hashnode): Add code slot to value union.
* cpphash.h (spec_nodes): Remove n_defined.
* cpplex.c (lex_line): Convert T_OPERATOR nodes to their proper types.
(spell_token, can_paste, maybe_paste_with_next): Handle named operators.
(is_macro_disabled): Tweak error messages.
* cpplib.c (get_define_node): Disallow all named operators as
macro names. Tweak error messages.
(_cpp_init_stacks): Don't set up spec_nodes->n_defined.
* cppinit.c (builtin_array): Add entries for the named operators.
* cppexp.c (lex): Check for CPP_DEFINED token.
(priority table): Add entries for CPP_MIN and CPP_MAX.
(_cpp_parse_expr): Handle CPP_MIN and CPP_MAX.
2000-07-19 Bernd Schmidt <bernds@cygnus.co.uk> 2000-07-19 Bernd Schmidt <bernds@cygnus.co.uk>
* gcse.c (INSN_CUID): If ENABLE_CHECKING, abort if the uid is * gcse.c (INSN_CUID): If ENABLE_CHECKING, abort if the uid is
...@@ -24,7 +49,7 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org> ...@@ -24,7 +49,7 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org>
2000-07-18 Zack Weinberg <zack@wolery.cumb.org> 2000-07-18 Zack Weinberg <zack@wolery.cumb.org>
* cpplib.h (TTYPE_TABLE): Rearrange to use only two per-entry * cpplib.h (TTYPE_TABLE): Rearrange to use only two per-entry
macros, not five. macros, not five.
* cpphash.h (TOKEN_NAME): New macro. * cpphash.h (TOKEN_NAME): New macro.
(_cpp_spell_operator): Deleted. (_cpp_spell_operator): Deleted.
...@@ -38,7 +63,7 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org> ...@@ -38,7 +63,7 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org>
Use TOKEN_NAME and/or TOKEN_SPELL, do not reference Use TOKEN_NAME and/or TOKEN_SPELL, do not reference
token_spellings directly. token_spellings directly.
* cpplib.c: Use TOKEN_SPELL. * cpplib.c: Use TOKEN_SPELL.
* cpplex.c (_cpp_push_token): If the token being pushed back * cpplex.c (_cpp_push_token): If the token being pushed back
is the previous token in this context, just subtract one from is the previous token in this context, just subtract one from
context->posn. context->posn.
...@@ -62,20 +87,20 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org> ...@@ -62,20 +87,20 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org>
2000-07-17 Gabriel Dos Reis <gdr@codesourcery.com> 2000-07-17 Gabriel Dos Reis <gdr@codesourcery.com>
* diagnostic.h (report_diagnostic): Change prototype. * diagnostic.h (report_diagnostic): Change prototype.
* diagnostic.c (output_do_verbatim, diagnostic_for_asm, * diagnostic.c (output_do_verbatim, diagnostic_for_asm,
diagnostic_for_decl): Change prototype. diagnostic_for_decl): Change prototype.
(error_with_decl, warning_with_decl, pedwarn_with_decl, warning, (error_with_decl, warning_with_decl, pedwarn_with_decl, warning,
error, warning, error_with_file_and_line, error, warning, error_with_file_and_line,
warning_with_file_and_line, pedwarn_with_file_and_line, fatal): warning_with_file_and_line, pedwarn_with_file_and_line, fatal):
Adjust call to report_diagnostic, diagnostic_for_decl. Adjust call to report_diagnostic, diagnostic_for_decl.
(error_for_asm, warning_for_asm): Adjust call to diagnostic_for_asm. (error_for_asm, warning_for_asm): Adjust call to diagnostic_for_asm.
(output_verbatim, verbatim): Adjust call to output_do_verbatim. (output_verbatim, verbatim): Adjust call to output_do_verbatim.
* c-errors.c (pedwarn_c99): Adjust call to report_diagnostic. End * c-errors.c (pedwarn_c99): Adjust call to report_diagnostic. End
varaible argument list. varaible argument list.
2000-07-17 Zack Weinberg <zack@wolery.cumb.org> 2000-07-17 Zack Weinberg <zack@wolery.cumb.org>
* cpphash.c: Don't include hashtab.h. Most macro-handling code * cpphash.c: Don't include hashtab.h. Most macro-handling code
...@@ -87,7 +112,7 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org> ...@@ -87,7 +112,7 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org>
Vlad's expandable hash table. Vlad's expandable hash table.
(cpp_lookup): Use new functions. (cpp_lookup): Use new functions.
(_cpp_init_macros, _cpp_cleanup_macros): Adjust for new (_cpp_init_macros, _cpp_cleanup_macros): Adjust for new
implementation. implementation.
* cppmacro.c: New file. * cppmacro.c: New file.
* cppinit.c (dump_macros_helper): New. * cppinit.c (dump_macros_helper): New.
(cpp_finish): Iterate over the identifier table directly. (cpp_finish): Iterate over the identifier table directly.
...@@ -112,7 +137,7 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org> ...@@ -112,7 +137,7 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org>
2000-07-17 Geoffrey Keating <geoffk@cygnus.com> 2000-07-17 Geoffrey Keating <geoffk@cygnus.com>
* configure: Regenerate. * configure: Regenerate.
* extend.texi (Extended Asm): Mention that a memory clobber * extend.texi (Extended Asm): Mention that a memory clobber
does not count as a side-effect. does not count as a side-effect.
...@@ -156,7 +181,7 @@ Mon Jul 17 23:43:26 MET DST 2000 Jan Hubicka <jh@suse.cz> ...@@ -156,7 +181,7 @@ Mon Jul 17 23:43:26 MET DST 2000 Jan Hubicka <jh@suse.cz>
2000-07-17 Chandrakala Chavva <cchavva@cygnus.com> 2000-07-17 Chandrakala Chavva <cchavva@cygnus.com>
* loop.c (check_dbra_loop) : Return if more than one condition is * loop.c (check_dbra_loop) : Return if more than one condition is
present to control the loop. present to control the loop.
Mon Jul 17 08:26:35 2000 Clinton Popetz <cpopetz@cygnus.com> Mon Jul 17 08:26:35 2000 Clinton Popetz <cpopetz@cygnus.com>
...@@ -284,7 +309,7 @@ Mon Jul 17 02:37:06 2000 Marc Espie <espie@openbsd.org> ...@@ -284,7 +309,7 @@ Mon Jul 17 02:37:06 2000 Marc Espie <espie@openbsd.org>
2000-07-15 Gabriel Dos Reis <gdr@codesourcery.com> 2000-07-15 Gabriel Dos Reis <gdr@codesourcery.com>
* diagnostic.c (doing_line_wrapping, line_wrapper_printf, notice, * diagnostic.c (doing_line_wrapping, line_wrapper_printf, notice,
v_error_with_decl, v_warning_with_decl, v_pedwarn_with_decl): Remove. v_error_with_decl, v_warning_with_decl, v_pedwarn_with_decl): Remove.
(v_message_with_decl): Rename to ... (v_message_with_decl): Rename to ...
(format_with_decl): ... this. Tweak (format_with_decl): ... this. Tweak
(diagnostic_for_decl): New function. (diagnostic_for_decl): New function.
...@@ -292,14 +317,14 @@ Mon Jul 17 02:37:06 2000 Marc Espie <espie@openbsd.org> ...@@ -292,14 +317,14 @@ Mon Jul 17 02:37:06 2000 Marc Espie <espie@openbsd.org>
(announce_function): Use verbatim. (announce_function): Use verbatim.
(default_print_error_function): Likewise. (default_print_error_function): Likewise.
(error_with_decl, warning_with_decl, pedwarn_with_decl): Use new (error_with_decl, warning_with_decl, pedwarn_with_decl): Use new
infratructure. infratructure.
2000-07-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2000-07-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* mips.c (function_arg_pass_by_reference): Don't do automatic * mips.c (function_arg_pass_by_reference): Don't do automatic
aggregate initialization. aggregate initialization.
(machine_dependent_reorg): Initialize variable `mode'. (machine_dependent_reorg): Initialize variable `mode'.
* mips.md (absdi2): Change variable `regno1' to unsigned int. * mips.md (absdi2): Change variable `regno1' to unsigned int.
(reload_indi): Rename loword/hiword to lo_word/hi_word to avoid (reload_indi): Rename loword/hiword to lo_word/hi_word to avoid
conflicts with sys/param.h macro of the same name. conflicts with sys/param.h macro of the same name.
...@@ -337,7 +362,7 @@ Fri Jul 14 18:13:53 2000 Mark P Mitchell <mark@codesourcery.com> ...@@ -337,7 +362,7 @@ Fri Jul 14 18:13:53 2000 Mark P Mitchell <mark@codesourcery.com>
2000-07-14 Jason Merrill <jason@redhat.com> 2000-07-14 Jason Merrill <jason@redhat.com>
* dwarf2out.c (dwarf2out_frame_debug_expr): If we store the CFA * dwarf2out.c (dwarf2out_frame_debug_expr): If we store the CFA
register in the stack and later in another register, use the new register in the stack and later in another register, use the new
register. register.
...@@ -358,7 +383,7 @@ Fri Jul 14 10:25:53 2000 Clinton Popetz <cpopetz@cygnus.com> ...@@ -358,7 +383,7 @@ Fri Jul 14 10:25:53 2000 Clinton Popetz <cpopetz@cygnus.com>
* .cvsignore: Add generated YACC files. * .cvsignore: Add generated YACC files.
* objc/.cvsignore: New file. * objc/.cvsignore: New file.
2000-07-14 Neil Booth <NeilB@earthling.net> 2000-07-14 Neil Booth <NeilB@earthling.net>
* cpplex.c (adjust_column): New funcion. * cpplex.c (adjust_column): New funcion.
...@@ -421,14 +446,14 @@ Fri Jul 14 10:25:53 2000 Clinton Popetz <cpopetz@cygnus.com> ...@@ -421,14 +446,14 @@ Fri Jul 14 10:25:53 2000 Clinton Popetz <cpopetz@cygnus.com>
error_with_file_and_line, warning_with_file_and_line, sorry, error_with_file_and_line, warning_with_file_and_line, sorry,
error_for_asm, warning_for_asm, fatal): Reimplement. error_for_asm, warning_for_asm, fatal): Reimplement.
(finish_diagnostic): Clear diagnostic info as well. (finish_diagnostic): Clear diagnostic info as well.
2000-07-13 Neil Booth <NeilB@earthling.net> 2000-07-13 Neil Booth <NeilB@earthling.net>
* c-common.h (flag_digraphs): New. * c-common.h (flag_digraphs): New.
* c-decl.c (c_decode_option): Set flag_digraphs as appropriate. * c-decl.c (c_decode_option): Set flag_digraphs as appropriate.
* c-lex.c (yylex): Use flag_digraphs to decide whether to * c-lex.c (yylex): Use flag_digraphs to decide whether to
honour digraphs. honour digraphs.
2000-07-13 Zack Weinberg <zack@wolery.cumb.org> 2000-07-13 Zack Weinberg <zack@wolery.cumb.org>
* gcc.c (do_spec_1): Add new %B operator. * gcc.c (do_spec_1): Add new %B operator.
...@@ -446,7 +471,7 @@ Fri Jul 14 10:25:53 2000 Clinton Popetz <cpopetz@cygnus.com> ...@@ -446,7 +471,7 @@ Fri Jul 14 10:25:53 2000 Clinton Popetz <cpopetz@cygnus.com>
named specs. named specs.
(C and assembly specs): Use the new named specs, as appropriate. (C and assembly specs): Use the new named specs, as appropriate.
* objc/lang-specs.h: Use the new named specs. * objc/lang-specs.h: Use the new named specs.
Remove unnecessary braces. Remove unnecessary braces.
2000-07-12 Zack Weinberg <zack@wolery.cumb.org> 2000-07-12 Zack Weinberg <zack@wolery.cumb.org>
......
...@@ -419,10 +419,10 @@ lex (pfile, skip_evaluation) ...@@ -419,10 +419,10 @@ lex (pfile, skip_evaluation)
else else
SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", tok->val.aux); SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", tok->val.aux);
case CPP_NAME: case CPP_DEFINED:
if (tok->val.node == pfile->spec_nodes->n_defined) return parse_defined (pfile);
return parse_defined (pfile);
case CPP_NAME:
op.op = CPP_INT; op.op = CPP_INT;
op.unsignedp = 0; op.unsignedp = 0;
op.value = 0; op.value = 0;
...@@ -648,12 +648,13 @@ be handled with operator-specific code. */ ...@@ -648,12 +648,13 @@ be handled with operator-specific code. */
#define OR_PRIO (8 << PRIO_SHIFT) #define OR_PRIO (8 << PRIO_SHIFT)
#define XOR_PRIO (9 << PRIO_SHIFT) #define XOR_PRIO (9 << PRIO_SHIFT)
#define AND_PRIO (10 << PRIO_SHIFT) #define AND_PRIO (10 << PRIO_SHIFT)
#define EQUAL_PRIO (11 << PRIO_SHIFT) #define MINMAX_PRIO (11 << PRIO_SHIFT)
#define LESS_PRIO (12 << PRIO_SHIFT) #define EQUAL_PRIO (12 << PRIO_SHIFT)
#define SHIFT_PRIO (13 << PRIO_SHIFT) #define LESS_PRIO (13 << PRIO_SHIFT)
#define PLUS_PRIO (14 << PRIO_SHIFT) #define SHIFT_PRIO (14 << PRIO_SHIFT)
#define MUL_PRIO (15 << PRIO_SHIFT) #define PLUS_PRIO (15 << PRIO_SHIFT)
#define UNARY_PRIO ((16 << PRIO_SHIFT) | RIGHT_ASSOC | NO_L_OPERAND) #define MUL_PRIO (16 << PRIO_SHIFT)
#define UNARY_PRIO ((17 << PRIO_SHIFT) | RIGHT_ASSOC | NO_L_OPERAND)
/* Operator to priority map. Must be in the same order as the first /* Operator to priority map. Must be in the same order as the first
N entries of enum cpp_ttype. */ N entries of enum cpp_ttype. */
...@@ -674,6 +675,8 @@ op_to_prio[] = ...@@ -674,6 +675,8 @@ op_to_prio[] =
/* XOR */ XOR_PRIO, /* XOR */ XOR_PRIO,
/* RSHIFT */ SHIFT_PRIO, /* RSHIFT */ SHIFT_PRIO,
/* LSHIFT */ SHIFT_PRIO, /* LSHIFT */ SHIFT_PRIO,
/* MIN */ MINMAX_PRIO, /* C++ specific */
/* MAX */ MINMAX_PRIO, /* extensions */
/* COMPL */ UNARY_PRIO, /* COMPL */ UNARY_PRIO,
/* AND_AND */ ANDAND_PRIO, /* AND_AND */ ANDAND_PRIO,
...@@ -700,6 +703,9 @@ op_to_prio[] = ...@@ -700,6 +703,9 @@ op_to_prio[] =
#define BITWISE(OP) \ #define BITWISE(OP) \
top->value = v1 OP v2; \ top->value = v1 OP v2; \
top->unsignedp = unsigned1 | unsigned2; top->unsignedp = unsigned1 | unsigned2;
#define MINMAX(OP) \
top->value = (v1 OP v2) ? v1 : v2; \
top->unsignedp = unsigned1 | unsigned2;
#define UNARY(OP) \ #define UNARY(OP) \
top->value = OP v2; \ top->value = OP v2; \
top->unsignedp = unsigned2; \ top->unsignedp = unsigned2; \
...@@ -831,6 +837,8 @@ _cpp_parse_expr (pfile) ...@@ -831,6 +837,8 @@ _cpp_parse_expr (pfile)
case CPP_OR: BITWISE(|); break; case CPP_OR: BITWISE(|); break;
case CPP_LSHIFT: SHIFT(left_shift, right_shift); break; case CPP_LSHIFT: SHIFT(left_shift, right_shift); break;
case CPP_RSHIFT: SHIFT(right_shift, left_shift); break; case CPP_RSHIFT: SHIFT(right_shift, left_shift); break;
case CPP_MIN: MINMAX(<); break;
case CPP_MAX: MINMAX(>); break;
case CPP_PLUS: case CPP_PLUS:
if (!(top->flags & HAVE_VALUE)) if (!(top->flags & HAVE_VALUE))
......
...@@ -124,7 +124,6 @@ struct include_file ...@@ -124,7 +124,6 @@ struct include_file
struct spec_nodes struct spec_nodes
{ {
cpp_hashnode *n_L; /* L"str" */ cpp_hashnode *n_L; /* L"str" */
cpp_hashnode *n_defined; /* #if defined */
cpp_hashnode *n__STRICT_ANSI__; /* STDC_0_IN_SYSTEM_HEADERS */ cpp_hashnode *n__STRICT_ANSI__; /* STDC_0_IN_SYSTEM_HEADERS */
cpp_hashnode *n__CHAR_UNSIGNED__; /* plain char is unsigned */ cpp_hashnode *n__CHAR_UNSIGNED__; /* plain char is unsigned */
cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */ cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */
......
...@@ -491,26 +491,33 @@ cpp_cleanup (pfile) ...@@ -491,26 +491,33 @@ cpp_cleanup (pfile)
/* This structure defines one built-in macro. A node of type TYPE will /* This structure defines one built-in macro. A node of type TYPE will
be entered in the macro hash table under the name NAME, with value be entered in the macro hash table under the name NAME, with value
VALUE (if any). Two values are not compile time constants, so we tag VALUE (if any). If TYPE is T_OPERATOR, the CODE field is used instead.
Two values are not compile time constants, so we tag
them in the FLAGS field instead: them in the FLAGS field instead:
VERS value is the global version_string, quoted VERS value is the global version_string, quoted
ULP value is the global user_label_prefix ULP value is the global user_label_prefix
Also, macros with CPLUS set in the flags field are entered only for C++.
*/ */
struct builtin struct builtin
{ {
const U_CHAR *name; const U_CHAR *name;
const char *value; const char *value;
unsigned short type; unsigned char code;
unsigned char type;
unsigned short flags; unsigned short flags;
unsigned int len; unsigned int len;
}; };
#define VERS 0x01 #define VERS 0x01
#define ULP 0x02 #define ULP 0x02
#define CPLUS 0x04
#define B(n, t) { U n, 0, t, 0, sizeof n - 1 }
#define C(n, v) { U n, v, T_MACRO, 0, sizeof n - 1 } #define B(n, t) { U n, 0, 0, t, 0, sizeof n - 1 }
#define X(n, f) { U n, 0, T_MACRO, f, sizeof n - 1 } #define C(n, v) { U n, v, 0, T_MACRO, 0, sizeof n - 1 }
#define X(n, f) { U n, 0, 0, T_MACRO, f, sizeof n - 1 }
#define O(n, c, f) { U n, 0, c, T_OPERATOR, f, sizeof n - 1 }
static const struct builtin builtin_array[] = static const struct builtin builtin_array[] =
{ {
B("__TIME__", T_TIME), B("__TIME__", T_TIME),
...@@ -534,6 +541,23 @@ static const struct builtin builtin_array[] = ...@@ -534,6 +541,23 @@ static const struct builtin builtin_array[] =
#ifndef NO_BUILTIN_WCHAR_TYPE #ifndef NO_BUILTIN_WCHAR_TYPE
C("__WCHAR_TYPE__", WCHAR_TYPE), C("__WCHAR_TYPE__", WCHAR_TYPE),
#endif #endif
/* Named operators known to the preprocessor. These cannot be #defined
and always have their stated meaning. They are treated like normal
string tokens except for the type code and the meaning. Most of them
are only for C++ (but see iso646.h). */
O("defined", CPP_DEFINED, 0),
O("and", CPP_AND_AND, CPLUS),
O("and_eq", CPP_AND_EQ, CPLUS),
O("bitand", CPP_AND, CPLUS),
O("bitor", CPP_OR, CPLUS),
O("compl", CPP_COMPL, CPLUS),
O("not", CPP_NOT, CPLUS),
O("not_eq", CPP_NOT_EQ, CPLUS),
O("or", CPP_OR_OR, CPLUS),
O("or_eq", CPP_OR_EQ, CPLUS),
O("xor", CPP_XOR, CPLUS),
O("xor_eq", CPP_XOR_EQ, CPLUS),
}; };
#undef B #undef B
#undef C #undef C
...@@ -550,6 +574,9 @@ initialize_builtins (pfile) ...@@ -550,6 +574,9 @@ initialize_builtins (pfile)
const struct builtin *b; const struct builtin *b;
for(b = builtin_array; b < builtin_array_end; b++) for(b = builtin_array; b < builtin_array_end; b++)
{ {
if (b->flags & CPLUS && ! CPP_OPTION (pfile, cplusplus))
continue;
if (b->type == T_MACRO) if (b->type == T_MACRO)
{ {
const char *val; const char *val;
...@@ -578,6 +605,8 @@ initialize_builtins (pfile) ...@@ -578,6 +605,8 @@ initialize_builtins (pfile)
{ {
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len); cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
hp->type = b->type; hp->type = b->type;
if (b->type == T_OPERATOR)
hp->value.code = b->code;
} }
} }
} }
......
...@@ -1460,6 +1460,13 @@ lex_line (pfile, list) ...@@ -1460,6 +1460,13 @@ lex_line (pfile, list)
list->directive = _cpp_check_directive (pfile, cur_token, list->directive = _cpp_check_directive (pfile, cur_token,
!(list->tokens[0].flags !(list->tokens[0].flags
& PREV_WHITE)); & PREV_WHITE));
/* Convert named operators to their proper types. */
if (cur_token->val.node->type == T_OPERATOR)
{
cur_token->flags |= NAMED_OP;
cur_token->type = cur_token->val.node->value.code;
}
cur_token++; cur_token++;
break; break;
...@@ -1860,8 +1867,8 @@ lex_line (pfile, list) ...@@ -1860,8 +1867,8 @@ lex_line (pfile, list)
&& cur_token > first + 1 && !CPP_OPTION (pfile, lang_asm)) && cur_token > first + 1 && !CPP_OPTION (pfile, lang_asm))
{ {
if (first[1].type == CPP_NAME) if (first[1].type == CPP_NAME)
cpp_error (pfile, "invalid preprocessing directive #%.*s", cpp_error (pfile, "invalid preprocessing directive #%s",
(int) first[1].val.node->length, first[1].val.node->name); first[1].val.node->name);
else else
cpp_error (pfile, "invalid preprocessing directive"); cpp_error (pfile, "invalid preprocessing directive");
} }
...@@ -1954,6 +1961,8 @@ spell_token (pfile, token, buffer) ...@@ -1954,6 +1961,8 @@ spell_token (pfile, token, buffer)
if (token->flags & DIGRAPH) if (token->flags & DIGRAPH)
spelling = digraph_spellings[token->type - CPP_FIRST_DIGRAPH]; spelling = digraph_spellings[token->type - CPP_FIRST_DIGRAPH];
else if (token->flags & NAMED_OP)
goto spell_ident;
else else
spelling = TOKEN_NAME (token); spelling = TOKEN_NAME (token);
...@@ -1963,6 +1972,7 @@ spell_token (pfile, token, buffer) ...@@ -1963,6 +1972,7 @@ spell_token (pfile, token, buffer)
break; break;
case SPELL_IDENT: case SPELL_IDENT:
spell_ident:
memcpy (buffer, token->val.node->name, token->val.node->length); memcpy (buffer, token->val.node->name, token->val.node->length);
buffer += token->val.node->length; buffer += token->val.node->length;
break; break;
...@@ -2245,8 +2255,8 @@ is_macro_disabled (pfile, expansion, token) ...@@ -2245,8 +2255,8 @@ is_macro_disabled (pfile, expansion, token)
_cpp_push_token (pfile, next); _cpp_push_token (pfile, next);
if (CPP_WTRADITIONAL (pfile)) if (CPP_WTRADITIONAL (pfile))
cpp_warning (pfile, cpp_warning (pfile,
"function macro %.*s must be used with arguments in traditional C", "function macro %s must be used with arguments in traditional C",
(int) token->val.node->length, token->val.node->name); token->val.node->name);
return 1; return 1;
} }
} }
...@@ -2379,8 +2389,7 @@ parse_args (pfile, hp, args) ...@@ -2379,8 +2389,7 @@ parse_args (pfile, hp, args)
if (token->type == CPP_EOF) if (token->type == CPP_EOF)
{ {
cpp_error (pfile, "unterminated invocation of macro \"%.*s\"", cpp_error(pfile, "unterminated argument list for macro \"%s\"", hp->name);
hp->length, hp->name);
return 1; return 1;
} }
else if (argc < macro->paramc) else if (argc < macro->paramc)
...@@ -2401,9 +2410,7 @@ parse_args (pfile, hp, args) ...@@ -2401,9 +2410,7 @@ parse_args (pfile, hp, args)
} }
else else
{ {
cpp_error (pfile, cpp_error (pfile, "not enough arguments for macro \"%s\"", hp->name);
"insufficient arguments in invocation of macro \"%.*s\"",
hp->length, hp->name);
return 1; return 1;
} }
} }
...@@ -2411,9 +2418,7 @@ parse_args (pfile, hp, args) ...@@ -2411,9 +2418,7 @@ parse_args (pfile, hp, args)
else if (argc > macro->paramc else if (argc > macro->paramc
&& !(macro->paramc == 0 && argc == 1 && empty_argument (args, 0))) && !(macro->paramc == 0 && argc == 1 && empty_argument (args, 0)))
{ {
cpp_error (pfile, cpp_error (pfile, "too many arguments for macro \"%s\"", hp->name);
"too many arguments in invocation of macro \"%.*s\"",
hp->length, hp->name);
return 1; return 1;
} }
...@@ -2583,6 +2588,12 @@ can_paste (pfile, token1, token2, digraph) ...@@ -2583,6 +2588,12 @@ can_paste (pfile, token1, token2, digraph)
enum cpp_ttype a = token1->type, b = token2->type; enum cpp_ttype a = token1->type, b = token2->type;
int cxx = CPP_OPTION (pfile, cplusplus); int cxx = CPP_OPTION (pfile, cplusplus);
/* Treat named operators as if they were ordinary NAMEs. */
if (token1->flags & NAMED_OP)
a = CPP_NAME;
if (token2->flags & NAMED_OP)
b = CPP_NAME;
if (a <= CPP_LAST_EQ && b == CPP_EQ) if (a <= CPP_LAST_EQ && b == CPP_EQ)
return a + (CPP_EQ_EQ - CPP_EQ); return a + (CPP_EQ_EQ - CPP_EQ);
...@@ -2756,6 +2767,12 @@ maybe_paste_with_next (pfile, token) ...@@ -2756,6 +2767,12 @@ maybe_paste_with_next (pfile, token)
pasted->type = type; pasted->type = type;
pasted->flags = digraph ? DIGRAPH : 0; pasted->flags = digraph ? DIGRAPH : 0;
if (type == CPP_NAME && pasted->val.node->type == T_OPERATOR)
{
pasted->type = pasted->val.node->value.code;
pasted->flags |= NAMED_OP;
}
} }
/* The pasted token gets the whitespace flags and position of the /* The pasted token gets the whitespace flags and position of the
...@@ -3101,11 +3118,11 @@ _cpp_get_token (pfile) ...@@ -3101,11 +3118,11 @@ _cpp_get_token (pfile)
token = maybe_paste_with_next (pfile, token); token = maybe_paste_with_next (pfile, token);
/* If it isn't a macro, return it now. */ /* If it isn't a macro, return it now. */
if (token->type != CPP_NAME if (token->type != CPP_NAME || token->val.node->type == T_VOID)
|| token->val.node->type == T_VOID)
return token; return token;
/* Is macro expansion disabled in general? */ /* Is macro expansion disabled in general, or are we in the
middle of a token paste? */
if (pfile->no_expand_level == pfile->cur_context || pfile->paste_level) if (pfile->no_expand_level == pfile->cur_context || pfile->paste_level)
return token; return token;
......
...@@ -236,39 +236,42 @@ static cpp_hashnode * ...@@ -236,39 +236,42 @@ static cpp_hashnode *
get_define_node (pfile) get_define_node (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_hashnode *node;
const cpp_token *token; const cpp_token *token;
/* Skip any -C comments. */ /* Skip any -C comments. */
while ((token = _cpp_get_token (pfile))->type == CPP_COMMENT) while ((token = _cpp_get_token (pfile))->type == CPP_COMMENT)
; ;
/* The token immediately after #define must be an identifier. That
identifier is not allowed to be "defined". See predefined macro
names (6.10.8.4). In C++, it is not allowed to be any of the
<iso646.h> macro names (which are keywords in C++) either. */
if (token->type != CPP_NAME) if (token->type != CPP_NAME)
{ {
cpp_error_with_line (pfile, token->line, token->col, if (token->type == CPP_DEFINED)
cpp_error_with_line (pfile, token->line, token->col,
"\"defined\" cannot be used as a macro name");
else if (token->flags & NAMED_OP)
cpp_error_with_line (pfile, token->line, token->col,
"\"%s\" cannot be used as a macro name in C++",
token->val.node->name);
else
cpp_error_with_line (pfile, token->line, token->col,
"macro names must be identifiers"); "macro names must be identifiers");
return 0; return 0;
} }
/* That identifier is not allowed to be "defined". See predefined
macro names (6.10.8.4). */
node = token->val.node;
if (node == pfile->spec_nodes->n_defined)
{
cpp_error_with_line (pfile, pfile->token_list.line, token->col,
"\"defined\" is not a legal macro name");
return 0;
}
/* Check for poisoned identifiers now. */ /* Check for poisoned identifiers now. */
if (node->type == T_POISON) if (token->val.node->type == T_POISON)
{ {
cpp_error (pfile, "attempt to use poisoned \"%s\"", node->name); cpp_error_with_line (pfile, token->line, token->col,
"attempt to use poisoned \"%s\"",
token->val.node->name);
return 0; return 0;
} }
return node; return token->val.node;
} }
/* Process a #define command. */ /* Process a #define command. */
...@@ -876,8 +879,8 @@ do_pragma_dependency (pfile) ...@@ -876,8 +879,8 @@ do_pragma_dependency (pfile)
_cpp_dump_list (pfile, &pfile->token_list, msg, 0); _cpp_dump_list (pfile, &pfile->token_list, msg, 0);
limit = pfile->limit; limit = pfile->limit;
pfile->limit = text; pfile->limit = text;
/* There must be something non-whitespace after. */
while (*text == ' ') while (*text == ' ')
/* There must be something non-whitespace after. */
text++; text++;
cpp_warning (pfile, "%.*s", (int)(limit - text), text); cpp_warning (pfile, "%.*s", (int)(limit - text), text);
} }
...@@ -915,8 +918,7 @@ detect_if_not_defined (pfile) ...@@ -915,8 +918,7 @@ detect_if_not_defined (pfile)
return 0; return 0;
token++; token++;
if (token->type != CPP_NAME if (token->type != CPP_DEFINED)
|| token->val.node != pfile->spec_nodes->n_defined)
return 0; return 0;
token++; token++;
...@@ -1338,8 +1340,7 @@ do_assert (pfile) ...@@ -1338,8 +1340,7 @@ do_assert (pfile)
return; return;
err: err:
cpp_warning (pfile, "\"%.*s\" re-asserted", cpp_warning (pfile, "\"%s\" re-asserted", node->name + 1);
node->length - 1, node->name + 1);
FREE_ANSWER (new_answer); FREE_ANSWER (new_answer);
} }
...@@ -1535,7 +1536,6 @@ _cpp_init_stacks (pfile) ...@@ -1535,7 +1536,6 @@ _cpp_init_stacks (pfile)
/* Perhaps not the ideal place to put this. */ /* Perhaps not the ideal place to put this. */
pfile->spec_nodes = s = xnew (struct spec_nodes); pfile->spec_nodes = s = xnew (struct spec_nodes);
s->n_L = cpp_lookup (pfile, DSC("L")); s->n_L = cpp_lookup (pfile, DSC("L"));
s->n_defined = cpp_lookup (pfile, DSC("defined"));
s->n__STRICT_ANSI__ = cpp_lookup (pfile, DSC("__STRICT_ANSI__")); s->n__STRICT_ANSI__ = cpp_lookup (pfile, DSC("__STRICT_ANSI__"));
s->n__CHAR_UNSIGNED__ = cpp_lookup (pfile, DSC("__CHAR_UNSIGNED__")); s->n__CHAR_UNSIGNED__ = cpp_lookup (pfile, DSC("__CHAR_UNSIGNED__"));
s->n__VA_ARGS__ = cpp_lookup (pfile, DSC("__VA_ARGS__")); s->n__VA_ARGS__ = cpp_lookup (pfile, DSC("__VA_ARGS__"));
......
...@@ -64,6 +64,8 @@ typedef struct cpp_hashnode cpp_hashnode; ...@@ -64,6 +64,8 @@ typedef struct cpp_hashnode cpp_hashnode;
OP(CPP_XOR, "^") \ OP(CPP_XOR, "^") \
OP(CPP_RSHIFT, ">>") \ OP(CPP_RSHIFT, ">>") \
OP(CPP_LSHIFT, "<<") \ OP(CPP_LSHIFT, "<<") \
OP(CPP_MIN, "<?") /* extension */ \
OP(CPP_MAX, ">?") \
\ \
OP(CPP_COMPL, "~") \ OP(CPP_COMPL, "~") \
OP(CPP_AND_AND, "&&") /* logical */ \ OP(CPP_AND_AND, "&&") /* logical */ \
...@@ -88,6 +90,8 @@ typedef struct cpp_hashnode cpp_hashnode; ...@@ -88,6 +90,8 @@ typedef struct cpp_hashnode cpp_hashnode;
OP(CPP_XOR_EQ, "^=") \ OP(CPP_XOR_EQ, "^=") \
OP(CPP_RSHIFT_EQ, ">>=") \ OP(CPP_RSHIFT_EQ, ">>=") \
OP(CPP_LSHIFT_EQ, "<<=") \ OP(CPP_LSHIFT_EQ, "<<=") \
OP(CPP_MIN_EQ, "<?=") /* extension */ \
OP(CPP_MAX_EQ, ">?=") \
/* Digraphs together, beginning with CPP_FIRST_DIGRAPH. */ \ /* Digraphs together, beginning with CPP_FIRST_DIGRAPH. */ \
OP(CPP_HASH, "#") /* digraphs */ \ OP(CPP_HASH, "#") /* digraphs */ \
OP(CPP_PASTE, "##") \ OP(CPP_PASTE, "##") \
...@@ -106,8 +110,7 @@ typedef struct cpp_hashnode cpp_hashnode; ...@@ -106,8 +110,7 @@ typedef struct cpp_hashnode cpp_hashnode;
OP(CPP_SCOPE, "::") \ OP(CPP_SCOPE, "::") \
OP(CPP_DEREF_STAR, "->*") \ OP(CPP_DEREF_STAR, "->*") \
OP(CPP_DOT_STAR, ".*") \ OP(CPP_DOT_STAR, ".*") \
OP(CPP_MIN, "<?") /* extension */ \ OP(CPP_DEFINED, "defined") /* #if */ \
OP(CPP_MAX, ">?") \
\ \
TK(CPP_NAME, SPELL_IDENT) /* word */ \ TK(CPP_NAME, SPELL_IDENT) /* word */ \
TK(CPP_INT, SPELL_STRING) /* 23 */ \ TK(CPP_INT, SPELL_STRING) /* 23 */ \
...@@ -147,10 +150,11 @@ struct cpp_string ...@@ -147,10 +150,11 @@ struct cpp_string
/* Flags for the cpp_token structure. */ /* Flags for the cpp_token structure. */
#define PREV_WHITE (1 << 0) /* If whitespace before this token. */ #define PREV_WHITE (1 << 0) /* If whitespace before this token. */
#define BOL (1 << 1) /* Beginning of logical line. */ #define BOL (1 << 1) /* Beginning of logical line. */
#define DIGRAPH (1 << 2) /* If it was a digraph. */ #define DIGRAPH (1 << 2) /* If it was a digraph. */
#define STRINGIFY_ARG (1 << 3) /* If macro argument to be stringified. */ #define STRINGIFY_ARG (1 << 3) /* If macro argument to be stringified. */
#define PASTE_LEFT (1 << 4) /* If on LHS of a ## operator. */ #define PASTE_LEFT (1 << 4) /* If on LHS of a ## operator. */
#define PASTED (1 << 5) /* The result of a ## operator. */ #define PASTED (1 << 5) /* The result of a ## operator. */
#define NAMED_OP (1 << 6) /* C++ named operators, also defined */
/* A preprocessing token. This has been carefully packed and should /* A preprocessing token. This has been carefully packed and should
occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */ occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */
...@@ -603,6 +607,7 @@ enum node_type ...@@ -603,6 +607,7 @@ enum node_type
T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */ T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
T_TIME, /* `__TIME__' */ T_TIME, /* `__TIME__' */
T_STDC, /* `__STDC__' */ T_STDC, /* `__STDC__' */
T_OPERATOR, /* operator with a name; val.code is token type */
T_POISON, /* poisoned identifier */ T_POISON, /* poisoned identifier */
T_MACRO, /* a macro, either object-like or function-like */ T_MACRO, /* a macro, either object-like or function-like */
T_ASSERTION /* predicate for #assert */ T_ASSERTION /* predicate for #assert */
...@@ -624,6 +629,7 @@ struct cpp_hashnode ...@@ -624,6 +629,7 @@ struct cpp_hashnode
{ {
const cpp_toklist *expansion; /* a macro's replacement list. */ const cpp_toklist *expansion; /* a macro's replacement list. */
struct answer *answers; /* answers to an assertion. */ struct answer *answers; /* answers to an assertion. */
enum cpp_ttype code; /* code for a named operator. */
} value; } value;
union tree_node *fe_value; /* front end value */ union tree_node *fe_value; /* front end value */
......
...@@ -28,7 +28,7 @@ EMPTY #define bar ...@@ -28,7 +28,7 @@ EMPTY #define bar
/* Check that directives always start a line, even if in middle of /* Check that directives always start a line, even if in middle of
macro expansion. */ macro expansion. */
#define func(x) x #define func(x) x
func (2 /* { dg-error "unterminated invocation" } */ func (2 /* { dg-error "unterminated argument" } */
#define foobar /* { dg-error "may not be used inside" } */ #define foobar /* { dg-error "may not be used inside" } */
/* For tidiness, I think the directive should still be processed /* For tidiness, I think the directive should still be processed
...@@ -43,5 +43,5 @@ func (2 /* { dg-error "unterminated invocation" } */ ...@@ -43,5 +43,5 @@ func (2 /* { dg-error "unterminated invocation" } */
Note that the #if is still treated as a conditional, so there Note that the #if is still treated as a conditional, so there
should be no errors about #endif without #if. */ should be no errors about #endif without #if. */
#if func ( /* { dg-error "unterminated invocation" } */ #if func ( /* { dg-error "unterminated argument" } */
#endif #endif
...@@ -48,11 +48,11 @@ one() /* OK. */ ...@@ -48,11 +48,11 @@ one() /* OK. */
one(ichi) /* OK. */ one(ichi) /* OK. */
one(ichi\ one(ichi\
, ni) /* { dg-error "too many" } */ , ni) /* { dg-error "too many" } */
two(ichi) /* { dg-error "insufficient" } */ two(ichi) /* { dg-error "not enough" } */
var0() /* OK. */ var0() /* OK. */
var0(ichi) /* OK. */ var0(ichi) /* OK. */
var1() /* { dg-error "insufficient" } */ var1() /* { dg-error "not enough" } */
var1(ichi) /* { dg-error "insufficient" } */ var1(ichi) /* { dg-error "not enough" } */
var1(ichi, ni) /* OK. */ var1(ichi, ni) /* OK. */
/* This tests two deprecated oddities of GNU rest args - omitting a /* This tests two deprecated oddities of GNU rest args - omitting a
...@@ -70,4 +70,4 @@ rest(ichi) /* { dg-warning "deprecated" } */ ...@@ -70,4 +70,4 @@ rest(ichi) /* { dg-warning "deprecated" } */
#define half_invocation do_nowt(2 #define half_invocation do_nowt(2
#define do_nowt(x) x #define do_nowt(x) x
half_invocation ) /* OK. */ half_invocation ) /* OK. */
do_nowt (half_invocation)) /* { dg-error "unterminated invocation" } */ do_nowt (half_invocation)) /* { dg-error "unterminated argument" } */
...@@ -9,6 +9,6 @@ ...@@ -9,6 +9,6 @@
#define foo(bar) bar #define foo(bar) bar
foo( blah /* { dg-error "unterminated invocation" } */ foo( blah /* { dg-error "unterminated argument" } */
#undef foo /* { dg-error "may not be used inside" "foo(#undef foo)" } */ #undef foo /* { dg-error "may not be used inside" "foo(#undef foo)" } */
blah ) blah )
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment