diff mbox series

[preprocessor] Include stacking

Message ID 7f6f0fe0-006c-8779-fcf5-ea8ffc911348@acm.org
State New
Headers show
Series [preprocessor] Include stacking | expand

Commit Message

Nathan Sidwell Aug. 29, 2019, 2:05 p.m. UTC
This patch refactors pieces of the include stacking routines.  Again 
from the modules branch, so these happen to provide the right slots to 
make that work, but I think they're good in their own right.

_cpp_find_file excitingly hid an if as the loop-invariant conditional of 
a for.  Refactored that, so mostly just changing indentation.

_should_stack_file was confusing, and I broke it apart into two 
predicates, then called from _stack_file.

Finally I extended the include_type enum to add IT_MAIN, for the main 
file, which means _cpp_stack_include just passes the include type down 
to _cpp_stack_file.

Applying to trunk.

nathan
diff mbox series

Patch

2019-08-29  Nathan Sidwell  <nathan@acm.org>

	* internal.h (enum include_type): Add IT_MAIN, IT_DIRECTIVE_HWM,
	IT_HEADER_HWM.
	(_cpp_stack_file): Take include_type, not a bool.
	* files.c (_cpp_find_file): Refactor to not hide an if inside a
	for conditional.
	(should_stack_file): Break apart to ...
	(is_known_idempotent_file, has_unique_contents): ... these.
	(_cpp_stack_file): Replace IMPORT boolean with include_type enum.
	Refactor to use new predicates.  Do linemap compensation here ...
	(_cpp_stack_include): ... not here.
	* init.c (cpp_read_main_file): Pass IT_MAIN to _cpp_stack_file.

Index: files.c
===================================================================
--- files.c	(revision 275032)
+++ files.c	(working copy)
@@ -177,6 +177,4 @@  static bool read_file_guts (cpp_reader *
 static bool read_file (cpp_reader *pfile, _cpp_file *file,
 		       location_t loc);
-static bool should_stack_file (cpp_reader *, _cpp_file *file, bool import,
-			       location_t loc);
 static struct cpp_dir *search_path_head (cpp_reader *, const char *fname,
 				 int angle_brackets, enum include_type);
@@ -537,77 +535,84 @@  _cpp_find_file (cpp_reader *pfile, const
 	   && pfile->buffer->file->implicit_preinclude));
 
-  /* Try each path in the include chain.  */
-  for (; !fake ;)
-    {
-      if (find_file_in_dir (pfile, file, &invalid_pch, loc))
-	break;
+  if (!fake)
+    /* Try each path in the include chain.  */
+    for (;;)
+      {
+	if (find_file_in_dir (pfile, file, &invalid_pch, loc))
+	  break;
 
-      file->dir = file->dir->next;
-      if (file->dir == NULL)
-	{
-	  if (search_path_exhausted (pfile, fname, file))
-	    {
-	      /* Although this file must not go in the cache, because
-		 the file found might depend on things (like the current file)
-		 that aren't represented in the cache, it still has to go in
-		 the list of all files so that #import works.  */
-	      file->next_file = pfile->all_files;
-	      pfile->all_files = file;
-	      if (*hash_slot == NULL)
-		{
-		  /* If *hash_slot is NULL, the above htab_find_slot_with_hash
-		     call just created the slot, but we aren't going to store
-		     there anything, so need to remove the newly created entry.
-		     htab_clear_slot requires that it is non-NULL, so store
-		     there some non-NULL pointer, htab_clear_slot will
-		     overwrite it immediately.  */
-		  *hash_slot = file;
-		  htab_clear_slot (pfile->file_hash, hash_slot);
-		}
-	      return file;
-	    }
+	file->dir = file->dir->next;
+	if (file->dir == NULL)
+	  {
+	    if (search_path_exhausted (pfile, fname, file))
+	      {
+		/* Although this file must not go in the cache,
+		   because the file found might depend on things (like
+		   the current file) that aren't represented in the
+		   cache, it still has to go in the list of all files
+		   so that #import works.  */
+		file->next_file = pfile->all_files;
+		pfile->all_files = file;
+		if (*hash_slot == NULL)
+		  {
+		    /* If *hash_slot is NULL, the above
+		       htab_find_slot_with_hash call just created the
+		       slot, but we aren't going to store there
+		       anything, so need to remove the newly created
+		       entry.  htab_clear_slot requires that it is
+		       non-NULL, so store there some non-NULL pointer,
+		       htab_clear_slot will overwrite it
+		       immediately.  */
+		    *hash_slot = file;
+		    htab_clear_slot (pfile->file_hash, hash_slot);
+		  }
+		return file;
+	      }
 
-	  if (invalid_pch)
-	    {
-	      cpp_error (pfile, CPP_DL_ERROR,
-	       "one or more PCH files were found, but they were invalid");
-	      if (!cpp_get_options (pfile)->warn_invalid_pch)
+	    if (invalid_pch)
+	      {
 		cpp_error (pfile, CPP_DL_ERROR,
-			   "use -Winvalid-pch for more information");
-	    }
-	  if (implicit_preinclude)
-	    {
-	      free ((char *) file->name);
-	      free (file);
-	      if (*hash_slot == NULL)
-		{
-		  /* See comment on the above htab_clear_slot call.  */
-		  *hash_slot = file;
-		  htab_clear_slot (pfile->file_hash, hash_slot);
-		}
-	      return NULL;
-	    }
-	  else
-	    open_file_failed (pfile, file, angle_brackets, loc);
-	  break;
-	}
+			   "one or more PCH files were found,"
+			   " but they were invalid");
+		if (!cpp_get_options (pfile)->warn_invalid_pch)
+		  cpp_error (pfile, CPP_DL_ERROR,
+			     "use -Winvalid-pch for more information");
+	      }
+
+	    if (implicit_preinclude)
+	      {
+		free ((char *) file->name);
+		free (file);
+		if (*hash_slot == NULL)
+		  {
+		    /* See comment on the above htab_clear_slot call.  */
+		    *hash_slot = file;
+		    htab_clear_slot (pfile->file_hash, hash_slot);
+		  }
+		return NULL;
+	      }
 
-      /* Only check the cache for the starting location (done above)
-	 and the quote and bracket chain heads because there are no
-	 other possible starting points for searches.  */
-      if (file->dir == pfile->bracket_include)
-	saw_bracket_include = true;
-      else if (file->dir == pfile->quote_include)
-	saw_quote_include = true;
-      else
-	continue;
+	    open_file_failed (pfile, file, angle_brackets, loc);
+	    break;
+	  }
 
-      entry = search_cache ((struct cpp_file_hash_entry *) *hash_slot, file->dir);
-      if (entry)
-	{
-	  found_in_cache = file->dir;
-	  break;
-	}
-    }
+	/* Only check the cache for the starting location (done above)
+	   and the quote and bracket chain heads because there are no
+	   other possible starting points for searches.  */
+	if (file->dir == pfile->bracket_include)
+	  saw_bracket_include = true;
+	else if (file->dir == pfile->quote_include)
+	  saw_quote_include = true;
+	else
+	  continue;
+
+	entry
+	  = search_cache ((struct cpp_file_hash_entry *) *hash_slot, file->dir);
+	if (entry)
+	  {
+	    found_in_cache = file->dir;
+	    break;
+	  }
+      }
 
   if (entry)
@@ -779,16 +784,12 @@  read_file (cpp_reader *pfile, _cpp_file
 }
 
-/* Returns TRUE if FILE's contents have been successfully placed in
-   FILE->buffer and the file should be stacked, otherwise false.
-   Use LOC for any diagnostics.  */
+/* Returns TRUE if FILE is already known to be idempotent, and should
+   therefore not be read again.  */
 static bool
-should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
-		   location_t loc)
+is_known_idempotent_file (cpp_reader *pfile, _cpp_file *file, bool import)
 {
-  _cpp_file *f;
-
   /* Skip once-only files.  */
   if (file->once_only)
-    return false;
+    return true;
 
   /* We must mark the file once-only if #import now, before header
@@ -801,5 +802,5 @@  should_stack_file (cpp_reader *pfile, _c
       /* Don't stack files that have been stacked before.  */
       if (file->stack_count)
-	return false;
+	return true;
     }
 
@@ -807,5 +808,5 @@  should_stack_file (cpp_reader *pfile, _c
      PCH relies on this appearing before the PCH handler below.  */
   if (file->cmacro && cpp_macro_p (file->cmacro))
-    return false;
+    return true;
 
   /* Handle PCH files immediately; don't stack them.  */
@@ -816,10 +817,17 @@  should_stack_file (cpp_reader *pfile, _c
       free ((void *) file->pchname);
       file->pchname = NULL;
-      return false;
+      return true;
     }
 
-  if (!read_file (pfile, file, loc))
-    return false;
+  return false;
+}
 
+/* Return TRUE if file has unique contents, so we should read process
+   it.  The file's contents must already have been read.  */
+
+static bool
+has_unique_contents (cpp_reader *pfile, _cpp_file *file, bool import,
+		     location_t loc)
+{
   /* Check the file against the PCH file.  This is done before
      checking against files we've already seen, since it may save on
@@ -842,8 +850,8 @@  should_stack_file (cpp_reader *pfile, _c
   /* We may have read the file under a different name.  Look
      for likely candidates and compare file contents to be sure.  */
-  for (f = pfile->all_files; f; f = f->next_file)
+  for (_cpp_file *f = pfile->all_files; f; f = f->next_file)
     {
       if (f == file)
-	continue;
+	continue; /* It'sa me!  */
 
       if ((import || f->once_only)
@@ -853,5 +861,4 @@  should_stack_file (cpp_reader *pfile, _c
 	{
 	  _cpp_file *ref_file;
-	  bool same_file_p = false;
 
 	  if (f->buffer && !f->buffer_valid)
@@ -866,10 +873,9 @@  should_stack_file (cpp_reader *pfile, _c
 	    ref_file = f;
 
-	  same_file_p = read_file (pfile, ref_file, loc)
-			/* Size might have changed in read_file().  */
-			&& ref_file->st.st_size == file->st.st_size
-			&& !memcmp (ref_file->buffer,
-				    file->buffer,
-				    file->st.st_size);
+	  bool same_file_p = (read_file (pfile, ref_file, loc)
+			      /* Size might have changed in read_file().  */
+			      && ref_file->st.st_size == file->st.st_size
+			      && !memcmp (ref_file->buffer, file->buffer,
+					  file->st.st_size));
 
 	  if (f->buffer && !f->buffer_valid)
@@ -880,9 +886,10 @@  should_stack_file (cpp_reader *pfile, _c
 
 	  if (same_file_p)
-	    break;
+	    /* Already seen under a different name.  */
+	    return false;
 	}
     }
 
-  return f == NULL;
+  return true;
 }
 
@@ -892,23 +899,25 @@  should_stack_file (cpp_reader *pfile, _c
    stacked.  Use LOC for any diagnostics.  */
 bool
-_cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
+_cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
 		 location_t loc)
 {
-  cpp_buffer *buffer;
-  int sysp;
+  if (is_known_idempotent_file (pfile, file, type == IT_IMPORT))
+    return false;
 
-  if (!should_stack_file (pfile, file, import, loc))
+  if (!read_file (pfile, file, loc))
     return false;
 
-  if (pfile->buffer == NULL || file->dir == NULL)
-    sysp = 0;
-  else
-    sysp = MAX (pfile->buffer->sysp,  file->dir->sysp);
+  if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc))
+    return false;
+
+  int sysp = 0;
+  if (pfile->buffer && file->dir)
+    sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
 
   /* Add the file to the dependencies on its first inclusion.  */
-  if (!file->stack_count
-      && CPP_OPTION (pfile, deps.style) > !!sysp
+  if (CPP_OPTION (pfile, deps.style) > (sysp != 0)
+      && !file->stack_count
       && file->path[0]
-      && (!file->main_file || !CPP_OPTION (pfile, deps.ignore_main_file)))
+      && !(file->main_file && CPP_OPTION (pfile, deps.ignore_main_file)))
     deps_add_dep (pfile->deps, file->path);
 
@@ -918,7 +927,8 @@  _cpp_stack_file (cpp_reader *pfile, _cpp
 
   /* Stack the buffer.  */
-  buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size,
-			    CPP_OPTION (pfile, preprocessed)
-			    && !CPP_OPTION (pfile, directives_only));
+  cpp_buffer *buffer
+    = cpp_push_buffer (pfile, file->buffer, file->st.st_size,
+		       CPP_OPTION (pfile, preprocessed)
+		       && !CPP_OPTION (pfile, directives_only));
   buffer->file = file;
   buffer->sysp = sysp;
@@ -929,5 +939,25 @@  _cpp_stack_file (cpp_reader *pfile, _cpp
   pfile->mi_cmacro = 0;
 
-  /* Generate the call back.  */
+  /* Compensate for the increment in linemap_add that occurs when in
+     do_file_change.   In the case of a normal #include, we're
+     currently at the start of the line *following* the #include.  A
+     separate location_t for this location makes no sense (until we do
+     the LC_LEAVE), and complicates LAST_SOURCE_LINE_LOCATION.  This
+     does not apply if we found a PCH file (in which case linemap_add
+     is not called) or we were included from the command-line.  In the
+     case that the #include is the last line in the file,
+     highest_location still points to the current line, not the start
+     of the next line, so we do not decrement in this case.  See
+     plugin/location-overflow-test-pr83173.h for an example.  */
+  bool decremented = false;
+  if (file->pchname == NULL && file->err_no == 0 && type < IT_DIRECTIVE_HWM)
+    {
+      decremented = (pfile->line_table->highest_line
+		     == pfile->line_table->highest_location);
+      if (decremented)
+	pfile->line_table->highest_location--;
+    }
+
+  /* Add line map and do callbacks.  */
   _cpp_do_file_change (pfile, LC_ENTER, file->path, 1, sysp);
 
@@ -1010,9 +1040,4 @@  _cpp_stack_include (cpp_reader *pfile, c
 		    enum include_type type, location_t loc)
 {
-  struct cpp_dir *dir;
-  _cpp_file *file;
-  bool stacked;
-  bool decremented = false;
-
   /* For -include command-line flags we have type == IT_CMDLINE.
      When the first -include file is processed we have the case, where
@@ -1027,46 +1052,14 @@  _cpp_stack_include (cpp_reader *pfile, c
     pfile->cur_token[-1].src_loc = 0;
 
-  dir = search_path_head (pfile, fname, angle_brackets, type);
+  cpp_dir *dir = search_path_head (pfile, fname, angle_brackets, type);
   if (!dir)
     return false;
 
-  file = _cpp_find_file (pfile, fname, dir, false, angle_brackets,
-			 type == IT_DEFAULT, loc);
+  _cpp_file *file = _cpp_find_file (pfile, fname, dir, false, angle_brackets,
+				    type == IT_DEFAULT, loc);
   if (type == IT_DEFAULT && file == NULL)
     return false;
 
-  /* Compensate for the increment in linemap_add that occurs if
-     _cpp_stack_file actually stacks the file.  In the case of a normal
-     #include, we're currently at the start of the line *following* the
-     #include.  A separate location_t for this location makes no
-     sense (until we do the LC_LEAVE), and complicates
-     LAST_SOURCE_LINE_LOCATION.  This does not apply if we found a PCH
-     file (in which case linemap_add is not called) or we were included
-     from the command-line.  In the case that the #include is the last
-     line in the file, highest_location still points to the current
-     line, not the start of the next line, so we do not decrement in
-     this case.  See plugin/location-overflow-test-pr83173.h for an
-     example.  */
-  if (file->pchname == NULL && file->err_no == 0
-      && type != IT_CMDLINE && type != IT_DEFAULT)
-    {
-      int highest_line = linemap_get_expansion_line (pfile->line_table,
-						     pfile->line_table->highest_location);
-      int source_line = linemap_get_expansion_line (pfile->line_table, loc);
-      if (highest_line > source_line)
-	{
-	  pfile->line_table->highest_location--;
-	  decremented = true;
-	}
-    }
-
-  stacked = _cpp_stack_file (pfile, file, type == IT_IMPORT, loc);
-
-  if (decremented && !stacked)
-    /* _cpp_stack_file didn't stack the file, so let's rollback the
-       compensation dance we performed above.  */
-    pfile->line_table->highest_location++;
-
-  return stacked;
+  return _cpp_stack_file (pfile, file, type, loc);
 }
 
Index: init.c
===================================================================
--- init.c	(revision 275032)
+++ init.c	(working copy)
@@ -652,5 +652,5 @@  cpp_read_main_file (cpp_reader *pfile, c
     return NULL;
 
-  _cpp_stack_file (pfile, pfile->main_file, false, loc);
+  _cpp_stack_file (pfile, pfile->main_file, IT_MAIN, 0);
 
   /* For foo.i, read the original filename foo.c now, for the benefit
Index: internal.h
===================================================================
--- internal.h	(revision 275032)
+++ internal.h	(working copy)
@@ -124,4 +124,8 @@  enum include_type
    IT_CMDLINE,  /* -include */
    IT_DEFAULT,  /* forced header  */
+   IT_MAIN,     /* main  */
+
+   IT_DIRECTIVE_HWM = IT_IMPORT + 1,  /* Directives below this.  */
+   IT_HEADER_HWM = IT_DEFAULT + 1,    /* Header files below this.  */
   };
 
@@ -672,6 +676,5 @@  extern bool _cpp_find_failed (_cpp_file
 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 *, _cpp_file*, bool,
-			     location_t);
+extern bool _cpp_stack_file (cpp_reader *, _cpp_file*, include_type, location_t);
 extern bool _cpp_stack_include (cpp_reader *, const char *, int,
 				enum include_type, location_t);