This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

#import ==> once-only


This gives #import the once-only semantics that Apple
need and that GCC used to do but didn't guarantee.  I've
added two tests; doc updates will be part of my upcoming
doc update patch and will document this as the intended
behaviour.

Neil.

	* cppfiles.c (struct _cpp_file): Rename once_only_next to
	next_file.  Remove import and pragma_once, add once_only.
	(find_file): Add new file structures to the all_files list.
	(should_stack_file): Mark #import-ed files once-only, and
	don't stack them if the file has already been stacked.
	(_cp_mark_file_once_only): Simplify.
	* cpphash.h (struct cpp_reader): Rename once_only_files
	to all_files.  Rename saw_pragma_once to seen_once_only.
	(_cpp_mark_file_once_only): Update prototype.
	* cpplib.c (do_pragma_once): Update.
testsuite:
	* import1.c, import2.c: New tests.
	
Index: cppfiles.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppfiles.c,v
retrieving revision 1.182
diff -u -p -r1.182 cppfiles.c
--- cppfiles.c	2 Aug 2003 12:44:27 -0000	1.182
+++ cppfiles.c	2 Aug 2003 16:04:37 -0000
@@ -70,8 +70,8 @@ struct _cpp_file
      been calculated yet.  */
   const char *dir_name;
 
-  /* Chain through #import-ed files or those  containing #pragma once.  */
-  struct _cpp_file *once_only_next;
+  /* Chain through all files.  */
+  struct _cpp_file *next_file;
 
   /* The contents of NAME after calling read_file().  */
   const uchar *buffer;
@@ -97,11 +97,8 @@ struct _cpp_file
   /* Number of times the file has been stacked for preprocessing.  */
   unsigned short stack_count;
 
-  /* If opened with #import.  */
-  bool import;
-
-  /* If contains #pragma once.  */
-  bool pragma_once;
+  /* If opened with #import or contains #pragma once.  */
+  bool once_only;
 
   /* If read() failed before.  */
   bool dont_read;
@@ -383,13 +380,21 @@ find_file (cpp_reader *pfile, const char
 
       entry = search_cache (*hash_slot, file->dir);
       if (entry)
-	{
-	  /* Cache for START_DIR too, sharing the _cpp_file structure.  */
-	  free ((char *) file->name);
-	  free (file);
-	  file = entry->u.file;
-	  break;
-	}
+	break;
+    }
+
+  if (entry)
+    {
+      /* Cache for START_DIR too, sharing the _cpp_file structure.  */
+      free ((char *) file->name);
+      free (file);
+      file = entry->u.file;
+    }
+  else
+    {
+      /* This is a new file; put it in the list.  */
+      file->next_file = pfile->all_files;
+      pfile->all_files = file;
     }
 
   /* Store this new result in the hash table.  */
@@ -520,6 +525,22 @@ should_stack_file (cpp_reader *pfile, _c
 {
   _cpp_file *f;
 
+  /* Skip once-only files.  */
+  if (file->once_only)
+    return false;
+
+  /* We must mark the file once-only if #import now, before header 
+     guard checks.  Otherwise, undefining the header guard might
+     cause the file to be re-stacked.  */
+  if (import)
+    {
+      _cpp_mark_file_once_only (pfile, file);
+
+      /* Don't stack files that have been stacked before.  */
+      if (file->stack_count)
+	return false;
+    }
+
   /* Skip if the file had a header guard and the macro is defined.
      PCH relies on this appearing before the PCH handler below.  */
   if (file->cmacro && file->cmacro->type == NT_MACRO)
@@ -534,34 +555,23 @@ should_stack_file (cpp_reader *pfile, _c
       return false;
     }
 
-  /* Did this file contain #pragma once?  */
-  if (file->pragma_once)
-    return false;
-
-  /* Are we #import-ing a previously #import-ed file?  */
-  if (import && file->import)
-    return false;
-
-  /* Read the file's contents.  */
   if (!read_file (pfile, file))
     return false;
 
-  /* Nothing to check if this isn't #import and there haven't been any
-     #pragma_once directives.  */
-  if (!import && !pfile->saw_pragma_once)
+  /* Now we've read the file's contents, we can stack it if there
+     are no once-only files.  */
+  if (!pfile->seen_once_only)
     return true;
 
-  /* We may have #imported it under a different name, though.  Look
+  /* We may have read the file under a different name.  Look
      for likely candidates and compare file contents to be sure.  */
-  for (f = pfile->once_only_files; f; f = f->once_only_next)
+  for (f = pfile->all_files; f; f = f->next_file)
     {
       if (f == file)
 	continue;
 
-      if (!f->pragma_once && !(f->import && import))
-	continue;
-
-      if (f->err_no == 0
+      if ((import || f->once_only)
+	  && f->err_no == 0
 	  && f->st.st_mtime == file->st.st_mtime
 	  && f->st.st_size == file->st.st_size
 	  && read_file (pfile, f)
@@ -571,9 +581,6 @@ should_stack_file (cpp_reader *pfile, _c
 	break;
     }
 
-  if (import || f != NULL)
-    _cpp_mark_file_once_only (pfile, file, import);
-
   return f == NULL;
 }
 
@@ -619,27 +626,12 @@ stack_file (cpp_reader *pfile, _cpp_file
   return true;
 }
 
-/* Mark FILE to be included once only.  IMPORT is true if because of
-   #import, otherwise it is assumed to be #pragma once.  */
+/* Mark FILE to be included once only.  */
 void
-_cpp_mark_file_once_only (cpp_reader *pfile, _cpp_file *file, bool import)
+_cpp_mark_file_once_only (cpp_reader *pfile, _cpp_file *file)
 {
-  /* Put it on the once-only list if it's not on there already (an
-     earlier #include with a #pragma once might have put it on there
-     already).  */
-  if (!file->import && !file->pragma_once)
-    {
-      file->once_only_next = pfile->once_only_files;
-      pfile->once_only_files = file;
-    }
-
-  if (import)
-    file->import = true;
-  else
-    {
-      pfile->saw_pragma_once = true;
-      file->pragma_once = true;
-    }
+  pfile->seen_once_only = true;
+  file->once_only = true;
 }
 
 /* Return the directory from which searching for FNAME should start,
Index: cpphash.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpphash.h,v
retrieving revision 1.196
diff -u -p -r1.196 cpphash.h
--- cpphash.h	1 Aug 2003 14:04:02 -0000	1.196
+++ cpphash.h	2 Aug 2003 16:04:37 -0000
@@ -359,8 +359,8 @@ struct cpp_reader
   struct cpp_dir *bracket_include;	/* <> */
   struct cpp_dir no_search_path;	/* No path.  */
 
-  /* Chain of files that were #import-ed or contain #pragma once.  */
-  struct _cpp_file *once_only_files;
+  /* Chain of all hashed _cpp_file instances.  */
+  struct _cpp_file *all_files;
 
   /* File and directory hash table.  */
   struct htab *file_hash;
@@ -371,8 +371,9 @@ struct cpp_reader
      directory.  */
   bool quote_ignores_source_dir;
 
-  /* Non-zero if any file has contained #pragma once.  */
-  bool saw_pragma_once;
+  /* Non-zero if any file has contained #pragma once or #import has
+     been used.  */
+  bool seen_once_only;
 
   /* Multiple include optimization.  */
   const cpp_hashnode *mi_cmacro;
@@ -514,7 +515,7 @@ extern void _cpp_init_hashtable (cpp_rea
 extern void _cpp_destroy_hashtable (cpp_reader *);
 
 /* In cppfiles.c */
-extern void _cpp_mark_file_once_only (cpp_reader *, struct _cpp_file *, bool);
+extern void _cpp_mark_file_once_only (cpp_reader *, struct _cpp_file *);
 extern void _cpp_fake_include (cpp_reader *, const char *);
 extern bool _cpp_stack_file (cpp_reader *, const char *);
 extern bool _cpp_stack_include (cpp_reader *, const char *, int,
Index: cpplib.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.c,v
retrieving revision 1.349
diff -u -p -r1.349 cpplib.c
--- cpplib.c	29 Jul 2003 22:26:11 -0000	1.349
+++ cpplib.c	2 Aug 2003 16:04:38 -0000
@@ -1167,7 +1167,7 @@ do_pragma_once (cpp_reader *pfile)
     cpp_error (pfile, DL_WARNING, "#pragma once in main file");
 
   check_eol (pfile);
-  _cpp_mark_file_once_only (pfile, pfile->buffer->file, false);
+  _cpp_mark_file_once_only (pfile, pfile->buffer->file);
 }
 
 /* Handle #pragma GCC poison, to poison one or more identifiers so
Index: testsuite/gcc.dg/cpp/import1.c
===================================================================
RCS file: testsuite/gcc.dg/cpp/import1.c
diff -N testsuite/gcc.dg/cpp/import1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cpp/import1.c	2 Aug 2003 16:04:40 -0000
@@ -0,0 +1,15 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.  */
+
+/* { dg-do preprocess } */
+
+/* This tests that our eagerness to apply the multiple include guard
+   optimization to the #import doesn't stop us marking the file
+   once-only.
+
+   Neil Booth, 2 August 2003.  */
+
+#include "import1.h"
+#import "import1.h"
+#undef IMPORT1_H
+#define BUG
+#include "import1.h"
Index: testsuite/gcc.dg/cpp/import1.h
===================================================================
RCS file: testsuite/gcc.dg/cpp/import1.h
diff -N testsuite/gcc.dg/cpp/import1.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cpp/import1.h	2 Aug 2003 16:04:40 -0000
@@ -0,0 +1,6 @@
+#ifndef IMPORT1_H
+#define IMPORT1_H
+#ifdef BUG
+#error Should not happen
+#endif
+#endif
Index: testsuite/gcc.dg/cpp/import2.c
===================================================================
RCS file: testsuite/gcc.dg/cpp/import2.c
diff -N testsuite/gcc.dg/cpp/import2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cpp/import2.c	2 Aug 2003 16:04:40 -0000
@@ -0,0 +1,9 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.  */
+
+/* { dg-do preprocess } */
+
+/* This tests that the file is only included once.  */
+
+#include "import2.h"
+#import "import2.h"
+#include "import2.h"
Index: testsuite/gcc.dg/cpp/import2.h
===================================================================
RCS file: testsuite/gcc.dg/cpp/import2.h
diff -N testsuite/gcc.dg/cpp/import2.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cpp/import2.h	2 Aug 2003 16:04:40 -0000
@@ -0,0 +1,4 @@
+#ifdef BUG
+#error Should not happen!
+#endif
+#define BUG


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]