Commit ea4a453b by Zack Weinberg Committed by Zack Weinberg

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
parent 1b50716d
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> 2000-05-29 Richard Henderson <rth@cygnus.com>
* function.c (emit_return_into_block): New line_note arg; emit it. * 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. */ ...@@ -39,8 +39,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
# define MMAP_THRESHOLD 0 # define MMAP_THRESHOLD 0
#endif #endif
static IHASH *redundant_include_p PARAMS ((cpp_reader *, IHASH *, static IHASH *redundant_include_p PARAMS ((IHASH *, struct file_name_list *));
struct file_name_list *));
static IHASH *make_IHASH PARAMS ((const char *, const char *, static IHASH *make_IHASH PARAMS ((const char *, const char *,
struct file_name_list *, struct file_name_list *,
unsigned int, IHASH **)); unsigned int, IHASH **));
...@@ -124,8 +123,7 @@ _cpp_init_include_hash (pfile) ...@@ -124,8 +123,7 @@ _cpp_init_include_hash (pfile)
the directories are in fact the same. */ the directories are in fact the same. */
static IHASH * static IHASH *
redundant_include_p (pfile, ihash, ilist) redundant_include_p (ihash, ilist)
cpp_reader *pfile;
IHASH *ihash; IHASH *ihash;
struct file_name_list *ilist; struct file_name_list *ilist;
{ {
...@@ -138,14 +136,14 @@ redundant_include_p (pfile, ihash, ilist) ...@@ -138,14 +136,14 @@ redundant_include_p (pfile, ihash, ilist)
for (i = ihash; i; i = i->next_this_file) for (i = ihash; i; i = i->next_this_file)
for (l = ilist; l; l = l->next) for (l = ilist; l; l = l->next)
if (i->foundhere == l) if (i->foundhere == l)
/* The control_macro works like this: If it's NULL, the file /* The cmacro works like this: If it's NULL, the file is to
is to be included again. If it's "", the file is never to be included again. If it's NEVER_REINCLUDE, the file is
be included again. If it's a string, the file is not to be never to be included again. Otherwise it is a macro
included again if the string is the name of a defined macro. */ hashnode, and the file is to be included again if the
return (i->control_macro macro is not defined. */
&& (i->control_macro[0] == '\0' return (i->cmacro
|| cpp_defined (pfile, i->control_macro, && (i->cmacro == NEVER_REINCLUDE
ustrlen (i->control_macro)))) || i->cmacro->type != T_VOID))
? (IHASH *)-1 : i; ? (IHASH *)-1 : i;
return 0; return 0;
...@@ -199,7 +197,7 @@ make_IHASH (name, fname, path, hash, slot) ...@@ -199,7 +197,7 @@ make_IHASH (name, fname, path, hash, slot)
} }
strcpy ((char *)ih->name, name); strcpy ((char *)ih->name, name);
ih->foundhere = path; ih->foundhere = path;
ih->control_macro = NULL; ih->cmacro = NULL;
ih->hash = hash; ih->hash = hash;
ih->next_this_file = *slot; ih->next_this_file = *slot;
*slot = ih; *slot = ih;
...@@ -256,7 +254,7 @@ find_include_file (pfile, fname, search_start, ihash, before) ...@@ -256,7 +254,7 @@ find_include_file (pfile, fname, search_start, ihash, before)
(const void *) &dummy, (const void *) &dummy,
dummy.hash, INSERT); dummy.hash, INSERT);
if (*slot && (ih = redundant_include_p (pfile, *slot, path))) if (*slot && (ih = redundant_include_p (*slot, path)))
{ {
if (ih == (IHASH *)-1) if (ih == (IHASH *)-1)
return -2; return -2;
...@@ -629,7 +627,7 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start) ...@@ -629,7 +627,7 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
/* Actually process the file. */ /* Actually process the file. */
if (no_reinclude) if (no_reinclude)
ihash->control_macro = U""; ihash->cmacro = NEVER_REINCLUDE;
if (read_include_file (pfile, fd, ihash)) if (read_include_file (pfile, fd, ihash))
{ {
...@@ -662,7 +660,7 @@ cpp_read_file (pfile, fname) ...@@ -662,7 +660,7 @@ cpp_read_file (pfile, fname)
slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files, slot = (IHASH **) htab_find_slot_with_hash (pfile->all_include_files,
(const void *) &dummy, (const void *) &dummy,
dummy.hash, INSERT); 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) if (ih == (IHASH *) -1)
return 1; /* Already included. */ return 1; /* Already included. */
...@@ -759,7 +757,7 @@ read_include_file (pfile, fd, ihash) ...@@ -759,7 +757,7 @@ read_include_file (pfile, fd, ihash)
fp->nominal_fname = ihash->name; fp->nominal_fname = ihash->name;
if (length == 0) if (length == 0)
ihash->control_macro = U""; /* never re-include */ ihash->cmacro = NEVER_REINCLUDE;
else else
/* Temporary - I hope. */ /* Temporary - I hope. */
length = _cpp_prescan (pfile, fp, length); length = _cpp_prescan (pfile, fp, length);
......
...@@ -69,10 +69,11 @@ struct ihash ...@@ -69,10 +69,11 @@ struct ihash
unsigned int hash; /* save hash value for future reference */ unsigned int hash; /* save hash value for future reference */
const char *nshort; /* name of file as referenced in #include; const char *nshort; /* name of file as referenced in #include;
points into name[] */ 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 */ const char name[1]; /* (partial) pathname of file */
}; };
typedef struct ihash IHASH; typedef struct ihash IHASH;
#define NEVER_REINCLUDE ((const cpp_hashnode *)-1)
/* Character classes. /* Character classes.
If the definition of `numchar' looks odd to you, please look up the If the definition of `numchar' looks odd to you, please look up the
......
...@@ -193,7 +193,6 @@ cpp_push_buffer (pfile, buffer, length) ...@@ -193,7 +193,6 @@ cpp_push_buffer (pfile, buffer, length)
new = (cpp_buffer *) xcalloc (1, sizeof (cpp_buffer)); new = (cpp_buffer *) xcalloc (1, sizeof (cpp_buffer));
new->if_stack = pfile->if_stack;
new->buf = new->cur = buffer; new->buf = new->cur = buffer;
new->rlimit = buffer + length; new->rlimit = buffer + length;
new->prev = buf; new->prev = buf;
...@@ -221,7 +220,7 @@ cpp_pop_buffer (pfile) ...@@ -221,7 +220,7 @@ cpp_pop_buffer (pfile)
pfile->system_include_depth--; pfile->system_include_depth--;
if (pfile->potential_control_macro) 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->potential_control_macro = 0;
} }
pfile->input_stack_listing_current = 0; pfile->input_stack_listing_current = 0;
...@@ -1743,6 +1742,7 @@ cpp_get_token (pfile) ...@@ -1743,6 +1742,7 @@ cpp_get_token (pfile)
{ {
enum cpp_ttype token; enum cpp_ttype token;
long written = CPP_WRITTEN (pfile); long written = CPP_WRITTEN (pfile);
int macro_buffer;
get_next: get_next:
token = _cpp_lex_token (pfile); token = _cpp_lex_token (pfile);
...@@ -1750,24 +1750,26 @@ cpp_get_token (pfile) ...@@ -1750,24 +1750,26 @@ cpp_get_token (pfile)
switch (token) switch (token)
{ {
default: default:
if (pfile->skipping)
break;
pfile->potential_control_macro = 0; pfile->potential_control_macro = 0;
pfile->only_seen_white = 0; pfile->only_seen_white = 0;
return token; break;
case CPP_HSPACE:
case CPP_COMMENT:
break;
case CPP_VSPACE: case CPP_VSPACE:
if (pfile->only_seen_white == 0) if (pfile->only_seen_white == 0)
pfile->only_seen_white = 1; pfile->only_seen_white = 1;
CPP_BUMP_LINE (pfile); CPP_BUMP_LINE (pfile);
return token; break;
case CPP_HSPACE:
case CPP_COMMENT:
return token;
case CPP_HASH: case CPP_HASH:
pfile->potential_control_macro = 0; pfile->potential_control_macro = 0;
if (!pfile->only_seen_white) if (!pfile->only_seen_white)
return CPP_HASH; break;
/* XXX shouldn't have to do this - remove the hash or %: from /* XXX shouldn't have to do this - remove the hash or %: from
the token buffer. */ the token buffer. */
if (CPP_PWRITTEN (pfile)[-1] == '#') if (CPP_PWRITTEN (pfile)[-1] == '#')
...@@ -1776,30 +1778,43 @@ cpp_get_token (pfile) ...@@ -1776,30 +1778,43 @@ cpp_get_token (pfile)
CPP_ADJUST_WRITTEN (pfile, -2); CPP_ADJUST_WRITTEN (pfile, -2);
if (_cpp_handle_directive (pfile)) if (_cpp_handle_directive (pfile))
return CPP_DIRECTIVE; {
token = CPP_DIRECTIVE;
break;
}
pfile->only_seen_white = 0; pfile->only_seen_white = 0;
CPP_PUTC (pfile, '#'); CPP_PUTC (pfile, '#');
return CPP_HASH; break;
case CPP_MACRO: case CPP_MACRO:
if (pfile->skipping)
break;
pfile->potential_control_macro = 0; pfile->potential_control_macro = 0;
pfile->only_seen_white = 0; pfile->only_seen_white = 0;
if (! pfile->no_macro_expand if (! pfile->no_macro_expand
&& maybe_macroexpand (pfile, written)) && maybe_macroexpand (pfile, written))
goto get_next; goto get_next;
return CPP_NAME; token = CPP_NAME;
break;
/* Do not run this case through the 'skipping' logic. */
case CPP_EOF: case CPP_EOF:
if (CPP_BUFFER (pfile) == NULL) if (CPP_BUFFER (pfile) == NULL)
return CPP_EOF; return CPP_EOF;
if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile))) macro_buffer = CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile));
{
cpp_pop_buffer (pfile); cpp_pop_buffer (pfile);
if (macro_buffer)
goto get_next; goto get_next;
}
cpp_pop_buffer (pfile);
return CPP_EOF; 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. */ /* Like cpp_get_token, but skip spaces and comments. */
......
...@@ -44,26 +44,22 @@ struct if_stack ...@@ -44,26 +44,22 @@ struct if_stack
{ {
struct if_stack *next; struct if_stack *next;
int lineno; /* line number where condition started */ int lineno; /* line number where condition started */
int if_succeeded; /* truth of last condition in this group */ int was_skipping; /* value of pfile->skipping before this if */
const U_CHAR *control_macro; /* macro name for #ifndef around entire file */ const cpp_hashnode *cmacro; /* macro name for #ifndef around entire file */
int type; /* type of last directive seen in this group */ int type; /* type of last directive seen in this group */
}; };
typedef struct if_stack IF_STACK;
/* Forward declarations. */ /* Forward declarations. */
static void validate_else PARAMS ((cpp_reader *, const U_CHAR *)); 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 unsigned int parse_include PARAMS ((cpp_reader *, const U_CHAR *));
static int conditional_skip PARAMS ((cpp_reader *, int, int, static void push_conditional PARAMS ((cpp_reader *, int, int,
U_CHAR *)); const cpp_hashnode *));
static int skip_if_group PARAMS ((cpp_reader *));
static void pass_thru_directive PARAMS ((const U_CHAR *, size_t, static void pass_thru_directive PARAMS ((const U_CHAR *, size_t,
cpp_reader *, int)); cpp_reader *, int));
static int read_line_number PARAMS ((cpp_reader *, int *)); static int read_line_number PARAMS ((cpp_reader *, int *));
static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *)); static const cpp_hashnode *parse_ifdef PARAMS ((cpp_reader *, const U_CHAR *));
static int consider_directive_while_skipping static const cpp_hashnode *detect_if_not_defined PARAMS ((cpp_reader *));
PARAMS ((cpp_reader *, IF_STACK *));
/* Values for the flags field of the table below. KANDR and COND /* Values for the flags field of the table below. KANDR and COND
directives come from traditional (K&R) C. The difference is, if we directives come from traditional (K&R) C. The difference is, if we
...@@ -208,12 +204,13 @@ _cpp_handle_directive (pfile) ...@@ -208,12 +204,13 @@ _cpp_handle_directive (pfile)
CPP_GOTO_MARK (pfile); CPP_GOTO_MARK (pfile);
/* # followed by a number is equivalent to #line. Do not recognize /* # followed by a number is equivalent to #line. Do not recognize
this form in assembly language source files. Complain about this this form in assembly language source files or skipped
form if we're being pedantic, but not if this is regurgitated conditional groups. Complain about this form if we're being
input (preprocessed or fed back in by the C++ frontend). */ pedantic, but not if this is regurgitated input (preprocessed or
fed back in by the C++ frontend). */
if (tok == CPP_NUMBER) if (tok == CPP_NUMBER)
{ {
if (CPP_OPTION (pfile, lang_asm)) if (pfile->skipping || CPP_OPTION (pfile, lang_asm))
return 0; return 0;
if (CPP_PEDANTIC (pfile) if (CPP_PEDANTIC (pfile)
...@@ -244,8 +241,9 @@ _cpp_handle_directive (pfile) ...@@ -244,8 +241,9 @@ _cpp_handle_directive (pfile)
} }
/* Don't complain about invalid directives in assembly source, /* Don't complain about invalid directives in assembly source,
we don't know where the comments are, and # may introduce we don't know where the comments are, and # may introduce
assembler pseudo-ops. */ assembler pseudo-ops. Don't complain about invalid directives
if (!CPP_OPTION (pfile, lang_asm)) in skipped conditional groups (6.10 p4). */
if (!pfile->skipping && !CPP_OPTION (pfile, lang_asm))
cpp_error (pfile, "invalid preprocessing directive #%s", ident); cpp_error (pfile, "invalid preprocessing directive #%s", ident);
return 0; return 0;
} }
...@@ -255,6 +253,11 @@ _cpp_handle_directive (pfile) ...@@ -255,6 +253,11 @@ _cpp_handle_directive (pfile)
real_directive: 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 /* In -traditional mode, a directive is ignored unless its # is in
column 1. */ column 1. */
if (CPP_TRADITIONAL (pfile) && !hash_at_bol) if (CPP_TRADITIONAL (pfile) && !hash_at_bol)
...@@ -302,11 +305,7 @@ _cpp_handle_directive (pfile) ...@@ -302,11 +305,7 @@ _cpp_handle_directive (pfile)
CPP_SET_WRITTEN (pfile, old_written); CPP_SET_WRITTEN (pfile, old_written);
process_directive: process_directive:
/* Some directives (e.g. #if) may return a request to execute (void) (*dtable[i].func) (pfile);
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)));
return 1; return 1;
} }
...@@ -434,7 +433,7 @@ parse_include (pfile, name) ...@@ -434,7 +433,7 @@ parse_include (pfile, name)
#endif #endif
else 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_SET_WRITTEN (pfile, old_written);
_cpp_skip_rest_of_line (pfile); _cpp_skip_rest_of_line (pfile);
return 0; return 0;
...@@ -442,14 +441,14 @@ parse_include (pfile, name) ...@@ -442,14 +441,14 @@ parse_include (pfile, name)
if (_cpp_get_directive_token (pfile) != CPP_VSPACE) 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_skip_rest_of_line (pfile);
} }
CPP_SET_WRITTEN (pfile, old_written); CPP_SET_WRITTEN (pfile, old_written);
if (len == 0) if (len == 0)
cpp_error (pfile, "empty file name in `#%s'", name); cpp_error (pfile, "empty file name in #%s", name);
return len; return len;
} }
...@@ -563,7 +562,7 @@ read_line_number (pfile, num) ...@@ -563,7 +562,7 @@ read_line_number (pfile, num)
else else
{ {
if (token != CPP_VSPACE && token != CPP_EOF) 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); CPP_SET_WRITTEN (pfile, save_written);
return 0; return 0;
} }
...@@ -587,7 +586,7 @@ do_line (pfile) ...@@ -587,7 +586,7 @@ do_line (pfile)
if (token != CPP_NUMBER) 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; goto bad_line_directive;
} }
...@@ -596,13 +595,13 @@ do_line (pfile) ...@@ -596,13 +595,13 @@ do_line (pfile)
&x, 10); &x, 10);
if (x[0] != '\0') 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; goto bad_line_directive;
} }
CPP_SET_WRITTEN (pfile, old_written); CPP_SET_WRITTEN (pfile, old_written);
if (CPP_PEDANTIC (pfile) && (new_lineno <= 0 || new_lineno > 32767)) 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); token = _cpp_get_directive_token (pfile);
...@@ -615,7 +614,7 @@ do_line (pfile) ...@@ -615,7 +614,7 @@ do_line (pfile)
if (read_line_number (pfile, &action_number)) if (read_line_number (pfile, &action_number))
{ {
if (CPP_PEDANTIC (pfile)) 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 /* This is somewhat questionable: change the buffer stack
depth so that output_line_command thinks we've stacked depth so that output_line_command thinks we've stacked
...@@ -656,7 +655,7 @@ do_line (pfile) ...@@ -656,7 +655,7 @@ do_line (pfile)
} }
else if (token != CPP_VSPACE && token != CPP_EOF) 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; goto bad_line_directive;
} }
...@@ -889,12 +888,12 @@ do_pragma_once (pfile) ...@@ -889,12 +888,12 @@ do_pragma_once (pfile)
/* Allow #pragma once in system headers, since that's not the user's /* Allow #pragma once in system headers, since that's not the user's
fault. */ fault. */
if (!ip->system_header_p) 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) if (CPP_PREV_BUFFER (ip) == NULL)
cpp_warning (pfile, "`#pragma once' outside include file"); cpp_warning (pfile, "#pragma once outside include file");
else else
ip->ihash->control_macro = U""; /* never repeat */ ip->ihash->cmacro = NEVER_REINCLUDE;
return 1; return 1;
} }
...@@ -929,7 +928,7 @@ do_pragma_implementation (pfile) ...@@ -929,7 +928,7 @@ do_pragma_implementation (pfile)
if (cpp_included (pfile, copy)) if (cpp_included (pfile, copy))
cpp_warning (pfile, cpp_warning (pfile,
"`#pragma implementation' for `%s' appears after file is included", "#pragma implementation for %s appears after file is included",
copy); copy);
return 0; return 0;
} }
...@@ -1018,21 +1017,21 @@ do_sccs (pfile) ...@@ -1018,21 +1017,21 @@ do_sccs (pfile)
this file is white space, and if it is of the form this file is white space, and if it is of the form
`#if ! defined SYMBOL', then SYMBOL is a possible controlling macro `#if ! defined SYMBOL', then SYMBOL is a possible controlling macro
for inclusion of this file. (See redundant_include_p in cppfiles.c for inclusion of this file. (See redundant_include_p in cppfiles.c
for an explanation of controlling macros.) If so, return a for an explanation of controlling macros.) If so, return the
malloced copy of SYMBOL. Otherwise, return NULL. */ hash node for SYMBOL. Otherwise, return NULL. */
static U_CHAR * static const cpp_hashnode *
detect_if_not_defined (pfile) detect_if_not_defined (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
U_CHAR *control_macro = 0; const cpp_hashnode *cmacro = 0;
enum cpp_ttype token; enum cpp_ttype token;
unsigned int base_offset; unsigned int base_offset;
unsigned int token_offset; unsigned int token_offset;
unsigned int need_rparen = 0; unsigned int need_rparen = 0;
unsigned int token_len; unsigned int token_len;
if (pfile->only_seen_white != 2) if (pfile->skipping || pfile->only_seen_white != 2)
return NULL; return NULL;
/* Save state required for restore. */ /* Save state required for restore. */
...@@ -1077,82 +1076,21 @@ detect_if_not_defined (pfile) ...@@ -1077,82 +1076,21 @@ detect_if_not_defined (pfile)
goto restore; goto restore;
/* We have a legitimate controlling macro for this header. */ /* We have a legitimate controlling macro for this header. */
control_macro = (U_CHAR *) xmalloc (token_len + 1); cmacro = cpp_lookup (pfile, pfile->token_buffer + token_offset, token_len);
memcpy (control_macro, pfile->token_buffer + token_offset, token_len);
control_macro[token_len] = '\0';
restore: restore:
CPP_SET_WRITTEN (pfile, base_offset); CPP_SET_WRITTEN (pfile, base_offset);
pfile->no_macro_expand--; pfile->no_macro_expand--;
CPP_GOTO_MARK (pfile); CPP_GOTO_MARK (pfile);
return control_macro; return cmacro;
}
/*
* #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;
} }
/* Parse an #ifdef or #ifndef directive. Returns 1 for defined, 0 for /* Parse an #ifdef or #ifndef directive. Returns 1 for defined, 0 for
not defined; the macro tested is left in the token buffer (but not defined; the macro tested is left in the token buffer (but
popped). */ popped). */
static int static const cpp_hashnode *
parse_ifdef (pfile, name) parse_ifdef (pfile, name)
cpp_reader *pfile; cpp_reader *pfile;
const U_CHAR *name; const U_CHAR *name;
...@@ -1161,7 +1099,7 @@ parse_ifdef (pfile, name) ...@@ -1161,7 +1099,7 @@ parse_ifdef (pfile, name)
unsigned int len; unsigned int len;
enum cpp_ttype token; enum cpp_ttype token;
long old_written = CPP_WRITTEN (pfile); long old_written = CPP_WRITTEN (pfile);
int defined; const cpp_hashnode *node = 0;
pfile->no_macro_expand++; pfile->no_macro_expand++;
token = _cpp_get_directive_token (pfile); token = _cpp_get_directive_token (pfile);
...@@ -1173,20 +1111,17 @@ parse_ifdef (pfile, name) ...@@ -1173,20 +1111,17 @@ parse_ifdef (pfile, name)
if (token == CPP_VSPACE) if (token == CPP_VSPACE)
{ {
if (! CPP_TRADITIONAL (pfile)) if (! CPP_TRADITIONAL (pfile))
cpp_pedwarn (pfile, "`#%s' with no argument", name); cpp_pedwarn (pfile, "#%s with no argument", name);
defined = 0;
goto done; goto done;
} }
else if (token == CPP_NAME) else if (token == CPP_NAME)
{ {
defined = cpp_defined (pfile, ident, len); node = cpp_lookup (pfile, ident, len);
CPP_PUTC (pfile, '\0'); /* so it can be copied with xstrdup */
} }
else else
{ {
defined = 0;
if (! CPP_TRADITIONAL (pfile)) if (! CPP_TRADITIONAL (pfile))
cpp_error (pfile, "`#%s' with invalid argument", name); cpp_error (pfile, "#%s with invalid argument", name);
} }
if (!CPP_TRADITIONAL (pfile)) if (!CPP_TRADITIONAL (pfile))
...@@ -1194,13 +1129,13 @@ parse_ifdef (pfile, name) ...@@ -1194,13 +1129,13 @@ parse_ifdef (pfile, name)
if (_cpp_get_directive_token (pfile) == CPP_VSPACE) if (_cpp_get_directive_token (pfile) == CPP_VSPACE)
goto done; 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); _cpp_skip_rest_of_line (pfile);
done: done:
CPP_SET_WRITTEN (pfile, old_written); /* Pop */ CPP_SET_WRITTEN (pfile, old_written); /* Pop */
return defined; return node;
} }
/* #ifdef is dead simple. */ /* #ifdef is dead simple. */
...@@ -1209,8 +1144,14 @@ static int ...@@ -1209,8 +1144,14 @@ static int
do_ifdef (pfile) do_ifdef (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
int skip = ! parse_ifdef (pfile, dtable[T_IFDEF].name); int def = 0;
return conditional_skip (pfile, skip, T_IFDEF, 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 /* #ifndef is a tad more complex, because we need to check for a
...@@ -1220,283 +1161,191 @@ static int ...@@ -1220,283 +1161,191 @@ static int
do_ifndef (pfile) do_ifndef (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
int start_of_file, skip; int start_of_file;
U_CHAR *control_macro = 0; int def = 0;
const cpp_hashnode *cmacro;
start_of_file = pfile->only_seen_white == 2; 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)
if (start_of_file && !skip) cpp_error (pfile, "attempt to use poisoned `%s'", cmacro->name);
control_macro = uxstrdup (CPP_PWRITTEN (pfile)); else
def = (cmacro->type != T_VOID);
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 is straightforward; just call _cpp_parse_expr, then conditional_skip.
If this is a #ifndef starting at the beginning of a file, Also, check for a reinclude preventer of the form #if !defined (MACRO). */
CONTROL_MACRO is the macro name tested by the #ifndef.
Otherwise, CONTROL_MACRO is 0. */
static int static int
conditional_skip (pfile, skip, type, control_macro) do_if (pfile)
cpp_reader *pfile; cpp_reader *pfile;
int skip;
int type;
U_CHAR *control_macro;
{ {
IF_STACK *temp; const cpp_hashnode *cmacro = 0;
int value = 0;
temp = (IF_STACK *) xcalloc (1, sizeof (IF_STACK)); int save_only_seen_white = pfile->only_seen_white;
temp->lineno = CPP_BUFFER (pfile)->lineno;
temp->next = pfile->if_stack;
temp->control_macro = control_macro;
pfile->if_stack = temp;
pfile->if_stack->type = type;
if (skip != 0) if (! pfile->skipping)
return skip_if_group (pfile); {
cmacro = detect_if_not_defined (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; return 0;
} }
/* Subroutine of skip_if_group. Examine one preprocessing directive /* #else flips pfile->skipping and continues without changing
and return 0 if skipping should continue, or the directive number if_stack; this is so that the error message for missing #endif's
of the directive that ends the block if it should halt. etc. will point to the original #if. */
Also adjusts the if_stack as appropriate. The `#' has been read,
but not the identifier. */
static int static int
consider_directive_while_skipping (pfile, stack) do_else (pfile)
cpp_reader *pfile; cpp_reader *pfile;
IF_STACK *stack;
{ {
long ident; struct if_stack *ifs = CPP_BUFFER (pfile)->if_stack;
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); validate_else (pfile, dtable[T_ELSE].name);
if (_cpp_get_directive_token (pfile) != CPP_NAME)
return 0;
len = CPP_WRITTEN (pfile) - ident;
for (i = 0; i < N_DIRECTIVES; i++) if (ifs == NULL)
{ {
if (dtable[i].length == len cpp_error (pfile, "#else without #if");
&& !ustrncmp (dtable[i].name, pfile->token_buffer + ident, len))
goto real_directive;
}
return 0; 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);
} }
if (ifs->type == T_ELSE)
switch (i)
{ {
default: cpp_error (pfile, "#else after #else");
cpp_ice (pfile, "non COND directive in switch in c_d_w_s"); cpp_error_with_line (pfile, ifs->lineno, 1, "the conditional began here");
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); /* #ifndef can't have its special treatment for containing the whole file
pfile->no_macro_expand++; if it has a #else clause. */
for (;;) ifs->cmacro = 0;
{
/* 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) ifs->type = T_ELSE;
if (! ifs->was_skipping)
{ {
ret = consider_directive_while_skipping (pfile, save_if_stack); /* If pfile->skipping is 2, one of the blocks in an #if/#elif/... chain
if (ret) succeeded, so we mustn't do the else block. */
break; if (pfile->skipping < 2)
} pfile->skipping = ! pfile->skipping;
if (token != CPP_VSPACE)
_cpp_skip_rest_of_line (pfile);
} }
CPP_SET_WRITTEN (pfile, old_written); return 0;
pfile->no_macro_expand--;
return ret;
} }
/* /*
* handle a #else directive. Do this by just continuing processing * handle a #elif directive by not changing if_stack either.
* without changing if_stack ; this is so that the error message * see the comment above do_else.
* for missing #endif's etc. will point to the original #if. It
* is possible that something different would be better.
*/ */
static int static int
do_else (pfile) do_elif (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
validate_else (pfile, dtable[T_ELSE].name); struct if_stack *ifs = CPP_BUFFER (pfile)->if_stack;
_cpp_skip_rest_of_line (pfile);
if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) if (ifs == NULL)
{ {
cpp_error (pfile, "`#else' not within a conditional"); cpp_error (pfile, "#elif without #if");
return 0; return 0;
} }
else if (ifs->type == T_ELSE)
{ {
/* #ifndef can't have its special treatment for containing the whole file cpp_error (pfile, "#elif after #else");
if it has a #else clause. */ cpp_error_with_line (pfile, ifs->lineno, 1, "the conditional began here");
pfile->if_stack->control_macro = 0; }
if (pfile->if_stack->type == T_ELSE) ifs->type = T_ELIF;
if (ifs->was_skipping)
_cpp_skip_rest_of_line (pfile);
else if (pfile->skipping != 1)
{ {
cpp_error (pfile, "`#else' after `#else'"); _cpp_skip_rest_of_line (pfile);
cpp_error_with_line (pfile, pfile->if_stack->lineno, 0, pfile->skipping = 2; /* one block succeeded, so don't do any others */
"the conditional began here");
}
pfile->if_stack->type = T_ELSE;
} }
else
pfile->skipping = ! _cpp_parse_expr (pfile);
if (pfile->if_stack->if_succeeded)
return skip_if_group (pfile);
++pfile->if_stack->if_succeeded; /* continue processing input */
return 0; return 0;
} }
/*
* unstack after #endif command /* #endif pops the if stack and resets pfile->skipping. */
*/
static int static int
do_endif (pfile) do_endif (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
struct if_stack *ifs = CPP_BUFFER (pfile)->if_stack;
validate_else (pfile, dtable[T_ENDIF].name); validate_else (pfile, dtable[T_ENDIF].name);
_cpp_skip_rest_of_line (pfile);
if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) if (ifs == NULL)
cpp_error (pfile, "`#endif' not within a conditional"); cpp_error (pfile, "#endif without #if");
else else
{ {
IF_STACK *temp = pfile->if_stack; CPP_BUFFER (pfile)->if_stack = ifs->next;
pfile->if_stack = temp->next; pfile->skipping = ifs->was_skipping;
if (temp->control_macro != 0) pfile->potential_control_macro = ifs->cmacro;
pfile->potential_control_macro = temp->control_macro; free (ifs);
free (temp);
} }
return 0; 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 /* 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 an #else or #endif. */
and very common on old systems. */
static void static void
validate_else (pfile, directive) validate_else (pfile, directive)
cpp_reader *pfile; cpp_reader *pfile;
const U_CHAR *directive; const U_CHAR *directive;
{ {
long old_written; if (CPP_PEDANTIC (pfile))
if (! CPP_PEDANTIC (pfile)) {
return; long old_written = CPP_WRITTEN (pfile);
old_written = CPP_WRITTEN (pfile);
pfile->no_macro_expand++; pfile->no_macro_expand++;
if (_cpp_get_directive_token (pfile) != CPP_VSPACE) if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
cpp_pedwarn (pfile, cpp_pedwarn (pfile, "ISO C forbids text after #%s", directive);
"text following `#%s' violates ANSI standard", directive);
CPP_SET_WRITTEN (pfile, old_written); CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--; pfile->no_macro_expand--;
}
_cpp_skip_rest_of_line (pfile);
} }
/* Called when we reach the end of a macro buffer. Walk back up the /* 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, conditional stack till we reach its level at entry to this file,
issuing error messages. */ issuing error messages. Then force skipping off. */
void void
_cpp_unwind_if_stack (pfile, pbuf) _cpp_unwind_if_stack (pfile, pbuf)
cpp_reader *pfile; cpp_reader *pfile;
...@@ -1504,18 +1353,14 @@ _cpp_unwind_if_stack (pfile, pbuf) ...@@ -1504,18 +1353,14 @@ _cpp_unwind_if_stack (pfile, pbuf)
{ {
struct if_stack *ifs, *nifs; struct if_stack *ifs, *nifs;
for (ifs = pfile->if_stack; for (ifs = pbuf->if_stack; ifs; ifs = nifs)
ifs != pbuf->if_stack;
ifs = nifs)
{ {
cpp_error_with_line (pfile, ifs->lineno, 0, cpp_error_with_line (pfile, ifs->lineno, 1, "unterminated #%s",
"unterminated `#%s' conditional",
dtable[ifs->type].name); dtable[ifs->type].name);
nifs = ifs->next; nifs = ifs->next;
free (ifs); free (ifs);
} }
pfile->if_stack = ifs; pfile->skipping = 0;
} }
#define WARNING(msgid) do { cpp_warning(pfile, msgid); goto error; } while (0) #define WARNING(msgid) do { cpp_warning(pfile, msgid); goto error; } while (0)
......
...@@ -509,8 +509,7 @@ struct cpp_reader ...@@ -509,8 +509,7 @@ struct cpp_reader
for include files. (Altered as we get more of them.) */ for include files. (Altered as we get more of them.) */
unsigned int max_include_len; unsigned int max_include_len;
struct if_stack *if_stack; const cpp_hashnode *potential_control_macro;
const unsigned char *potential_control_macro;
/* Token column position adjustment owing to tabs in whitespace. */ /* Token column position adjustment owing to tabs in whitespace. */
unsigned int col_adjust; unsigned int col_adjust;
...@@ -555,6 +554,9 @@ struct cpp_reader ...@@ -555,6 +554,9 @@ struct cpp_reader
/* True after cpp_start_read completes. Used to inhibit some /* True after cpp_start_read completes. Used to inhibit some
warnings while parsing the command line. */ warnings while parsing the command line. */
unsigned char done_initializing; 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 /* struct cpp_printer encapsulates state used to convert the stream of
......
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> 2000-05-28 Alexandre Oliva <aoliva@cygnus.com>
* gcc.c-torture/execute/20000528-1.c: New test. * gcc.c-torture/execute/20000528-1.c: New test.
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
extern "C" { extern "C" {
int printf (const char *, ...); int printf (const char *, ...);
void exit (int); void exit (int);
void abort (void);
}; };
__complex__ double cd; __complex__ double cd;
......
// GROUPS passed references // GROUPS passed references
// execution test - XFAIL *-*-* // execution test
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
// execution test - XFAIL *-*-* // execution test - XFAIL *-*-*
extern "C" void abort (void);
extern "C" void exit (int);
int i, j; int i, j;
const int &f(const int& I, const int& J) { const int &f(const int& I, const int& J) {
......
...@@ -17,6 +17,10 @@ ...@@ -17,6 +17,10 @@
#include "cpp-mindp.h" #include "cpp-mindp.h"
#include "cpp-mindp.h" #include "cpp-mindp.h"
#define CPP_MIX_H
#include "cpp-mix.h"
#include "cpp-mix.h"
int int
main (void) main (void)
{ {
...@@ -28,7 +32,7 @@ main (void) ...@@ -28,7 +32,7 @@ main (void)
{ dg-final { set tmp [grep cpp-mi.i {cpp-mi.*\.h} line] } } { dg-final { set tmp [grep cpp-mi.i {cpp-mi.*\.h} line] } }
{ dg-final { # send_user "$tmp\n" } } { 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 { pass "cpp-mi.c: redundant include check" } }
{ dg-final { \} else \{ } } { dg-final { \} else \{ } }
{ dg-final { fail "cpp-mi.c: redundant include check" } } { dg-final { fail "cpp-mi.c: redundant include check" } }
......
/* 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 @@ ...@@ -4,7 +4,7 @@
/* You can't get away with this in your own code... */ /* You can't get away with this in your own code... */
#ifdef KERNEL #ifdef KERNEL
#define foo #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. */ /* This will provoke a warning because the '3' is an extension. */
#line 10 "endif-label.c" 3 /* { dg-warning "garbage at end" "#line extension" } */ #line 10 "endif-label.c" 3 /* { dg-warning "garbage at end" "#line extension" } */
...@@ -12,4 +12,4 @@ ...@@ -12,4 +12,4 @@
/* ... but in a system header, it's acceptable. */ /* ... but in a system header, it's acceptable. */
#ifdef KERNEL #ifdef KERNEL
#define foo #define foo
#endif KERNEL /* { dg-bogus "text following" "bad warning" } */ #endif KERNEL /* { dg-bogus "forbids text after" "bad warning" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment