mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-27 05:44:15 +08:00
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:
parent
0068fd9637
commit
6d18adbc2c
@ -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.
|
||||||
|
42
gcc/cppexp.c
42
gcc/cppexp.c
@ -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))
|
||||||
|
@ -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))
|
||||||
|
@ -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. */
|
||||||
|
@ -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,
|
||||||
|
30
gcc/cpplib.c
30
gcc/cpplib.c
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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: <% %> <: :> %: %:%:
|
||||||
|
Loading…
Reference in New Issue
Block a user