cppexp.c (parse_defined): Always record the macro name.

* cppexp.c (parse_defined): Always record the macro name.
	(lex): Don't worry about identifiers, or special-case
	CPP_NOT here.
	(_cpp_parse_expr): Figure out at the end of the routine
	whether we saw a valid !defined() expression.
	* cppfiles.c (stack_include_file): Update for mi_valid.
	(_cpp_pop_file_buffer): Similarly.
	* cpplex.c (_cpp_lex_token): Similarly.
	* cpphash.h (enum mi_state, enum mi_ind, mi_state,
	mi_if_not_defined, mi_lexed): Remove.
	(mi_valid): New.
	* cpplib.c (do_if): Simplify.
	(do_endif, push_conditional, _cpp_handle_directive): Update
	for renaming of mi_state to mi_valid.

	* cpp.texi: Add index entries for digraphs, and add comment
	that C++ refers to them as alternative tokens.

From-SVN: r44459
This commit is contained in:
Neil Booth 2001-07-29 17:27:57 +00:00 committed by Neil Booth
parent 0068fd9637
commit 6d18adbc2c
8 changed files with 68 additions and 57 deletions

View File

@ -1,3 +1,23 @@
2001-07-29 Neil Booth <neil@cat.daikokuya.demon.co.uk>
* cppexp.c (parse_defined): Always record the macro name.
(lex): Don't worry about identifiers, or special-case
CPP_NOT here.
(_cpp_parse_expr): Figure out at the end of the routine
whether we saw a valid !defined() expression.
* cppfiles.c (stack_include_file): Update for mi_valid.
(_cpp_pop_file_buffer): Similarly.
* cpplex.c (_cpp_lex_token): Similarly.
* cpphash.h (enum mi_state, enum mi_ind, mi_state,
mi_if_not_defined, mi_lexed): Remove.
(mi_valid): New.
* cpplib.c (do_if): Simplify.
(do_endif, push_conditional, _cpp_handle_directive): Update
for renaming of mi_state to mi_valid.
doc:
* cpp.texi: Add index entries for digraphs, and add comment
that C++ refers to them as alternative tokens.
Sun Jul 29 18:59:13 CEST 2001 Jan Hubicka <jh@suse.cz> Sun Jul 29 18:59:13 CEST 2001 Jan Hubicka <jh@suse.cz>
* basic-block.h (CLEANUP_PRE_LOOP): New. * basic-block.h (CLEANUP_PRE_LOOP): New.

View File

@ -267,16 +267,9 @@ parse_defined (pfile)
op.unsignedp = 0; op.unsignedp = 0;
op.op = CPP_NUMBER; op.op = CPP_NUMBER;
/* No macros? At top of file? */ /* A possible controlling macro of the form #if !defined ().
if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0 _cpp_parse_expr checks there was no other junk on the line. */
&& pfile->mi_if_not_defined == MI_IND_NOT && pfile->mi_lexed == 1) pfile->mi_ind_cmacro = node;
{
cpp_start_lookahead (pfile);
cpp_get_token (pfile, &token);
if (token.type == CPP_EOF)
pfile->mi_ind_cmacro = node;
cpp_stop_lookahead (pfile, 0);
}
} }
pfile->state.prevent_expansion--; pfile->state.prevent_expansion--;
@ -351,10 +344,6 @@ lex (pfile, skip_evaluation, token)
} }
else else
{ {
/* Controlling #if expressions cannot contain identifiers (they
could become macros in the future). */
pfile->mi_state = MI_FAILED;
op.op = CPP_NUMBER; op.op = CPP_NUMBER;
op.unsignedp = 0; op.unsignedp = 0;
op.value = 0; op.value = 0;
@ -377,11 +366,6 @@ lex (pfile, skip_evaluation, token)
return op; return op;
} }
case CPP_NOT:
/* We don't worry about its position here. */
pfile->mi_if_not_defined = MI_IND_NOT;
/* Fall through. */
default: default:
if (((int) token->type > (int) CPP_EQ if (((int) token->type > (int) CPP_EQ
&& (int) token->type < (int) CPP_PLUS_EQ) && (int) token->type < (int) CPP_PLUS_EQ)
@ -598,10 +582,12 @@ _cpp_parse_expr (pfile)
register struct op *top = stack + 1; register struct op *top = stack + 1;
int skip_evaluation = 0; int skip_evaluation = 0;
int result; int result;
unsigned int lex_count, saw_leading_not;
/* Set up detection of #if ! defined(). */ /* Set up detection of #if ! defined(). */
pfile->mi_lexed = 0; pfile->mi_ind_cmacro = 0;
pfile->mi_if_not_defined = MI_IND_NONE; saw_leading_not = 0;
lex_count = 0;
/* We've finished when we try to reduce this. */ /* We've finished when we try to reduce this. */
top->op = CPP_EOF; top->op = CPP_EOF;
@ -618,7 +604,7 @@ _cpp_parse_expr (pfile)
/* Read a token */ /* Read a token */
op = lex (pfile, skip_evaluation, &token); op = lex (pfile, skip_evaluation, &token);
pfile->mi_lexed++; lex_count++;
/* If the token is an operand, push its value and get next /* If the token is an operand, push its value and get next
token. If it is an operator, get its priority and flags, and token. If it is an operator, get its priority and flags, and
@ -638,6 +624,11 @@ _cpp_parse_expr (pfile)
continue; continue;
case CPP_EOF: prio = FORCE_REDUCE_PRIO; break; case CPP_EOF: prio = FORCE_REDUCE_PRIO; break;
case CPP_NOT:
saw_leading_not = lex_count == 1;
prio = op_to_prio[op.op];
break;
case CPP_PLUS: case CPP_PLUS:
case CPP_MINUS: prio = PLUS_PRIO; if (top->flags & HAVE_VALUE) break; case CPP_MINUS: prio = PLUS_PRIO; if (top->flags & HAVE_VALUE) break;
/* else unary; fall through */ /* else unary; fall through */
@ -869,7 +860,14 @@ _cpp_parse_expr (pfile)
} }
done: done:
/* The controlling macro expression is only valid if we called lex 3
times: <!> <defined expression> and <EOF>. push_conditional ()
checks that we are at top-of-file. */
if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3))
pfile->mi_ind_cmacro = 0;
result = (top[1].value != 0); result = (top[1].value != 0);
if (top != stack) if (top != stack)
CPP_ICE ("unbalanced stack in #if"); CPP_ICE ("unbalanced stack in #if");
else if (!(top[1].flags & HAVE_VALUE)) else if (!(top[1].flags & HAVE_VALUE))

View File

@ -332,7 +332,7 @@ stack_include_file (pfile, inc)
fp->sysp = sysp; fp->sysp = sysp;
/* Initialise controlling macro state. */ /* Initialise controlling macro state. */
pfile->mi_state = MI_OUTSIDE; pfile->mi_valid = true;
pfile->mi_cmacro = 0; pfile->mi_cmacro = 0;
pfile->include_depth++; pfile->include_depth++;
@ -748,12 +748,12 @@ _cpp_pop_file_buffer (pfile, buf)
pfile->include_depth--; pfile->include_depth--;
/* Record the inclusion-preventing macro, which could be NULL /* Record the inclusion-preventing macro, which could be NULL
meaning no controlling macro, if we haven't got it already. */ meaning no controlling macro. */
if (pfile->mi_state == MI_OUTSIDE && inc->cmacro == NULL) if (pfile->mi_valid && inc->cmacro == NULL)
inc->cmacro = pfile->mi_cmacro; inc->cmacro = pfile->mi_cmacro;
/* Invalidate control macros in the #including file. */ /* Invalidate control macros in the #including file. */
pfile->mi_state = MI_FAILED; pfile->mi_valid = false;
inc->refcnt--; inc->refcnt--;
if (inc->refcnt == 0 && DO_NOT_REREAD (inc)) if (inc->refcnt == 0 && DO_NOT_REREAD (inc))

View File

@ -93,10 +93,6 @@ struct search_path
struct file_name_map *name_map; struct file_name_map *name_map;
}; };
/* Multiple-include optimisation. */
enum mi_state {MI_FAILED = 0, MI_OUTSIDE};
enum mi_ind {MI_IND_NONE = 0, MI_IND_NOT};
/* #include types. */ /* #include types. */
enum include_type {IT_INCLUDE, IT_INCLUDE_NEXT, IT_IMPORT, IT_CMDLINE}; enum include_type {IT_INCLUDE, IT_INCLUDE_NEXT, IT_IMPORT, IT_CMDLINE};
@ -268,11 +264,9 @@ struct cpp_reader
const struct directive *directive; const struct directive *directive;
/* Multiple inlcude optimisation. */ /* Multiple inlcude optimisation. */
enum mi_state mi_state;
enum mi_ind mi_if_not_defined;
unsigned int mi_lexed;
const cpp_hashnode *mi_cmacro; const cpp_hashnode *mi_cmacro;
const cpp_hashnode *mi_ind_cmacro; const cpp_hashnode *mi_ind_cmacro;
bool mi_valid;
/* Token lookahead. */ /* Token lookahead. */
struct cpp_lookahead *la_read; /* Read from this lookahead. */ struct cpp_lookahead *la_read; /* Read from this lookahead. */

View File

@ -1266,7 +1266,7 @@ _cpp_lex_token (pfile, result)
/* If not in a directive, this token invalidates controlling macros. */ /* If not in a directive, this token invalidates controlling macros. */
if (!pfile->state.in_directive) if (!pfile->state.in_directive)
pfile->mi_state = MI_FAILED; pfile->mi_valid = false;
} }
/* An upper bound on the number of bytes needed to spell a token, /* An upper bound on the number of bytes needed to spell a token,

View File

@ -358,7 +358,7 @@ _cpp_handle_directive (pfile, indented)
/* If we have a directive that is not an opening /* If we have a directive that is not an opening
conditional, invalidate any control macro. */ conditional, invalidate any control macro. */
if (! (dir->flags & IF_COND)) if (! (dir->flags & IF_COND))
pfile->mi_state = MI_FAILED; pfile->mi_valid = false;
(*dir->handler) (pfile); (*dir->handler) (pfile);
} }
@ -1278,27 +1278,22 @@ do_ifndef (pfile)
push_conditional (pfile, skip, T_IFNDEF, node); push_conditional (pfile, skip, T_IFNDEF, node);
} }
/* #if cooperates with parse_defined to handle multiple-include /* _cpp_parse_expr puts a macro in a "#if !defined ()" expression in
optimisations. If macro expansions or identifiers appear in the pfile->mi_ind_cmacro so we can handle multiple-include
expression, we cannot treat it as a controlling conditional, since optimisations. If macro expansion occurs in the expression, we
their values could change in the future. */ cannot treat it as a controlling conditional, since the expansion
could change in the future. That is handled by cpp_get_token. */
static void static void
do_if (pfile) do_if (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
int skip = 1; int skip = 1;
const cpp_hashnode *cmacro = 0;
if (! pfile->state.skipping) if (! pfile->state.skipping)
{ skip = _cpp_parse_expr (pfile) == 0;
/* Controlling macro of #if ! defined () */
pfile->mi_ind_cmacro = 0;
skip = _cpp_parse_expr (pfile) == 0;
cmacro = pfile->mi_ind_cmacro;
}
push_conditional (pfile, skip, T_IF, cmacro); push_conditional (pfile, skip, T_IF, pfile->mi_ind_cmacro);
} }
/* Flip skipping state if appropriate and continue without changing /* Flip skipping state if appropriate and continue without changing
@ -1395,7 +1390,7 @@ do_endif (pfile)
/* If potential control macro, we go back outside again. */ /* If potential control macro, we go back outside again. */
if (ifs->next == 0 && ifs->mi_cmacro) if (ifs->next == 0 && ifs->mi_cmacro)
{ {
pfile->mi_state = MI_OUTSIDE; pfile->mi_valid = true;
pfile->mi_cmacro = ifs->mi_cmacro; pfile->mi_cmacro = ifs->mi_cmacro;
} }
@ -1406,8 +1401,8 @@ do_endif (pfile)
} }
/* Push an if_stack entry and set pfile->state.skipping accordingly. /* Push an if_stack entry and set pfile->state.skipping accordingly.
If this is a #ifndef starting at the beginning of a file, If this is a #if or #ifndef, CMACRO is a potentially controlling
CMACRO is the macro name tested by the #ifndef. */ macro - we need to check here that we are at the top of the file. */
static void static void
push_conditional (pfile, skip, type, cmacro) push_conditional (pfile, skip, type, cmacro)
@ -1425,7 +1420,8 @@ push_conditional (pfile, skip, type, cmacro)
ifs->skip_elses = pfile->state.skipping || !skip; ifs->skip_elses = pfile->state.skipping || !skip;
ifs->was_skipping = pfile->state.skipping; ifs->was_skipping = pfile->state.skipping;
ifs->type = type; ifs->type = type;
if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0) /* This condition is effectively a test for top-of-file. */
if (pfile->mi_valid && pfile->mi_cmacro == 0)
ifs->mi_cmacro = cmacro; ifs->mi_cmacro = cmacro;
else else
ifs->mi_cmacro = 0; ifs->mi_cmacro = 0;

View File

@ -953,7 +953,7 @@ cpp_get_token (pfile, token)
cpp_hashnode *node = token->val.node; cpp_hashnode *node = token->val.node;
/* Macros invalidate controlling macros. */ /* Macros invalidate controlling macros. */
pfile->mi_state = MI_FAILED; pfile->mi_valid = false;
if (node->flags & NODE_BUILTIN) if (node->flags & NODE_BUILTIN)
{ {

View File

@ -536,15 +536,18 @@ be removed in GCC 3.1. You may use continued lines instead, or string
constant concatenation. @xref{Differences from previous versions}. constant concatenation. @xref{Differences from previous versions}.
@cindex punctuators @cindex punctuators
@cindex digraphs
@cindex alternative tokens
@dfn{Punctuators} are all the usual bits of punctuation which are @dfn{Punctuators} are all the usual bits of punctuation which are
meaningful to C and C++. All but three of the punctuation characters in meaningful to C and C++. All but three of the punctuation characters in
ASCII are C punctuators. The exceptions are @samp{@@}, @samp{$}, and ASCII are C punctuators. The exceptions are @samp{@@}, @samp{$}, and
@samp{`}. In addition, all the two- and three-character operators are @samp{`}. In addition, all the two- and three-character operators are
punctuators. There are also six @dfn{digraphs}, which are merely punctuators. There are also six @dfn{digraphs}, which the C++ standard
alternate ways to spell other punctuators. This is a second attempt to calls @dfn{alternative tokens}, which are merely alternate ways to spell
work around missing punctuation in obsolete systems. It has no negative other punctuators. This is a second attempt to work around missing
side effects, unlike trigraphs, but does not cover as much ground. The punctuation in obsolete systems. It has no negative side effects,
digraphs and their corresponding normal punctuators are: unlike trigraphs, but does not cover as much ground. The digraphs and
their corresponding normal punctuators are:
@example @example
Digraph: <% %> <: :> %: %:%: Digraph: <% %> <: :> %: %:%: