aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flang/include/flang/Parser/provenance.h8
-rw-r--r--flang/include/flang/Parser/source.h6
-rw-r--r--flang/lib/Frontend/FrontendActions.cpp2
-rw-r--r--flang/lib/Parser/parsing.cpp9
-rw-r--r--flang/lib/Parser/preprocessor.cpp11
-rw-r--r--flang/lib/Parser/prescan.cpp12
-rw-r--r--flang/lib/Parser/provenance.cpp26
-rw-r--r--flang/lib/Parser/source.cpp10
-rw-r--r--flang/test/Flang-Driver/Inputs/basictestmoduleone.mod6
-rw-r--r--flang/test/Flang-Driver/Inputs/module-dir/basictestmoduleone.mod5
-rw-r--r--flang/test/Flang-Driver/Inputs/module-dir/basictestmoduletwo.mod4
-rw-r--r--flang/test/Flang-Driver/include-header.f902
-rw-r--r--flang/test/Flang-Driver/include-module.f9011
-rw-r--r--flang/tools/f18/f18.cpp2
-rw-r--r--flang/unittests/Frontend/FrontendActionTest.cpp2
15 files changed, 74 insertions, 42 deletions
diff --git a/flang/include/flang/Parser/provenance.h b/flang/include/flang/Parser/provenance.h
index 73661d9..bce7980 100644
--- a/flang/include/flang/Parser/provenance.h
+++ b/flang/include/flang/Parser/provenance.h
@@ -148,9 +148,9 @@ public:
return *this;
}
- void PushSearchPathDirectory(std::string);
- std::string PopSearchPathDirectory();
- const SourceFile *Open(std::string path, llvm::raw_ostream &error);
+ void AppendSearchPathDirectory(std::string); // new last directory
+ const SourceFile *Open(std::string path, llvm::raw_ostream &error,
+ std::optional<std::string> &&prependPath = std::nullopt);
const SourceFile *ReadStandardInput(llvm::raw_ostream &error);
ProvenanceRange AddIncludedFile(
@@ -210,7 +210,7 @@ private:
ProvenanceRange range_;
std::map<char, Provenance> compilerInsertionProvenance_;
std::vector<std::unique_ptr<SourceFile>> ownedSourceFiles_;
- std::vector<std::string> searchPath_;
+ std::list<std::string> searchPath_;
Encoding encoding_{Encoding::UTF_8};
};
diff --git a/flang/include/flang/Parser/source.h b/flang/include/flang/Parser/source.h
index e0d1a53..4f387bd 100644
--- a/flang/include/flang/Parser/source.h
+++ b/flang/include/flang/Parser/source.h
@@ -17,6 +17,8 @@
#include "characters.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstddef>
+#include <list>
+#include <optional>
#include <string>
#include <utility>
#include <vector>
@@ -28,8 +30,8 @@ class raw_ostream;
namespace Fortran::parser {
std::string DirectoryName(std::string path);
-std::string LocateSourceFile(
- std::string name, const std::vector<std::string> &searchPath);
+std::optional<std::string> LocateSourceFile(
+ std::string name, const std::list<std::string> &searchPath);
class SourceFile;
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index c200d60..a89ebf0 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -28,7 +28,7 @@ void InputOutputTestAction::ExecuteAction() {
CompilerInstance &ci = instance();
Fortran::parser::AllSources &allSources{ci.allSources()};
const Fortran::parser::SourceFile *sf;
- sf = allSources.Open(path, error_stream);
+ sf = allSources.Open(path, error_stream, std::optional<std::string>{"."s});
llvm::ArrayRef<char> fileContent = sf->content();
// Output file descriptor to receive the content of input file.
diff --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp
index 7f3a4a6..5845c75 100644
--- a/flang/lib/Parser/parsing.cpp
+++ b/flang/lib/Parser/parsing.cpp
@@ -25,7 +25,7 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
AllSources &allSources{allCooked_.allSources()};
if (options.isModuleFile) {
for (const auto &path : options.searchDirectories) {
- allSources.PushSearchPathDirectory(path);
+ allSources.AppendSearchPathDirectory(path);
}
}
@@ -35,7 +35,8 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
if (path == "-") {
sourceFile = allSources.ReadStandardInput(fileError);
} else {
- sourceFile = allSources.Open(path, fileError);
+ std::optional<std::string> currentDirectory{"."};
+ sourceFile = allSources.Open(path, fileError, std::move(currentDirectory));
}
if (!fileError.str().empty()) {
ProvenanceRange range{allSources.AddCompilerInsertion(path)};
@@ -46,12 +47,12 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
if (!options.isModuleFile) {
// For .mod files we always want to look in the search directories.
- // For normal source files we don't push them until after the primary
+ // For normal source files we don't add 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.PushSearchPathDirectory(path);
+ allSources.AppendSearchPathDirectory(path);
}
}
diff --git a/flang/lib/Parser/preprocessor.cpp b/flang/lib/Parser/preprocessor.cpp
index c5422cc..d3dd50a 100644
--- a/flang/lib/Parser/preprocessor.cpp
+++ b/flang/lib/Parser/preprocessor.cpp
@@ -399,6 +399,7 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
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;
@@ -578,6 +579,7 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
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) {
@@ -598,6 +600,12 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
} 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);
@@ -615,7 +623,8 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
}
std::string buf;
llvm::raw_string_ostream error{buf};
- const SourceFile *included{allSources_.Open(include, error)};
+ const SourceFile *included{
+ allSources_.Open(include, error, std::move(prependPath))};
if (!included) {
prescanner->Say(dir.GetTokenProvenanceRange(dirOffset),
"#include: %s"_err_en_US, error.str());
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index dc6fbe5..edb62b3 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -760,14 +760,12 @@ void Prescanner::FortranInclude(const char *firstQuote) {
std::string buf;
llvm::raw_string_ostream error{buf};
Provenance provenance{GetProvenance(nextLine_)};
- const SourceFile *currentFile{allSources_.GetSourceFile(provenance)};
- if (currentFile) {
- allSources_.PushSearchPathDirectory(DirectoryName(currentFile->path()));
- }
- const SourceFile *included{allSources_.Open(path, error)};
- if (currentFile) {
- allSources_.PopSearchPathDirectory();
+ std::optional<std::string> prependPath;
+ if (const SourceFile * currentFile{allSources_.GetSourceFile(provenance)}) {
+ prependPath = DirectoryName(currentFile->path());
}
+ const SourceFile *included{
+ allSources_.Open(path, error, std::move(prependPath))};
if (!included) {
Say(provenance, "INCLUDE: %s"_err_en_US, error.str());
} else if (included->bytes() > 0) {
diff --git a/flang/lib/Parser/provenance.cpp b/flang/lib/Parser/provenance.cpp
index 46a0dc9..14124a5 100644
--- a/flang/lib/Parser/provenance.cpp
+++ b/flang/lib/Parser/provenance.cpp
@@ -156,20 +156,28 @@ const char &AllSources::operator[](Provenance at) const {
return origin[origin.covers.MemberOffset(at)];
}
-void AllSources::PushSearchPathDirectory(std::string directory) {
+void AllSources::AppendSearchPathDirectory(std::string directory) {
// gfortran and ifort append to current path, PGI prepends
searchPath_.push_back(directory);
}
-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) {
+const SourceFile *AllSources::Open(std::string path, llvm::raw_ostream &error,
+ std::optional<std::string> &&prependPath) {
std::unique_ptr<SourceFile> source{std::make_unique<SourceFile>(encoding_)};
- if (source->Open(LocateSourceFile(path, searchPath_), error)) {
+ 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_.emplace_front(std::move(*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)) {
return ownedSourceFiles_.emplace_back(std::move(source)).get();
} else {
return nullptr;
diff --git a/flang/lib/Parser/source.cpp b/flang/lib/Parser/source.cpp
index 11cd591..3fbbf78 100644
--- a/flang/lib/Parser/source.cpp
+++ b/flang/lib/Parser/source.cpp
@@ -56,9 +56,9 @@ std::string DirectoryName(std::string path) {
return pathBuf.str().str();
}
-std::string LocateSourceFile(
- std::string name, const std::vector<std::string> &searchPath) {
- if (name.empty() || name == "-" || llvm::sys::path::is_absolute(name)) {
+std::optional<std::string> LocateSourceFile(
+ std::string name, const std::list<std::string> &searchPath) {
+ if (name == "-" || llvm::sys::path::is_absolute(name)) {
return name;
}
for (const std::string &dir : searchPath) {
@@ -70,7 +70,7 @@ std::string LocateSourceFile(
return path.str().str();
}
}
- return name;
+ return std::nullopt;
}
std::size_t RemoveCarriageReturns(llvm::MutableArrayRef<char> buf) {
@@ -123,7 +123,6 @@ bool SourceFile::Open(std::string path, llvm::raw_ostream &error) {
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();
@@ -146,7 +145,6 @@ void SourceFile::ReadFile() {
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/flang/test/Flang-Driver/Inputs/basictestmoduleone.mod b/flang/test/Flang-Driver/Inputs/basictestmoduleone.mod
index 424a151..e0563fe 100644
--- a/flang/test/Flang-Driver/Inputs/basictestmoduleone.mod
+++ b/flang/test/Flang-Driver/Inputs/basictestmoduleone.mod
@@ -1 +1,5 @@
-NOT A REAL MODULE FILE - USE THIS ONLY FOR TESTING THE DRIVER
+!mod$ v1 sum:1f5a35ada852dc66
+module basictestmoduleone
+type::t1
+end type
+end
diff --git a/flang/test/Flang-Driver/Inputs/module-dir/basictestmoduleone.mod b/flang/test/Flang-Driver/Inputs/module-dir/basictestmoduleone.mod
new file mode 100644
index 0000000..1140a84
--- /dev/null
+++ b/flang/test/Flang-Driver/Inputs/module-dir/basictestmoduleone.mod
@@ -0,0 +1,5 @@
+!mod$ v1 sum:449b70509dd4bce3
+module basictestmoduleone
+type::t2
+end type
+end
diff --git a/flang/test/Flang-Driver/Inputs/module-dir/basictestmoduletwo.mod b/flang/test/Flang-Driver/Inputs/module-dir/basictestmoduletwo.mod
index 424a151..ea7d12d 100644
--- a/flang/test/Flang-Driver/Inputs/module-dir/basictestmoduletwo.mod
+++ b/flang/test/Flang-Driver/Inputs/module-dir/basictestmoduletwo.mod
@@ -1 +1,3 @@
-NOT A REAL MODULE FILE - USE THIS ONLY FOR TESTING THE DRIVER
+!mod$ v1 sum:563b9a1f049282d2
+module basictestmoduletwo
+end
diff --git a/flang/test/Flang-Driver/include-header.f90 b/flang/test/Flang-Driver/include-header.f90
index a171ed9..f3cafb7 100644
--- a/flang/test/Flang-Driver/include-header.f90
+++ b/flang/test/Flang-Driver/include-header.f90
@@ -21,7 +21,7 @@
!--------------------------------------------
! EXPECTED OUTPUT FOR MISSING INCLUDED FILE
!--------------------------------------------
-! UNINCLUDED:No such file or directory
+! UNINCLUDED:#include: Source file 'basic-header-one.h' was not found
! UNINCLUDED-NOT:program b
! UNINCLUDED-NOT:program c
diff --git a/flang/test/Flang-Driver/include-module.f90 b/flang/test/Flang-Driver/include-module.f90
index 7a55195..e9530cc 100644
--- a/flang/test/Flang-Driver/include-module.f90
+++ b/flang/test/Flang-Driver/include-module.f90
@@ -1,5 +1,4 @@
! Ensure argument -I works as expected with module files.
-! The module files for this test are not real module files.
! REQUIRES: new-flang-driver
@@ -18,15 +17,21 @@
!-----------------------------------------
! EXPECTED OUTPUT FOR MISSING MODULE FILE
!-----------------------------------------
-! SINGLEINCLUDE:No such file or directory
+! SINGLEINCLUDE:Error reading module file for module 'basictestmoduletwo'
! SINGLEINCLUDE-NOT:Error reading module file for module 'basictestmoduletwo'
+! SINGLEINCLUDE-NOT:error: Derived type 't1' not found
+! SINGLEINCLUDE:error: Derived type 't2' not found
!---------------------------------------
! EXPECTED OUTPUT FOR ALL MODULES FOUND
!---------------------------------------
-! INCLUDED-NOT:No such file or directory
+! INCLUDED-NOT:Error reading module file
+! INCLUDED-NOT:error: Derived type 't1' not found
+! INCLUDED:error: Derived type 't2' not found
program test_dash_I_with_mod_files
USE basictestmoduleone
USE basictestmoduletwo
+ type(t1) :: x1 ! t1 defined in Inputs/basictestmoduleone.mod
+ type(t2) :: x2 ! t2 defined in Inputs/module-dir/basictestmoduleone.mod
end
diff --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp
index 9a10aed..7cb0129 100644
--- a/flang/tools/f18/f18.cpp
+++ b/flang/tools/f18/f18.cpp
@@ -84,7 +84,7 @@ struct DriverOptions {
bool verbose{false}; // -v
bool compileOnly{false}; // -c
std::string outputPath; // -o path
- std::vector<std::string> searchDirectories{"."s}; // -I dir
+ std::vector<std::string> searchDirectories; // -I dir
std::string moduleDirectory{"."s}; // -module dir
std::string moduleFileSuffix{".mod"}; // -moduleSuffix suff
bool forcedForm{false}; // -Mfixed or -Mfree appeared
diff --git a/flang/unittests/Frontend/FrontendActionTest.cpp b/flang/unittests/Frontend/FrontendActionTest.cpp
index fba4669..150f20d 100644
--- a/flang/unittests/Frontend/FrontendActionTest.cpp
+++ b/flang/unittests/Frontend/FrontendActionTest.cpp
@@ -157,7 +157,7 @@ TEST_F(FrontendActionTest, ParseSyntaxOnly) {
EXPECT_TRUE(!outputDiagBuffer.empty());
EXPECT_TRUE(
llvm::StringRef(outputDiagBuffer.data())
- .startswith(
+ .contains(
":1:14: error: IF statement is not allowed in IF statement\n"));
}
} // namespace