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:
parent
1b50716d21
commit
ea4a453b89
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
49
gcc/cpplex.c
49
gcc/cpplex.c
@ -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. */
|
||||
|
533
gcc/cpplib.c
533
gcc/cpplib.c
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -8,6 +8,7 @@
|
||||
extern "C" {
|
||||
int printf (const char *, ...);
|
||||
void exit (int);
|
||||
void abort (void);
|
||||
};
|
||||
|
||||
__complex__ double cd;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// GROUPS passed references
|
||||
|
||||
// execution test - XFAIL *-*-*
|
||||
// execution test
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -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) {
|
||||
|
@ -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" } }
|
||||
|
9
gcc/testsuite/gcc.dg/cpp-mix.h
Normal file
9
gcc/testsuite/gcc.dg/cpp-mix.h
Normal 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
|
@ -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" } */
|
||||
|
Loading…
Reference in New Issue
Block a user