diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 247687299d06195b60684d1a16d59d5468da5290..05e68f5754ea8929e26ff6edbee183355c78eea0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,16 @@
+2005-08-30  Jakub Jelinek  <jakub@redhat.com>
+
+	PR preprocessor/20348
+	PR preprocessor/20356
+	* gcc.dg/cpp/pr20348.c: New test.
+	* gcc.dg/cpp/pr20348.h: New file.
+	* gcc.dg/cpp/inc/pr20348.h: New file.
+	* gcc.dg/cpp/inc/pr20348-aux.h: New file.
+	* gcc.dg/cpp/pr20356.c: New test.
+	* gcc.dg/cpp/pr20356.h: New file.
+	* gcc.dg/cpp/inc/pr20356.h: New file.
+	* gcc.dg/cpp/inc/pr20356-aux.h: New file.
+
 2005-08-29  Jerry DeLisle  <jvdelisle@verizon.net>
 
 	* gfortran.fortran-torture/execute/intrinsic_count.f90:
diff --git a/gcc/testsuite/gcc.dg/cpp/inc/pr20348-aux.h b/gcc/testsuite/gcc.dg/cpp/inc/pr20348-aux.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f04c756975c3695c9118c262b6c6842706c0881
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/inc/pr20348-aux.h
@@ -0,0 +1 @@
+#include "pr20348.h"
diff --git a/gcc/testsuite/gcc.dg/cpp/inc/pr20348.h b/gcc/testsuite/gcc.dg/cpp/inc/pr20348.h
new file mode 100644
index 0000000000000000000000000000000000000000..810bb36d792dad3f20a8715b13f78939359108c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/inc/pr20348.h
@@ -0,0 +1,9 @@
+#ifndef MIDDLE
+# ifndef INC_PR20348_H_SEEN
+#  define INC_PR20348_H_SEEN
+# else
+#  error inc/pr20348.h included twice before MIDDLE definition
+# endif
+#else
+# error inc/pr20348.h included after MIDDLE definition
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/inc/pr20356-aux.h b/gcc/testsuite/gcc.dg/cpp/inc/pr20356-aux.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f4a67f8effd0d5d829eb3c281db08d22b90431a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/inc/pr20356-aux.h
@@ -0,0 +1 @@
+#include "pr20356.h"
diff --git a/gcc/testsuite/gcc.dg/cpp/inc/pr20356.h b/gcc/testsuite/gcc.dg/cpp/inc/pr20356.h
new file mode 100644
index 0000000000000000000000000000000000000000..5829257392c6ac5ca11cc2a7b64470e842f89801
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/inc/pr20356.h
@@ -0,0 +1,6 @@
+#ifndef INC_PR20356_H
+# define INC_PR20356_H
+#endif
+#ifndef PR20356_H
+# include_next <pr20356.h>
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/pr20348.c b/gcc/testsuite/gcc.dg/cpp/pr20348.c
new file mode 100644
index 0000000000000000000000000000000000000000..f75f14290ca49fd7c68bf4ca9a835b403b4d7ce2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pr20348.c
@@ -0,0 +1,16 @@
+/* PR preprocessor/20348 */
+/* { dg-do compile } */
+/* { dg-options "-I$srcdir/gcc.dg/cpp -I$srcdir/gcc.dg/cpp/inc" } */
+
+#include <pr20348-aux.h>
+#define MIDDLE
+#include <pr20348.h>
+
+#ifndef PR20348_H_SEEN
+# error pr20348.h not included after MIDDLE definition
+#endif
+#ifndef INC_PR20348_H_SEEN
+# error inc/pr20348.h not included before MIDDLE definition
+#endif
+
+int i;
diff --git a/gcc/testsuite/gcc.dg/cpp/pr20348.h b/gcc/testsuite/gcc.dg/cpp/pr20348.h
new file mode 100644
index 0000000000000000000000000000000000000000..97ef80edbaacf7a6f92393aa0a85575d4d9da4c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pr20348.h
@@ -0,0 +1,9 @@
+#ifdef MIDDLE
+# ifndef PR20348_H_SEEN
+#  define PR20348_H_SEEN
+# else
+#  error pr20348.h included twice after MIDDLE definition
+# endif
+#else
+# error pr20348.h included before MIDDLE definition
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/pr20356.c b/gcc/testsuite/gcc.dg/cpp/pr20356.c
new file mode 100644
index 0000000000000000000000000000000000000000..469ab0c0f6f0a42b902dd98cb5803a944dbd2d5c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pr20356.c
@@ -0,0 +1,14 @@
+/* PR preprocessor/20356 */
+/* { dg-do compile } */
+/* { dg-options "-I$srcdir/gcc.dg/cpp -I$srcdir/gcc.dg/cpp/inc" } */
+
+#include <pr20356-aux.h>
+
+#ifndef PR20356_H
+# error PR20356_H not defined
+#endif
+#ifndef INC_PR20356_H
+# error INC_PR20356_H not defined
+#endif
+
+int i;
diff --git a/gcc/testsuite/gcc.dg/cpp/pr20356.h b/gcc/testsuite/gcc.dg/cpp/pr20356.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3f289145aca9cd64d7a1fac16816a25094c1191
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pr20356.h
@@ -0,0 +1,5 @@
+#ifndef PR20356_H
+# define PR20356_H
+#else
+# include_next <pr20356.h>
+#endif
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 74b93085f2a26bd7365daaac0048806683fb722a..1b62fcce3e2da875b7d59e14a262aca7e8eacfd1 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,10 @@
+2005-08-30  Jakub Jelinek  <jakub@redhat.com>
+
+	PR preprocessor/20348
+	PR preprocessor/20356
+	* files.c (_cpp_find_file, search_cache): Revert 2004-06-26 and
+	2004-06-05 changes.
+
 2005-07-23  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
 	* configure.ac (ACX_PROG_CC_WARNING_OPTS): add
diff --git a/libcpp/files.c b/libcpp/files.c
index dd4f6d92ec5649946d3768ea7c35a622e4ff928f..779fec7ca63202e149c034185f01ffd77c8efa06 100644
--- a/libcpp/files.c
+++ b/libcpp/files.c
@@ -416,21 +416,6 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
   /* Try each path in the include chain.  */
   for (; !fake ;)
     {
-      if (file->dir == pfile->quote_include
-	  || file->dir == pfile->bracket_include)
-	{
-	  entry = search_cache (*hash_slot, file->dir);
-	  if (entry)
-	    {
-	      /* Found the same file again.  Record it as reachable
-		 from this position, too.  */
-	      free ((char *) file->name);
-	      free (file);
-	      file = entry->u.file;
-	      goto found;
-	    }
-	}
-
       if (find_file_in_dir (pfile, file, &invalid_pch))
 	break;
 
@@ -459,40 +444,33 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
 	    }
 	  break;
 	}
-    }
 
-  /* This is a new file; put it in the list.  */
-  file->next_file = pfile->all_files;
-  pfile->all_files = file;
+      /* 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
+	  && file->dir != pfile->quote_include)
+	continue;
 
-  /* If this file was found in the directory-of-the-current-file,
-     check whether that directory is reachable via one of the normal
-     search paths.  If so, we must record this entry as being
-     reachable that way, otherwise we will mistakenly reprocess this
-     file if it is included later from the normal search path.  */
-  if (file->dir && start_dir->next == pfile->quote_include)
-    {
-      cpp_dir *d;
-      cpp_dir *proper_start_dir = pfile->quote_include;
+      entry = search_cache (*hash_slot, file->dir);
+      if (entry)
+	break;
+    }
 
-      for (d = proper_start_dir;; d = d->next)
-	{
-	  if (d == pfile->bracket_include)
-	    proper_start_dir = d;
-	  if (d == 0)
-	    {
-	      proper_start_dir = 0;
-	      break;
-	    }
-	  /* file->dir->name will have a trailing slash.  */
-	  if (!strncmp (d->name, file->dir->name, file->dir->len - 1))
-	    break;
-	}
-      if (proper_start_dir)
-	start_dir = proper_start_dir;
+  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;
     }
 
- found:
   /* Store this new result in the hash table.  */
   entry = new_file_hash_entry (pfile);
   entry->next = *hash_slot;
@@ -880,14 +858,10 @@ open_file_failed (cpp_reader *pfile, _cpp_file *file)
 static struct file_hash_entry *
 search_cache (struct file_hash_entry *head, const cpp_dir *start_dir)
 {
-  struct file_hash_entry *p;
+  while (head && head->start_dir != start_dir)
+    head = head->next;
 
-  /* Look for a file that was found from a search starting at the
-     given location.  */
-  for (p = head; p; p = p->next)
-    if (p->start_dir == start_dir)
-      return p;
-  return 0;
+  return head;
 }
 
 /* Allocate a new _cpp_file structure.  */