Revert "[flang] Search for #include "file" in right directory"

This reverts commit d987b61b1dce9948801ac37704477e7c257100b1.

As pointed out in https://reviews.llvm.org/D95388, the reverted commit
causes build failures in the following Flang buildbots:
  * http://lab.llvm.org:8011/#/builders/32/builds/2642
  * http://lab.llvm.org:8011/#/builders/33/builds/2131
  * http://lab.llvm.org:8011/#/builders/135/builds/1473
  * http://lab.llvm.org:8011/#/builders/66/builds/1559
  * http://lab.llvm.org:8011/#/builders/134/builds/1409
  * http://lab.llvm.org:8011/#/builders/132/builds/1817
I'm guessing that the patch was only tested with
`FLANG_BUILD_NEW_DRIVER=Off` (i.e. the default). The builders listed
above set `FLANG_BUILD_NEW_DRIVER` to `On`.

Although fixing the build is relatively easy, the reverted patch
modifies the behaviour of the frontend, which breaks driver tests. In
particular, in https://reviews.llvm.org/D93453 support for `-I` was
added that depends on the current behaviour. The reverted patch
changes that behaviour. Either the tests have to be updated or the
change fine-tuned.

GitOrigin-RevId: e878589098c2ed510159e67d9c6c5e0f3dfbf5a6
diff --git a/include/flang/Parser/provenance.h b/include/flang/Parser/provenance.h
index 08afcf1..73661d9 100644
--- a/include/flang/Parser/provenance.h
+++ b/include/flang/Parser/provenance.h
@@ -148,9 +148,9 @@
     return *this;
   }
 
-  void AppendSearchPathDirectory(std::string); // new last directory
-  const SourceFile *Open(std::string path, llvm::raw_ostream &error,
-      const std::optional<std::string> &prependPath);
+  void PushSearchPathDirectory(std::string);
+  std::string PopSearchPathDirectory();
+  const SourceFile *Open(std::string path, llvm::raw_ostream &error);
   const SourceFile *ReadStandardInput(llvm::raw_ostream &error);
 
   ProvenanceRange AddIncludedFile(
@@ -210,7 +210,7 @@
   ProvenanceRange range_;
   std::map<char, Provenance> compilerInsertionProvenance_;
   std::vector<std::unique_ptr<SourceFile>> ownedSourceFiles_;
-  std::list<std::string> searchPath_;
+  std::vector<std::string> searchPath_;
   Encoding encoding_{Encoding::UTF_8};
 };
 
diff --git a/include/flang/Parser/source.h b/include/flang/Parser/source.h
index 4f387bd..e0d1a53 100644
--- a/include/flang/Parser/source.h
+++ b/include/flang/Parser/source.h
@@ -17,8 +17,6 @@
 #include "characters.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include <cstddef>
-#include <list>
-#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -30,8 +28,8 @@
 namespace Fortran::parser {
 
 std::string DirectoryName(std::string path);
-std::optional<std::string> LocateSourceFile(
-    std::string name, const std::list<std::string> &searchPath);
+std::string LocateSourceFile(
+    std::string name, const std::vector<std::string> &searchPath);
 
 class SourceFile;
 
diff --git a/lib/Parser/parsing.cpp b/lib/Parser/parsing.cpp
index 0bd542c..7f3a4a6 100644
--- a/lib/Parser/parsing.cpp
+++ b/lib/Parser/parsing.cpp
@@ -25,7 +25,7 @@
   AllSources &allSources{allCooked_.allSources()};
   if (options.isModuleFile) {
     for (const auto &path : options.searchDirectories) {
-      allSources.AppendSearchPathDirectory(path);
+      allSources.PushSearchPathDirectory(path);
     }
   }
 
@@ -35,8 +35,7 @@
   if (path == "-") {
     sourceFile = allSources.ReadStandardInput(fileError);
   } else {
-    std::optional<std::string> currentDirectory{"."};
-    sourceFile = allSources.Open(path, fileError, currentDirectory);
+    sourceFile = allSources.Open(path, fileError);
   }
   if (!fileError.str().empty()) {
     ProvenanceRange range{allSources.AddCompilerInsertion(path)};
@@ -47,12 +46,12 @@
 
   if (!options.isModuleFile) {
     // For .mod files we always want to look in the search directories.
-    // For normal source files we don't add them until after the primary
+    // For normal source files we don't push them until after the primary
     // source file has been opened.  If foo.f is missing from the current
     // working directory, we don't want to accidentally read another foo.f
     // from another directory that's on the search path.
     for (const auto &path : options.searchDirectories) {
-      allSources.AppendSearchPathDirectory(path);
+      allSources.PushSearchPathDirectory(path);
     }
   }
 
diff --git a/lib/Parser/preprocessor.cpp b/lib/Parser/preprocessor.cpp
index 14c9e54..c5422cc 100644
--- a/lib/Parser/preprocessor.cpp
+++ b/lib/Parser/preprocessor.cpp
@@ -399,7 +399,6 @@
   if (j == tokens) {
     return;
   }
-  CHECK(prescanner); // TODO: change to reference
   if (dir.TokenAt(j).ToString() != "#") {
     prescanner->Say(dir.GetTokenProvenanceRange(j), "missing '#'"_err_en_US);
     return;
@@ -579,7 +578,6 @@
       return;
     }
     std::string include;
-    std::optional<std::string> prependPath;
     if (dir.TokenAt(j).ToString() == "<") { // #include <foo>
       std::size_t k{j + 1};
       if (k >= tokens) {
@@ -600,12 +598,6 @@
     } else if ((include = dir.TokenAt(j).ToString()).substr(0, 1) == "\"" &&
         include.substr(include.size() - 1, 1) == "\"") { // #include "foo"
       include = include.substr(1, include.size() - 2);
-      // #include "foo" starts search in directory of file containing
-      // the directive
-      auto prov{dir.GetTokenProvenanceRange(dirOffset).start()};
-      if (const auto *currentFile{allSources_.GetSourceFile(prov)}) {
-        prependPath = DirectoryName(currentFile->path());
-      }
     } else {
       prescanner->Say(dir.GetTokenProvenanceRange(j < tokens ? j : tokens - 1),
           "#include: expected name of file to include"_err_en_US);
@@ -623,7 +615,7 @@
     }
     std::string buf;
     llvm::raw_string_ostream error{buf};
-    const SourceFile *included{allSources_.Open(include, error, prependPath)};
+    const SourceFile *included{allSources_.Open(include, error)};
     if (!included) {
       prescanner->Say(dir.GetTokenProvenanceRange(dirOffset),
           "#include: %s"_err_en_US, error.str());
diff --git a/lib/Parser/prescan.cpp b/lib/Parser/prescan.cpp
index 7a78dd2..dc6fbe5 100644
--- a/lib/Parser/prescan.cpp
+++ b/lib/Parser/prescan.cpp
@@ -760,11 +760,14 @@
   std::string buf;
   llvm::raw_string_ostream error{buf};
   Provenance provenance{GetProvenance(nextLine_)};
-  std::optional<std::string> prependPath;
-  if (const SourceFile * currentFile{allSources_.GetSourceFile(provenance)}) {
-    prependPath = DirectoryName(currentFile->path());
+  const SourceFile *currentFile{allSources_.GetSourceFile(provenance)};
+  if (currentFile) {
+    allSources_.PushSearchPathDirectory(DirectoryName(currentFile->path()));
   }
-  const SourceFile *included{allSources_.Open(path, error, prependPath)};
+  const SourceFile *included{allSources_.Open(path, error)};
+  if (currentFile) {
+    allSources_.PopSearchPathDirectory();
+  }
   if (!included) {
     Say(provenance, "INCLUDE: %s"_err_en_US, error.str());
   } else if (included->bytes() > 0) {
diff --git a/lib/Parser/provenance.cpp b/lib/Parser/provenance.cpp
index bed9090..46a0dc9 100644
--- a/lib/Parser/provenance.cpp
+++ b/lib/Parser/provenance.cpp
@@ -156,28 +156,20 @@
   return origin[origin.covers.MemberOffset(at)];
 }
 
-void AllSources::AppendSearchPathDirectory(std::string directory) {
+void AllSources::PushSearchPathDirectory(std::string directory) {
   // gfortran and ifort append to current path, PGI prepends
   searchPath_.push_back(directory);
 }
 
-const SourceFile *AllSources::Open(std::string path, llvm::raw_ostream &error,
-    const std::optional<std::string> &prependPath) {
+std::string AllSources::PopSearchPathDirectory() {
+  std::string directory{searchPath_.back()};
+  searchPath_.pop_back();
+  return directory;
+}
+
+const SourceFile *AllSources::Open(std::string path, llvm::raw_ostream &error) {
   std::unique_ptr<SourceFile> source{std::make_unique<SourceFile>(encoding_)};
-  if (prependPath) {
-    // Set to "." for the initial source file; set to the directory name
-    // of the including file for #include "quoted-file" directives &
-    // INCLUDE statements.
-    searchPath_.push_front(*prependPath);
-  }
-  std::optional<std::string> found{LocateSourceFile(path, searchPath_)};
-  if (prependPath) {
-    searchPath_.pop_front();
-  }
-  if (!found) {
-    error << "Source file '" << path << "' was not found";
-    return nullptr;
-  } else if (source->Open(*found, error)) {
+  if (source->Open(LocateSourceFile(path, searchPath_), error)) {
     return ownedSourceFiles_.emplace_back(std::move(source)).get();
   } else {
     return nullptr;
diff --git a/lib/Parser/source.cpp b/lib/Parser/source.cpp
index 3fbbf78..11cd591 100644
--- a/lib/Parser/source.cpp
+++ b/lib/Parser/source.cpp
@@ -56,9 +56,9 @@
   return pathBuf.str().str();
 }
 
-std::optional<std::string> LocateSourceFile(
-    std::string name, const std::list<std::string> &searchPath) {
-  if (name == "-" || llvm::sys::path::is_absolute(name)) {
+std::string LocateSourceFile(
+    std::string name, const std::vector<std::string> &searchPath) {
+  if (name.empty() || name == "-" || llvm::sys::path::is_absolute(name)) {
     return name;
   }
   for (const std::string &dir : searchPath) {
@@ -70,7 +70,7 @@
       return path.str().str();
     }
   }
-  return std::nullopt;
+  return name;
 }
 
 std::size_t RemoveCarriageReturns(llvm::MutableArrayRef<char> buf) {
@@ -123,6 +123,7 @@
 bool SourceFile::ReadStandardInput(llvm::raw_ostream &error) {
   Close();
   path_ = "standard input";
+
   auto buf_or = llvm::MemoryBuffer::getSTDIN();
   if (!buf_or) {
     auto err = buf_or.getError();
@@ -145,6 +146,7 @@
       auto tmp_buf{llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
           content().size() + 1)};
       llvm::copy(content(), tmp_buf->getBufferStart());
+      Close();
       buf_ = std::move(tmp_buf);
     }
     buf_end_++;
diff --git a/tools/f18/f18.cpp b/tools/f18/f18.cpp
index 7cb0129..9a10aed 100644
--- a/tools/f18/f18.cpp
+++ b/tools/f18/f18.cpp
@@ -84,7 +84,7 @@
   bool verbose{false}; // -v
   bool compileOnly{false}; // -c
   std::string outputPath; // -o path
-  std::vector<std::string> searchDirectories; // -I dir
+  std::vector<std::string> searchDirectories{"."s}; // -I dir
   std::string moduleDirectory{"."s}; // -module dir
   std::string moduleFileSuffix{".mod"}; // -moduleSuffix suff
   bool forcedForm{false}; // -Mfixed or -Mfree appeared