]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cpplib.h (cpp_reader): Remove if_stack.
authorZack Weinberg <zack@wolery.cumb.org>
Mon, 29 May 2000 16:19:32 +0000 (16:19 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Mon, 29 May 2000 16:19:32 +0000 (16:19 +0000)
* 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

13 files changed:
gcc/ChangeLog
gcc/cppfiles.c
gcc/cpphash.h
gcc/cpplex.c
gcc/cpplib.c
gcc/cpplib.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.brendan/complex1.C
gcc/testsuite/g++.old-deja/g++.law/refs4.C
gcc/testsuite/g++.old-deja/g++.oliva/expr2.C
gcc/testsuite/gcc.dg/cpp-mi.c
gcc/testsuite/gcc.dg/cpp-mix.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/endif-label.c

index f425de924e22571992f89a86196eb80096a390a5..6534ad18c1885195bde1ce745ad646d959c2554b 100644 (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.
index 295590203963237a65857239adcd000f91d338a8..676c9d56c4a90dd86e22b8c95c21cece86f4b2e6 100644 (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);
index c590de68636ec453a17435765cc132703d76e791..28761c71225ad851545e3eaa06e3484427b8c41b 100644 (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
index 4708382d15825d4ab46847f116debe22869bb22a..b35f2989786a8b2b02ca0b1cd3d2d021cf84f649 100644 (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.  */
index 6cc99ec7eaacfb3af81812e7dcec1fa68d2bce71..3bc882562e72e17e2bb3cd26aed567f41ecb6b35 100644 (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);
-
-  if (start_of_file && !skip)
-    control_macro = uxstrdup (CPP_PWRITTEN (pfile));
+  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);
 
-  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;
-
-  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;
-
-  pfile->if_stack->type = type;
+  const cpp_hashnode *cmacro = 0;
+  int value = 0;
+  int save_only_seen_white = pfile->only_seen_white;
 
-  if (skip != 0)
-    return skip_if_group (pfile);
+  if (! pfile->skipping)
+    {
+      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;
 }
 
-/* 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. */
+/* #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
-consider_directive_while_skipping (pfile, stack)
-    cpp_reader *pfile;
-    IF_STACK *stack; 
+do_else (pfile)
+     cpp_reader *pfile;
 {
-  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;
+  struct if_stack *ifs = CPP_BUFFER (pfile)->if_stack;
 
-  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.  */
+  validate_else (pfile, dtable[T_ELSE].name);
 
-  if (! hash_at_bol)
+  if (ifs == NULL)
     {
-      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);
+      cpp_error (pfile, "#else without #if");
+      return 0;
     }
-  
-  switch (i)
+  if (ifs->type == T_ELSE)
     {
-    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;
+      cpp_error (pfile, "#else after #else");
+      cpp_error_with_line (pfile, ifs->lineno, 1, "the conditional began here");
     }
-}
-
-/* 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;
+  /* #ifndef can't have its special treatment for containing the whole file
+     if it has a #else clause.  */
+  ifs->cmacro = 0;
 
-  old_written = CPP_WRITTEN (pfile);
-  pfile->no_macro_expand++;
-  for (;;)
+  ifs->type = T_ELSE;
+  if (! ifs->was_skipping)
     {
-      /* 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);
+      /* 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;
     }
-  CPP_SET_WRITTEN (pfile, old_written);
-  pfile->no_macro_expand--;
-  return ret;
+  return 0;
 }
 
 /*
- * 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.
+ * handle a #elif directive by not changing if_stack either.
+ * see the comment above do_else.
  */
 
 static int
-do_else (pfile)
+do_elif (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)
+  if (ifs == NULL)
     {
-      cpp_error (pfile, "`#else' not within a conditional");
+      cpp_error (pfile, "#elif 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;
+      cpp_error (pfile, "#elif after #else");
+      cpp_error_with_line (pfile, ifs->lineno, 1, "the conditional began here");
+    }
 
-      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;
+  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);
 
-  if (pfile->if_stack->if_succeeded)
-    return skip_if_group (pfile);
-  
-  ++pfile->if_stack->if_succeeded;     /* continue processing input */
   return 0;
 }
 
-/*
- * unstack after #endif command
- */
+
+/* #endif pops the if stack and resets pfile->skipping.  */
 
 static int
 do_endif (pfile)
      cpp_reader *pfile;
 {
+  struct if_stack *ifs = CPP_BUFFER (pfile)->if_stack;
+
   validate_else (pfile, dtable[T_ENDIF].name);
-  _cpp_skip_rest_of_line (pfile);
 
-  if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
-    cpp_error (pfile, "`#endif' not within a conditional");
+  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)
index 0ac5c271ea6a948df1c567d47f47fd834c59f840..c2f95f526ddc1ff6dfeb371853e3d79749a1639c 100644 (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
index f9d89e984e992912f4b29c0d1ffd358cc5694ee5..c963207532c85e15d753b5b38d33faa195f9ff55 100644 (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.
index 1c9c4d2fa4248dab4533bc9fa9c8a11c6410fe7b..a2378bedf7337384fa3c9e13ed4061b894515dc3 100644 (file)
@@ -8,6 +8,7 @@
 extern "C" {
 int printf (const char *, ...);
 void exit (int);
+void abort (void);
 };
 
 __complex__ double cd;
index a227f23d78d0396415e4f6ca45cc6f95c1e1b35f..13349ef1365a7cda147ec4715fab92f6fbef4668 100644 (file)
@@ -1,6 +1,6 @@
 // GROUPS passed references
 
-// execution test - XFAIL *-*-*
+// execution test
 
 #include <stdio.h>
 #include <stdlib.h>
index c1994349acd07f6f1ece515d5e8f381b8bc2ce73..20285937b78e2f446b6b96efb7c96b3a4b49b15c 100644 (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) {
index a05b279558b55f45cf4db0fe52323e338d7e654b..f83a64d5871905e30e8a935ec67878fb09d72c53 100644 (file)
 #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"   } }
diff --git a/gcc/testsuite/gcc.dg/cpp-mix.h b/gcc/testsuite/gcc.dg/cpp-mix.h
new file mode 100644 (file)
index 0000000..ce0e764
--- /dev/null
@@ -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
index 95bd05d51a79f5aee96dc4dbc0836eb3044dc687..c12662cd52ba6b2bdaef97f23f2cc385a904871d 100644 (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" } */