cpplib.h (cpp_reader): Remove if_stack.

* cpplib.h (cpp_reader): Remove if_stack.  Change
	potential_control_macro to a cpp_hashnode *.  Add skipping flag.
	* cpphash.h (struct ihash): Change control_macro to a
	cpp_hashnode * and shorten name to cmacro.
	Add NEVER_REINCLUDE constant.

	* cppfiles.c (redundant_include_p): Drop cpp_reader argument.
	Examine the cmacro node directly, no need to call cpp_defined.
	(_cpp_execute_include, read_include_file): Set cmacro to
	NEVER_REINCLUDE, not U"".
	* cpplex.c (cpp_push_buffer): Don't set new->if_stack.
	(cpp_get_token): If pfile->skipping is true, discard text and
	keep scanning until we hit a directive; don't expand macros.

	* cpplib.c (struct if_stack): Remove if_succeeded, add
	was_skipping. Change control_macro to a cpp_hashnode * and
	shorten name to cmacro.  Remove typedef IF_STACK.
	(parse_ifdef), detect_if_not_defined): Return a cpp_hashnode *.
	(conditional_skip, skip_if_group,
	consider_directive_while_skipping): Delete.
	(push_conditional): New.
	(_cpp_handle_directive): Don't process directives other than
	conditionals if we are skipping.

	(do_ifdef, do_ifndef, do_if, do_else, do_elif, do_endif):
	Update to new scheme.
	(validate_else): Skip rest of line here, unconditionally.
	(_cpp_unwind_if_stack): The stack is per-buffer.  Force
	pfile->skipping off.

	(all): Remove `scare quotes' from error messages.

	* gcc.dg/cpp-mi.c: Add another case, cpp-mix.h, where the
	guard macro is already defined when the header is first
	included.
	* gcc.dg/cpp-mix.h: New file.
	* gcc.dg/endif-label.c: Update patterns to match compiler.

	* g++.brendan/complex1.C: Declare abort.
	* g++.law/refs4.C: Remove XFAIL.
	* g++.oliva/expr2.C: Declare abort and exit.

From-SVN: r34253
This commit is contained in:
Zack Weinberg 2000-05-29 16:19:32 +00:00 committed by Zack Weinberg
parent 1b50716d21
commit ea4a453b89
13 changed files with 309 additions and 385 deletions

View File

@ -1,3 +1,37 @@
2000-05-29 Zack Weinberg <zack@wolery.cumb.org>
* cpplib.h (cpp_reader): Remove if_stack. Change
potential_control_macro to a cpp_hashnode *. Add skipping flag.
* cpphash.h (struct ihash): Change control_macro to a
cpp_hashnode * and shorten name to cmacro.
Add NEVER_REINCLUDE constant.
* cppfiles.c (redundant_include_p): Drop cpp_reader argument.
Examine the cmacro node directly, no need to call cpp_defined.
(_cpp_execute_include, read_include_file): Set cmacro to
NEVER_REINCLUDE, not U"".
* cpplex.c (cpp_push_buffer): Don't set new->if_stack.
(cpp_get_token): If pfile->skipping is true, discard text and
keep scanning until we hit a directive; don't expand macros.
* cpplib.c (struct if_stack): Remove if_succeeded, add
was_skipping. Change control_macro to a cpp_hashnode * and
shorten name to cmacro. Remove typedef IF_STACK.
(parse_ifdef), detect_if_not_defined): Return a cpp_hashnode *.
(conditional_skip, skip_if_group,
consider_directive_while_skipping): Delete.
(push_conditional): New.
(_cpp_handle_directive): Don't process directives other than
conditionals if we are skipping.
(do_ifdef, do_ifndef, do_if, do_else, do_elif, do_endif):
Update to new scheme.
(validate_else): Skip rest of line here, unconditionally.
(_cpp_unwind_if_stack): The stack is per-buffer. Force
pfile->skipping off.
(all): Remove `scare quotes' from error messages.
2000-05-29 Richard Henderson <rth@cygnus.com>
* function.c (emit_return_into_block): New line_note arg; emit it.

View File

@ -39,8 +39,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
# define MMAP_THRESHOLD 0
#endif
static IHASH *redundant_include_p PARAMS ((cpp_reader *, IHASH *,
struct file_name_list *));
static IHASH *redundant_include_p PARAMS ((IHASH *, struct file_name_list *));
static IHASH *make_IHASH PARAMS ((const char *, const char *,
struct file_name_list *,
unsigned int, IHASH **));
@ -124,8 +123,7 @@ _cpp_init_include_hash (pfile)
the directories are in fact the same. */
static IHASH *
redundant_include_p (pfile, ihash, ilist)
cpp_reader *pfile;
redundant_include_p (ihash, ilist)
IHASH *ihash;
struct file_name_list *ilist;
{
@ -138,14 +136,14 @@ redundant_include_p (pfile, ihash, ilist)
for (i = ihash; i; i = i->next_this_file)
for (l = ilist; l; l = l->next)
if (i->foundhere == l)
/* The control_macro works like this: If it's NULL, the file
is to be included again. If it's "", the file is never to
be included again. If it's a string, the file is not to be
included again if the string is the name of a defined macro. */
return (i->control_macro
&& (i->control_macro[0] == '\0'
|| cpp_defined (pfile, i->control_macro,
ustrlen (i->control_macro))))
/* The cmacro works like this: If it's NULL, the file is to
be included again. If it's NEVER_REINCLUDE, the file is
never to be included again. Otherwise it is a macro
hashnode, and the file is to be included again if the
macro is not defined. */
return (i->cmacro
&& (i->cmacro == NEVER_REINCLUDE
|| i->cmacro->type != T_VOID))
? (IHASH *)-1 : i;
return 0;
@ -199,7 +197,7 @@ make_IHASH (name, fname, path, hash, slot)
}
strcpy ((char *)ih->name, name);
ih->foundhere = path;
ih->control_macro = NULL;
ih->cmacro = NULL;
ih->hash = hash;
ih->next_this_file = *slot;
*slot = ih;
@ -256,7 +254,7 @@ find_include_file (pfile, fname, search_start, ihash, before)
(const void *) &dummy,
dummy.hash, INSERT);
if (*slot && (ih = redundant_include_p (pfile, *slot, path)))
if (*slot && (ih = redundant_include_p (*slot, path)))
{
if (ih == (IHASH *)-1)
return -2;
@ -629,7 +627,7 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
/* Actually process the file. */
if (no_reinclude)
ihash->control_macro = U"";
ihash->cmacro = NEVER_REINCLUDE;
if (read_include_file (pfile, fd, ihash))
{
@ -662,7 +660,7 @@ cpp_read_file (pfile, fname)
slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files,
(const void *) &dummy,
dummy.hash, INSERT);
if (*slot && (ih = redundant_include_p (pfile, *slot, ABSOLUTE_PATH)))
if (*slot && (ih = redundant_include_p (*slot, ABSOLUTE_PATH)))
{
if (ih == (IHASH *) -1)
return 1; /* Already included. */
@ -759,7 +757,7 @@ read_include_file (pfile, fd, ihash)
fp->nominal_fname = ihash->name;
if (length == 0)
ihash->control_macro = U""; /* never re-include */
ihash->cmacro = NEVER_REINCLUDE;
else
/* Temporary - I hope. */
length = _cpp_prescan (pfile, fp, length);

View File

@ -69,10 +69,11 @@ struct ihash
unsigned int hash; /* save hash value for future reference */
const char *nshort; /* name of file as referenced in #include;
points into name[] */
const U_CHAR *control_macro; /* macro, if any, preventing reinclusion. */
const cpp_hashnode *cmacro; /* macro, if any, preventing reinclusion. */
const char name[1]; /* (partial) pathname of file */
};
typedef struct ihash IHASH;
#define NEVER_REINCLUDE ((const cpp_hashnode *)-1)
/* Character classes.
If the definition of `numchar' looks odd to you, please look up the

View File

@ -193,7 +193,6 @@ cpp_push_buffer (pfile, buffer, length)
new = (cpp_buffer *) xcalloc (1, sizeof (cpp_buffer));
new->if_stack = pfile->if_stack;
new->buf = new->cur = buffer;
new->rlimit = buffer + length;
new->prev = buf;
@ -221,7 +220,7 @@ cpp_pop_buffer (pfile)
pfile->system_include_depth--;
if (pfile->potential_control_macro)
{
buf->ihash->control_macro = pfile->potential_control_macro;
buf->ihash->cmacro = pfile->potential_control_macro;
pfile->potential_control_macro = 0;
}
pfile->input_stack_listing_current = 0;
@ -1743,6 +1742,7 @@ cpp_get_token (pfile)
{
enum cpp_ttype token;
long written = CPP_WRITTEN (pfile);
int macro_buffer;
get_next:
token = _cpp_lex_token (pfile);
@ -1750,24 +1750,26 @@ cpp_get_token (pfile)
switch (token)
{
default:
if (pfile->skipping)
break;
pfile->potential_control_macro = 0;
pfile->only_seen_white = 0;
return token;
break;
case CPP_HSPACE:
case CPP_COMMENT:
break;
case CPP_VSPACE:
if (pfile->only_seen_white == 0)
pfile->only_seen_white = 1;
CPP_BUMP_LINE (pfile);
return token;
case CPP_HSPACE:
case CPP_COMMENT:
return token;
break;
case CPP_HASH:
pfile->potential_control_macro = 0;
if (!pfile->only_seen_white)
return CPP_HASH;
break;
/* XXX shouldn't have to do this - remove the hash or %: from
the token buffer. */
if (CPP_PWRITTEN (pfile)[-1] == '#')
@ -1776,30 +1778,43 @@ cpp_get_token (pfile)
CPP_ADJUST_WRITTEN (pfile, -2);
if (_cpp_handle_directive (pfile))
return CPP_DIRECTIVE;
{
token = CPP_DIRECTIVE;
break;
}
pfile->only_seen_white = 0;
CPP_PUTC (pfile, '#');
return CPP_HASH;
break;
case CPP_MACRO:
if (pfile->skipping)
break;
pfile->potential_control_macro = 0;
pfile->only_seen_white = 0;
if (! pfile->no_macro_expand
&& maybe_macroexpand (pfile, written))
goto get_next;
return CPP_NAME;
token = CPP_NAME;
break;
/* Do not run this case through the 'skipping' logic. */
case CPP_EOF:
if (CPP_BUFFER (pfile) == NULL)
return CPP_EOF;
if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
{
cpp_pop_buffer (pfile);
goto get_next;
}
macro_buffer = CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile));
cpp_pop_buffer (pfile);
if (macro_buffer)
goto get_next;
return CPP_EOF;
}
if (pfile->skipping)
{
CPP_SET_WRITTEN (pfile, written);
goto get_next;
}
return token;
}
/* Like cpp_get_token, but skip spaces and comments. */

View File

@ -44,26 +44,22 @@ struct if_stack
{
struct if_stack *next;
int lineno; /* line number where condition started */
int if_succeeded; /* truth of last condition in this group */
const U_CHAR *control_macro; /* macro name for #ifndef around entire file */
int was_skipping; /* value of pfile->skipping before this if */
const cpp_hashnode *cmacro; /* macro name for #ifndef around entire file */
int type; /* type of last directive seen in this group */
};
typedef struct if_stack IF_STACK;
/* Forward declarations. */
static void validate_else PARAMS ((cpp_reader *, const U_CHAR *));
static int parse_ifdef PARAMS ((cpp_reader *, const U_CHAR *));
static unsigned int parse_include PARAMS ((cpp_reader *, const U_CHAR *));
static int conditional_skip PARAMS ((cpp_reader *, int, int,
U_CHAR *));
static int skip_if_group PARAMS ((cpp_reader *));
static void push_conditional PARAMS ((cpp_reader *, int, int,
const cpp_hashnode *));
static void pass_thru_directive PARAMS ((const U_CHAR *, size_t,
cpp_reader *, int));
static int read_line_number PARAMS ((cpp_reader *, int *));
static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *));
static int consider_directive_while_skipping
PARAMS ((cpp_reader *, IF_STACK *));
static const cpp_hashnode *parse_ifdef PARAMS ((cpp_reader *, const U_CHAR *));
static const cpp_hashnode *detect_if_not_defined PARAMS ((cpp_reader *));
/* Values for the flags field of the table below. KANDR and COND
directives come from traditional (K&R) C. The difference is, if we
@ -208,12 +204,13 @@ _cpp_handle_directive (pfile)
CPP_GOTO_MARK (pfile);
/* # followed by a number is equivalent to #line. Do not recognize
this form in assembly language source files. Complain about this
form if we're being pedantic, but not if this is regurgitated
input (preprocessed or fed back in by the C++ frontend). */
this form in assembly language source files or skipped
conditional groups. Complain about this form if we're being
pedantic, but not if this is regurgitated input (preprocessed or
fed back in by the C++ frontend). */
if (tok == CPP_NUMBER)
{
if (CPP_OPTION (pfile, lang_asm))
if (pfile->skipping || CPP_OPTION (pfile, lang_asm))
return 0;
if (CPP_PEDANTIC (pfile)
@ -244,8 +241,9 @@ _cpp_handle_directive (pfile)
}
/* Don't complain about invalid directives in assembly source,
we don't know where the comments are, and # may introduce
assembler pseudo-ops. */
if (!CPP_OPTION (pfile, lang_asm))
assembler pseudo-ops. Don't complain about invalid directives
in skipped conditional groups (6.10 p4). */
if (!pfile->skipping && !CPP_OPTION (pfile, lang_asm))
cpp_error (pfile, "invalid preprocessing directive #%s", ident);
return 0;
}
@ -255,6 +253,11 @@ _cpp_handle_directive (pfile)
real_directive:
/* If we are skipping a failed conditional group, all non-conditional
directives are ignored. */
if (pfile->skipping && ORIGIN (dtable[i].flags) != COND)
return 0;
/* In -traditional mode, a directive is ignored unless its # is in
column 1. */
if (CPP_TRADITIONAL (pfile) && !hash_at_bol)
@ -302,11 +305,7 @@ _cpp_handle_directive (pfile)
CPP_SET_WRITTEN (pfile, old_written);
process_directive:
/* Some directives (e.g. #if) may return a request to execute
another directive handler immediately. No directive ever
requests that #define be executed immediately, so it is safe for
the loop to terminate when some function returns 0 (== T_DEFINE). */
while ((i = dtable[i].func (pfile)));
(void) (*dtable[i].func) (pfile);
return 1;
}
@ -434,7 +433,7 @@ parse_include (pfile, name)
#endif
else
{
cpp_error (pfile, "`#%s' expects \"FILENAME\" or <FILENAME>", name);
cpp_error (pfile, "#%s expects \"FILENAME\" or <FILENAME>", name);
CPP_SET_WRITTEN (pfile, old_written);
_cpp_skip_rest_of_line (pfile);
return 0;
@ -442,14 +441,14 @@ parse_include (pfile, name)
if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
{
cpp_error (pfile, "junk at end of `#%s'", name);
cpp_error (pfile, "junk at end of #%s", name);
_cpp_skip_rest_of_line (pfile);
}
CPP_SET_WRITTEN (pfile, old_written);
if (len == 0)
cpp_error (pfile, "empty file name in `#%s'", name);
cpp_error (pfile, "empty file name in #%s", name);
return len;
}
@ -563,7 +562,7 @@ read_line_number (pfile, num)
else
{
if (token != CPP_VSPACE && token != CPP_EOF)
cpp_error (pfile, "invalid format `#line' command");
cpp_error (pfile, "invalid format #line");
CPP_SET_WRITTEN (pfile, save_written);
return 0;
}
@ -587,7 +586,7 @@ do_line (pfile)
if (token != CPP_NUMBER)
{
cpp_error (pfile, "token after `#line' is not an integer");
cpp_error (pfile, "token after #line is not an integer");
goto bad_line_directive;
}
@ -596,13 +595,13 @@ do_line (pfile)
&x, 10);
if (x[0] != '\0')
{
cpp_error (pfile, "token after `#line' is not an integer");
cpp_error (pfile, "token after #line is not an integer");
goto bad_line_directive;
}
CPP_SET_WRITTEN (pfile, old_written);
if (CPP_PEDANTIC (pfile) && (new_lineno <= 0 || new_lineno > 32767))
cpp_pedwarn (pfile, "line number out of range in `#line' command");
cpp_pedwarn (pfile, "line number out of range in #line");
token = _cpp_get_directive_token (pfile);
@ -615,7 +614,7 @@ do_line (pfile)
if (read_line_number (pfile, &action_number))
{
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "garbage at end of `#line' command");
cpp_pedwarn (pfile, "garbage at end of #line");
/* This is somewhat questionable: change the buffer stack
depth so that output_line_command thinks we've stacked
@ -656,7 +655,7 @@ do_line (pfile)
}
else if (token != CPP_VSPACE && token != CPP_EOF)
{
cpp_error (pfile, "token after `#line %d' is not a string", new_lineno);
cpp_error (pfile, "second token after #line is not a string");
goto bad_line_directive;
}
@ -889,12 +888,12 @@ do_pragma_once (pfile)
/* Allow #pragma once in system headers, since that's not the user's
fault. */
if (!ip->system_header_p)
cpp_warning (pfile, "`#pragma once' is obsolete");
cpp_warning (pfile, "#pragma once is obsolete");
if (CPP_PREV_BUFFER (ip) == NULL)
cpp_warning (pfile, "`#pragma once' outside include file");
cpp_warning (pfile, "#pragma once outside include file");
else
ip->ihash->control_macro = U""; /* never repeat */
ip->ihash->cmacro = NEVER_REINCLUDE;
return 1;
}
@ -929,7 +928,7 @@ do_pragma_implementation (pfile)
if (cpp_included (pfile, copy))
cpp_warning (pfile,
"`#pragma implementation' for `%s' appears after file is included",
"#pragma implementation for %s appears after file is included",
copy);
return 0;
}
@ -1018,21 +1017,21 @@ do_sccs (pfile)
this file is white space, and if it is of the form
`#if ! defined SYMBOL', then SYMBOL is a possible controlling macro
for inclusion of this file. (See redundant_include_p in cppfiles.c
for an explanation of controlling macros.) If so, return a
malloced copy of SYMBOL. Otherwise, return NULL. */
for an explanation of controlling macros.) If so, return the
hash node for SYMBOL. Otherwise, return NULL. */
static U_CHAR *
static const cpp_hashnode *
detect_if_not_defined (pfile)
cpp_reader *pfile;
{
U_CHAR *control_macro = 0;
const cpp_hashnode *cmacro = 0;
enum cpp_ttype token;
unsigned int base_offset;
unsigned int token_offset;
unsigned int need_rparen = 0;
unsigned int token_len;
if (pfile->only_seen_white != 2)
if (pfile->skipping || pfile->only_seen_white != 2)
return NULL;
/* Save state required for restore. */
@ -1077,82 +1076,21 @@ detect_if_not_defined (pfile)
goto restore;
/* We have a legitimate controlling macro for this header. */
control_macro = (U_CHAR *) xmalloc (token_len + 1);
memcpy (control_macro, pfile->token_buffer + token_offset, token_len);
control_macro[token_len] = '\0';
cmacro = cpp_lookup (pfile, pfile->token_buffer + token_offset, token_len);
restore:
CPP_SET_WRITTEN (pfile, base_offset);
pfile->no_macro_expand--;
CPP_GOTO_MARK (pfile);
return control_macro;
}
/*
* #if is straightforward; just call _cpp_parse_expr, then conditional_skip.
* Also, check for a reinclude preventer of the form #if !defined (MACRO).
*/
static int
do_if (pfile)
cpp_reader *pfile;
{
U_CHAR *control_macro;
int value;
int save_only_seen_white = pfile->only_seen_white;
control_macro = detect_if_not_defined (pfile);
pfile->only_seen_white = 0;
value = _cpp_parse_expr (pfile);
pfile->only_seen_white = save_only_seen_white;
return conditional_skip (pfile, value == 0, T_IF, control_macro);
}
/*
* handle a #elif directive by not changing if_stack either.
* see the comment above do_else.
*/
static int
do_elif (pfile)
cpp_reader *pfile;
{
if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
{
cpp_error (pfile, "`#elif' not within a conditional");
return 0;
}
else
{
if (pfile->if_stack->type == T_ELSE)
{
cpp_error (pfile, "`#elif' after `#else'");
cpp_error_with_line (pfile, pfile->if_stack->lineno, 0,
"the conditional began here");
}
pfile->if_stack->type = T_ELIF;
}
if (pfile->if_stack->if_succeeded)
{
_cpp_skip_rest_of_line (pfile);
return skip_if_group (pfile);
}
if (_cpp_parse_expr (pfile) == 0)
return skip_if_group (pfile);
++pfile->if_stack->if_succeeded; /* continue processing input */
return 0;
return cmacro;
}
/* Parse an #ifdef or #ifndef directive. Returns 1 for defined, 0 for
not defined; the macro tested is left in the token buffer (but
popped). */
static int
static const cpp_hashnode *
parse_ifdef (pfile, name)
cpp_reader *pfile;
const U_CHAR *name;
@ -1161,7 +1099,7 @@ parse_ifdef (pfile, name)
unsigned int len;
enum cpp_ttype token;
long old_written = CPP_WRITTEN (pfile);
int defined;
const cpp_hashnode *node = 0;
pfile->no_macro_expand++;
token = _cpp_get_directive_token (pfile);
@ -1173,20 +1111,17 @@ parse_ifdef (pfile, name)
if (token == CPP_VSPACE)
{
if (! CPP_TRADITIONAL (pfile))
cpp_pedwarn (pfile, "`#%s' with no argument", name);
defined = 0;
cpp_pedwarn (pfile, "#%s with no argument", name);
goto done;
}
else if (token == CPP_NAME)
{
defined = cpp_defined (pfile, ident, len);
CPP_PUTC (pfile, '\0'); /* so it can be copied with xstrdup */
node = cpp_lookup (pfile, ident, len);
}
else
{
defined = 0;
if (! CPP_TRADITIONAL (pfile))
cpp_error (pfile, "`#%s' with invalid argument", name);
cpp_error (pfile, "#%s with invalid argument", name);
}
if (!CPP_TRADITIONAL (pfile))
@ -1194,13 +1129,13 @@ parse_ifdef (pfile, name)
if (_cpp_get_directive_token (pfile) == CPP_VSPACE)
goto done;
cpp_pedwarn (pfile, "garbage at end of `#%s' argument", name);
cpp_pedwarn (pfile, "garbage at end of #%s", name);
}
_cpp_skip_rest_of_line (pfile);
done:
CPP_SET_WRITTEN (pfile, old_written); /* Pop */
return defined;
return node;
}
/* #ifdef is dead simple. */
@ -1209,8 +1144,14 @@ static int
do_ifdef (pfile)
cpp_reader *pfile;
{
int skip = ! parse_ifdef (pfile, dtable[T_IFDEF].name);
return conditional_skip (pfile, skip, T_IFDEF, 0);
int def = 0;
const cpp_hashnode *node = parse_ifdef (pfile, dtable[T_IFDEF].name);
if (node->type == T_POISON)
cpp_error (pfile, "attempt to use poisoned `%s'", node->name);
else
def = (node->type != T_VOID);
push_conditional (pfile, !def, T_IFDEF, 0);
return 0;
}
/* #ifndef is a tad more complex, because we need to check for a
@ -1220,283 +1161,191 @@ static int
do_ifndef (pfile)
cpp_reader *pfile;
{
int start_of_file, skip;
U_CHAR *control_macro = 0;
int start_of_file;
int def = 0;
const cpp_hashnode *cmacro;
start_of_file = pfile->only_seen_white == 2;
skip = parse_ifdef (pfile, dtable[T_IFNDEF].name);
cmacro = parse_ifdef (pfile, dtable[T_IFNDEF].name);
if (cmacro->type == T_POISON)
cpp_error (pfile, "attempt to use poisoned `%s'", cmacro->name);
else
def = (cmacro->type != T_VOID);
if (start_of_file && !skip)
control_macro = uxstrdup (CPP_PWRITTEN (pfile));
return conditional_skip (pfile, skip, T_IFNDEF, control_macro);
push_conditional (pfile, def, T_IFNDEF,
start_of_file ? cmacro : 0);
return 0;
}
/* Push TYPE on stack; then, if SKIP is nonzero, skip ahead.
If this is a #ifndef starting at the beginning of a file,
CONTROL_MACRO is the macro name tested by the #ifndef.
Otherwise, CONTROL_MACRO is 0. */
/* #if is straightforward; just call _cpp_parse_expr, then conditional_skip.
Also, check for a reinclude preventer of the form #if !defined (MACRO). */
static int
conditional_skip (pfile, skip, type, control_macro)
do_if (pfile)
cpp_reader *pfile;
int skip;
int type;
U_CHAR *control_macro;
{
IF_STACK *temp;
const cpp_hashnode *cmacro = 0;
int value = 0;
int save_only_seen_white = pfile->only_seen_white;
temp = (IF_STACK *) xcalloc (1, sizeof (IF_STACK));
temp->lineno = CPP_BUFFER (pfile)->lineno;
temp->next = pfile->if_stack;
temp->control_macro = control_macro;
pfile->if_stack = temp;
if (! pfile->skipping)
{
cmacro = detect_if_not_defined (pfile);
pfile->if_stack->type = type;
if (skip != 0)
return skip_if_group (pfile);
++pfile->if_stack->if_succeeded;
pfile->only_seen_white = 0;
value = _cpp_parse_expr (pfile);
pfile->only_seen_white = save_only_seen_white;
}
push_conditional (pfile, value == 0, T_IF, cmacro);
return 0;
}
/* Subroutine of skip_if_group. Examine one preprocessing directive
and return 0 if skipping should continue, or the directive number
of the directive that ends the block if it should halt.
Also adjusts the if_stack as appropriate. The `#' has been read,
but not the identifier. */
static int
consider_directive_while_skipping (pfile, stack)
cpp_reader *pfile;
IF_STACK *stack;
{
long ident;
int i, hash_at_bol;
unsigned int len;
IF_STACK *temp;
/* -traditional directives are recognized only with the # in column 1. */
hash_at_bol = CPP_IN_COLUMN_1 (pfile);
ident = CPP_WRITTEN (pfile);
if (_cpp_get_directive_token (pfile) != CPP_NAME)
return 0;
len = CPP_WRITTEN (pfile) - ident;
for (i = 0; i < N_DIRECTIVES; i++)
{
if (dtable[i].length == len
&& !ustrncmp (dtable[i].name, pfile->token_buffer + ident, len))
goto real_directive;
}
return 0;
real_directive:
/* If it's not a directive of interest to us, return now. */
if (ORIGIN (dtable[i].flags) != COND)
return 0;
/* First, deal with -traditional and -Wtraditional.
All COND directives are from K+R. */
if (! hash_at_bol)
{
if (CPP_TRADITIONAL (pfile))
{
if (CPP_WTRADITIONAL (pfile))
cpp_warning (pfile, "ignoring #%s because of its indented #",
dtable[i].name);
return 0;
}
if (CPP_WTRADITIONAL (pfile))
cpp_warning (pfile, "traditional C ignores %s with the # indented",
dtable[i].name);
}
switch (i)
{
default:
cpp_ice (pfile, "non COND directive in switch in c_d_w_s");
return 0;
case T_IF:
case T_IFDEF:
case T_IFNDEF:
temp = (IF_STACK *) xcalloc (1, sizeof (IF_STACK));
temp->lineno = CPP_BUFFER (pfile)->lineno;
temp->next = pfile->if_stack;
temp->type = i;
pfile->if_stack = temp;
return 0;
case T_ELSE:
if (pfile->if_stack != stack)
validate_else (pfile, dtable[i].name);
/* fall through */
case T_ELIF:
if (pfile->if_stack == stack)
return i;
pfile->if_stack->type = i;
return 0;
case T_ENDIF:
if (pfile->if_stack != stack)
validate_else (pfile, dtable[i].name);
if (pfile->if_stack == stack)
return i;
temp = pfile->if_stack;
pfile->if_stack = temp->next;
free (temp);
return 0;
}
}
/* Skip to #endif, #else, or #elif. Consumes the directive that
causes it to stop, but not its argument. Returns the number of
that directive, which must be passed back up to
_cpp_handle_directive, which will execute it. */
static int
skip_if_group (pfile)
cpp_reader *pfile;
{
enum cpp_ttype token;
IF_STACK *save_if_stack = pfile->if_stack; /* don't pop past here */
long old_written;
int ret = 0;
/* We are no longer at the start of the file. */
pfile->only_seen_white = 0;
old_written = CPP_WRITTEN (pfile);
pfile->no_macro_expand++;
for (;;)
{
/* We are at the end of a line.
XXX Serious layering violation here. */
int c = CPP_BUF_PEEK (CPP_BUFFER (pfile));
if (c == EOF)
break; /* Caller will issue error. */
else if (c != '\n')
cpp_ice (pfile, "character %c at end of line in skip_if_group", c);
CPP_BUFFER (pfile)->cur++;
CPP_BUMP_LINE (pfile);
CPP_SET_WRITTEN (pfile, old_written);
pfile->only_seen_white = 1;
token = _cpp_get_directive_token (pfile);
if (token == CPP_HASH)
{
ret = consider_directive_while_skipping (pfile, save_if_stack);
if (ret)
break;
}
if (token != CPP_VSPACE)
_cpp_skip_rest_of_line (pfile);
}
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
return ret;
}
/*
* handle a #else directive. Do this by just continuing processing
* without changing if_stack ; this is so that the error message
* for missing #endif's etc. will point to the original #if. It
* is possible that something different would be better.
*/
/* #else flips pfile->skipping and continues without changing
if_stack; this is so that the error message for missing #endif's
etc. will point to the original #if. */
static int
do_else (pfile)
cpp_reader *pfile;
{
validate_else (pfile, dtable[T_ELSE].name);
_cpp_skip_rest_of_line (pfile);
struct if_stack *ifs = CPP_BUFFER (pfile)->if_stack;
if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
validate_else (pfile, dtable[T_ELSE].name);
if (ifs == NULL)
{
cpp_error (pfile, "`#else' not within a conditional");
cpp_error (pfile, "#else without #if");
return 0;
}
else
if (ifs->type == T_ELSE)
{
/* #ifndef can't have its special treatment for containing the whole file
if it has a #else clause. */
pfile->if_stack->control_macro = 0;
if (pfile->if_stack->type == T_ELSE)
{
cpp_error (pfile, "`#else' after `#else'");
cpp_error_with_line (pfile, pfile->if_stack->lineno, 0,
"the conditional began here");
}
pfile->if_stack->type = T_ELSE;
cpp_error (pfile, "#else after #else");
cpp_error_with_line (pfile, ifs->lineno, 1, "the conditional began here");
}
if (pfile->if_stack->if_succeeded)
return skip_if_group (pfile);
++pfile->if_stack->if_succeeded; /* continue processing input */
/* #ifndef can't have its special treatment for containing the whole file
if it has a #else clause. */
ifs->cmacro = 0;
ifs->type = T_ELSE;
if (! ifs->was_skipping)
{
/* If pfile->skipping is 2, one of the blocks in an #if/#elif/... chain
succeeded, so we mustn't do the else block. */
if (pfile->skipping < 2)
pfile->skipping = ! pfile->skipping;
}
return 0;
}
/*
* unstack after #endif command
* handle a #elif directive by not changing if_stack either.
* see the comment above do_else.
*/
static int
do_elif (pfile)
cpp_reader *pfile;
{
struct if_stack *ifs = CPP_BUFFER (pfile)->if_stack;
if (ifs == NULL)
{
cpp_error (pfile, "#elif without #if");
return 0;
}
if (ifs->type == T_ELSE)
{
cpp_error (pfile, "#elif after #else");
cpp_error_with_line (pfile, ifs->lineno, 1, "the conditional began here");
}
ifs->type = T_ELIF;
if (ifs->was_skipping)
_cpp_skip_rest_of_line (pfile);
else if (pfile->skipping != 1)
{
_cpp_skip_rest_of_line (pfile);
pfile->skipping = 2; /* one block succeeded, so don't do any others */
}
else
pfile->skipping = ! _cpp_parse_expr (pfile);
return 0;
}
/* #endif pops the if stack and resets pfile->skipping. */
static int
do_endif (pfile)
cpp_reader *pfile;
{
validate_else (pfile, dtable[T_ENDIF].name);
_cpp_skip_rest_of_line (pfile);
struct if_stack *ifs = CPP_BUFFER (pfile)->if_stack;
if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
cpp_error (pfile, "`#endif' not within a conditional");
validate_else (pfile, dtable[T_ENDIF].name);
if (ifs == NULL)
cpp_error (pfile, "#endif without #if");
else
{
IF_STACK *temp = pfile->if_stack;
pfile->if_stack = temp->next;
if (temp->control_macro != 0)
pfile->potential_control_macro = temp->control_macro;
free (temp);
CPP_BUFFER (pfile)->if_stack = ifs->next;
pfile->skipping = ifs->was_skipping;
pfile->potential_control_macro = ifs->cmacro;
free (ifs);
}
return 0;
}
/* Push an if_stack entry and set pfile->skipping accordingly.
If this is a #ifndef starting at the beginning of a file,
CMACRO is the macro name tested by the #ifndef. */
static void
push_conditional (pfile, skip, type, cmacro)
cpp_reader *pfile;
int skip;
int type;
const cpp_hashnode *cmacro;
{
struct if_stack *ifs;
ifs = (struct if_stack *) xmalloc (sizeof (struct if_stack));
ifs->lineno = CPP_BUFFER (pfile)->lineno;
ifs->next = CPP_BUFFER (pfile)->if_stack;
ifs->cmacro = cmacro;
ifs->was_skipping = pfile->skipping;
ifs->type = type;
if (!pfile->skipping)
pfile->skipping = skip;
CPP_BUFFER (pfile)->if_stack = ifs;
}
/* Issue -pedantic warning for text which is not a comment following
an #else or #endif. Do not warn in system headers, as this is harmless
and very common on old systems. */
an #else or #endif. */
static void
validate_else (pfile, directive)
cpp_reader *pfile;
const U_CHAR *directive;
{
long old_written;
if (! CPP_PEDANTIC (pfile))
return;
old_written = CPP_WRITTEN (pfile);
pfile->no_macro_expand++;
if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
cpp_pedwarn (pfile,
"text following `#%s' violates ANSI standard", directive);
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
if (CPP_PEDANTIC (pfile))
{
long old_written = CPP_WRITTEN (pfile);
pfile->no_macro_expand++;
if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
cpp_pedwarn (pfile, "ISO C forbids text after #%s", directive);
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
}
_cpp_skip_rest_of_line (pfile);
}
/* Called when we reach the end of a macro buffer. Walk back up the
conditional stack till we reach its level at entry to this file,
issuing error messages. */
issuing error messages. Then force skipping off. */
void
_cpp_unwind_if_stack (pfile, pbuf)
cpp_reader *pfile;
@ -1504,18 +1353,14 @@ _cpp_unwind_if_stack (pfile, pbuf)
{
struct if_stack *ifs, *nifs;
for (ifs = pfile->if_stack;
ifs != pbuf->if_stack;
ifs = nifs)
for (ifs = pbuf->if_stack; ifs; ifs = nifs)
{
cpp_error_with_line (pfile, ifs->lineno, 0,
"unterminated `#%s' conditional",
cpp_error_with_line (pfile, ifs->lineno, 1, "unterminated #%s",
dtable[ifs->type].name);
nifs = ifs->next;
free (ifs);
}
pfile->if_stack = ifs;
pfile->skipping = 0;
}
#define WARNING(msgid) do { cpp_warning(pfile, msgid); goto error; } while (0)

View File

@ -509,8 +509,7 @@ struct cpp_reader
for include files. (Altered as we get more of them.) */
unsigned int max_include_len;
struct if_stack *if_stack;
const unsigned char *potential_control_macro;
const cpp_hashnode *potential_control_macro;
/* Token column position adjustment owing to tabs in whitespace. */
unsigned int col_adjust;
@ -555,6 +554,9 @@ struct cpp_reader
/* True after cpp_start_read completes. Used to inhibit some
warnings while parsing the command line. */
unsigned char done_initializing;
/* True if we are skipping a failed conditional group. */
unsigned char skipping;
};
/* struct cpp_printer encapsulates state used to convert the stream of

View File

@ -1,3 +1,15 @@
2000-05-29 Zack Weinberg <zack@wolery.cumb.org>
* gcc.dg/cpp-mi.c: Add another case, cpp-mix.h, where the
guard macro is already defined when the header is first
included.
* gcc.dg/cpp-mix.h: New file.
* gcc.dg/endif-label.c: Update patterns to match compiler.
* g++.brendan/complex1.C: Declare abort.
* g++.law/refs4.C: Remove XFAIL.
* g++.oliva/expr2.C: Declare abort and exit.
2000-05-28 Alexandre Oliva <aoliva@cygnus.com>
* gcc.c-torture/execute/20000528-1.c: New test.

View File

@ -8,6 +8,7 @@
extern "C" {
int printf (const char *, ...);
void exit (int);
void abort (void);
};
__complex__ double cd;

View File

@ -1,6 +1,6 @@
// GROUPS passed references
// execution test - XFAIL *-*-*
// execution test
#include <stdio.h>
#include <stdlib.h>

View File

@ -4,6 +4,9 @@
// execution test - XFAIL *-*-*
extern "C" void abort (void);
extern "C" void exit (int);
int i, j;
const int &f(const int& I, const int& J) {

View File

@ -17,6 +17,10 @@
#include "cpp-mindp.h"
#include "cpp-mindp.h"
#define CPP_MIX_H
#include "cpp-mix.h"
#include "cpp-mix.h"
int
main (void)
{
@ -28,7 +32,7 @@ main (void)
{ dg-final { set tmp [grep cpp-mi.i {cpp-mi.*\.h} line] } }
{ dg-final { # send_user "$tmp\n" } }
{ dg-final { if [regexp "^{\[0-9\]+ cpp-mic\.h} {\[0-9\]+ cpp-micc\.h} {\[0-9\]+ cpp-mind\.h} {\[0-9\]+ cpp-mindp\.h}$" $tmp] \{ } }
{ dg-final { if [regexp "^{\[0-9\]+ cpp-mic\.h} {\[0-9\]+ cpp-micc\.h} {\[0-9\]+ cpp-mind\.h} {\[0-9\]+ cpp-mindp\.h} {\[0-9]+ cpp-mix\.h}$" $tmp] \{ } }
{ dg-final { pass "cpp-mi.c: redundant include check" } }
{ dg-final { \} else \{ } }
{ dg-final { fail "cpp-mi.c: redundant include check" } }

View File

@ -0,0 +1,9 @@
/* This header is never to have its contents visible, but it should
still receive the optimization. */
#ifndef CPP_MIX_H
#define CPP_MIX_H
#define main wibble
#endif

View File

@ -4,7 +4,7 @@
/* You can't get away with this in your own code... */
#ifdef KERNEL
#define foo
#endif KERNEL /* { dg-warning "text following" "good warning" } */
#endif KERNEL /* { dg-warning "forbids text after" "good warning" } */
/* This will provoke a warning because the '3' is an extension. */
#line 10 "endif-label.c" 3 /* { dg-warning "garbage at end" "#line extension" } */
@ -12,4 +12,4 @@
/* ... but in a system header, it's acceptable. */
#ifdef KERNEL
#define foo
#endif KERNEL /* { dg-bogus "text following" "bad warning" } */
#endif KERNEL /* { dg-bogus "forbids text after" "bad warning" } */