Skip to content

Commit 6110e77

Browse files
committed
[flang] Search for #include "file" in right directory (take 2)
Make the #include "file" preprocessing directive begin its search in the same directory as the file containing the directive, as other preprocessors and our Fortran INCLUDE statement do. Avoid current working directory for all source files except the original. Resolve tests. Differential Revision: https://reviews.llvm.org/D95481
1 parent 764a7a2 commit 6110e77

File tree

15 files changed

+74
-42
lines changed

15 files changed

+74
-42
lines changed

flang/include/flang/Parser/provenance.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,9 @@ class AllSources {
148148
return *this;
149149
}
150150

151-
void PushSearchPathDirectory(std::string);
152-
std::string PopSearchPathDirectory();
153-
const SourceFile *Open(std::string path, llvm::raw_ostream &error);
151+
void AppendSearchPathDirectory(std::string); // new last directory
152+
const SourceFile *Open(std::string path, llvm::raw_ostream &error,
153+
std::optional<std::string> &&prependPath = std::nullopt);
154154
const SourceFile *ReadStandardInput(llvm::raw_ostream &error);
155155

156156
ProvenanceRange AddIncludedFile(
@@ -210,7 +210,7 @@ class AllSources {
210210
ProvenanceRange range_;
211211
std::map<char, Provenance> compilerInsertionProvenance_;
212212
std::vector<std::unique_ptr<SourceFile>> ownedSourceFiles_;
213-
std::vector<std::string> searchPath_;
213+
std::list<std::string> searchPath_;
214214
Encoding encoding_{Encoding::UTF_8};
215215
};
216216

flang/include/flang/Parser/source.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "characters.h"
1818
#include "llvm/Support/MemoryBuffer.h"
1919
#include <cstddef>
20+
#include <list>
21+
#include <optional>
2022
#include <string>
2123
#include <utility>
2224
#include <vector>
@@ -28,8 +30,8 @@ class raw_ostream;
2830
namespace Fortran::parser {
2931

3032
std::string DirectoryName(std::string path);
31-
std::string LocateSourceFile(
32-
std::string name, const std::vector<std::string> &searchPath);
33+
std::optional<std::string> LocateSourceFile(
34+
std::string name, const std::list<std::string> &searchPath);
3335

3436
class SourceFile;
3537

flang/lib/Frontend/FrontendActions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void InputOutputTestAction::ExecuteAction() {
2828
CompilerInstance &ci = instance();
2929
Fortran::parser::AllSources &allSources{ci.allSources()};
3030
const Fortran::parser::SourceFile *sf;
31-
sf = allSources.Open(path, error_stream);
31+
sf = allSources.Open(path, error_stream, std::optional<std::string>{"."s});
3232
llvm::ArrayRef<char> fileContent = sf->content();
3333

3434
// Output file descriptor to receive the content of input file.

flang/lib/Parser/parsing.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
2525
AllSources &allSources{allCooked_.allSources()};
2626
if (options.isModuleFile) {
2727
for (const auto &path : options.searchDirectories) {
28-
allSources.PushSearchPathDirectory(path);
28+
allSources.AppendSearchPathDirectory(path);
2929
}
3030
}
3131

@@ -35,7 +35,8 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
3535
if (path == "-") {
3636
sourceFile = allSources.ReadStandardInput(fileError);
3737
} else {
38-
sourceFile = allSources.Open(path, fileError);
38+
std::optional<std::string> currentDirectory{"."};
39+
sourceFile = allSources.Open(path, fileError, std::move(currentDirectory));
3940
}
4041
if (!fileError.str().empty()) {
4142
ProvenanceRange range{allSources.AddCompilerInsertion(path)};
@@ -46,12 +47,12 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
4647

4748
if (!options.isModuleFile) {
4849
// For .mod files we always want to look in the search directories.
49-
// For normal source files we don't push them until after the primary
50+
// For normal source files we don't add them until after the primary
5051
// source file has been opened. If foo.f is missing from the current
5152
// working directory, we don't want to accidentally read another foo.f
5253
// from another directory that's on the search path.
5354
for (const auto &path : options.searchDirectories) {
54-
allSources.PushSearchPathDirectory(path);
55+
allSources.AppendSearchPathDirectory(path);
5556
}
5657
}
5758

flang/lib/Parser/preprocessor.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
399399
if (j == tokens) {
400400
return;
401401
}
402+
CHECK(prescanner); // TODO: change to reference
402403
if (dir.TokenAt(j).ToString() != "#") {
403404
prescanner->Say(dir.GetTokenProvenanceRange(j), "missing '#'"_err_en_US);
404405
return;
@@ -578,6 +579,7 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
578579
return;
579580
}
580581
std::string include;
582+
std::optional<std::string> prependPath;
581583
if (dir.TokenAt(j).ToString() == "<") { // #include <foo>
582584
std::size_t k{j + 1};
583585
if (k >= tokens) {
@@ -598,6 +600,12 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
598600
} else if ((include = dir.TokenAt(j).ToString()).substr(0, 1) == "\"" &&
599601
include.substr(include.size() - 1, 1) == "\"") { // #include "foo"
600602
include = include.substr(1, include.size() - 2);
603+
// #include "foo" starts search in directory of file containing
604+
// the directive
605+
auto prov{dir.GetTokenProvenanceRange(dirOffset).start()};
606+
if (const auto *currentFile{allSources_.GetSourceFile(prov)}) {
607+
prependPath = DirectoryName(currentFile->path());
608+
}
601609
} else {
602610
prescanner->Say(dir.GetTokenProvenanceRange(j < tokens ? j : tokens - 1),
603611
"#include: expected name of file to include"_err_en_US);
@@ -615,7 +623,8 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
615623
}
616624
std::string buf;
617625
llvm::raw_string_ostream error{buf};
618-
const SourceFile *included{allSources_.Open(include, error)};
626+
const SourceFile *included{
627+
allSources_.Open(include, error, std::move(prependPath))};
619628
if (!included) {
620629
prescanner->Say(dir.GetTokenProvenanceRange(dirOffset),
621630
"#include: %s"_err_en_US, error.str());

flang/lib/Parser/prescan.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -760,14 +760,12 @@ void Prescanner::FortranInclude(const char *firstQuote) {
760760
std::string buf;
761761
llvm::raw_string_ostream error{buf};
762762
Provenance provenance{GetProvenance(nextLine_)};
763-
const SourceFile *currentFile{allSources_.GetSourceFile(provenance)};
764-
if (currentFile) {
765-
allSources_.PushSearchPathDirectory(DirectoryName(currentFile->path()));
766-
}
767-
const SourceFile *included{allSources_.Open(path, error)};
768-
if (currentFile) {
769-
allSources_.PopSearchPathDirectory();
763+
std::optional<std::string> prependPath;
764+
if (const SourceFile * currentFile{allSources_.GetSourceFile(provenance)}) {
765+
prependPath = DirectoryName(currentFile->path());
770766
}
767+
const SourceFile *included{
768+
allSources_.Open(path, error, std::move(prependPath))};
771769
if (!included) {
772770
Say(provenance, "INCLUDE: %s"_err_en_US, error.str());
773771
} else if (included->bytes() > 0) {

flang/lib/Parser/provenance.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,20 +156,28 @@ const char &AllSources::operator[](Provenance at) const {
156156
return origin[origin.covers.MemberOffset(at)];
157157
}
158158

159-
void AllSources::PushSearchPathDirectory(std::string directory) {
159+
void AllSources::AppendSearchPathDirectory(std::string directory) {
160160
// gfortran and ifort append to current path, PGI prepends
161161
searchPath_.push_back(directory);
162162
}
163163

164-
std::string AllSources::PopSearchPathDirectory() {
165-
std::string directory{searchPath_.back()};
166-
searchPath_.pop_back();
167-
return directory;
168-
}
169-
170-
const SourceFile *AllSources::Open(std::string path, llvm::raw_ostream &error) {
164+
const SourceFile *AllSources::Open(std::string path, llvm::raw_ostream &error,
165+
std::optional<std::string> &&prependPath) {
171166
std::unique_ptr<SourceFile> source{std::make_unique<SourceFile>(encoding_)};
172-
if (source->Open(LocateSourceFile(path, searchPath_), error)) {
167+
if (prependPath) {
168+
// Set to "." for the initial source file; set to the directory name
169+
// of the including file for #include "quoted-file" directives &
170+
// INCLUDE statements.
171+
searchPath_.emplace_front(std::move(*prependPath));
172+
}
173+
std::optional<std::string> found{LocateSourceFile(path, searchPath_)};
174+
if (prependPath) {
175+
searchPath_.pop_front();
176+
}
177+
if (!found) {
178+
error << "Source file '" << path << "' was not found";
179+
return nullptr;
180+
} else if (source->Open(*found, error)) {
173181
return ownedSourceFiles_.emplace_back(std::move(source)).get();
174182
} else {
175183
return nullptr;

flang/lib/Parser/source.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ std::string DirectoryName(std::string path) {
5656
return pathBuf.str().str();
5757
}
5858

59-
std::string LocateSourceFile(
60-
std::string name, const std::vector<std::string> &searchPath) {
61-
if (name.empty() || name == "-" || llvm::sys::path::is_absolute(name)) {
59+
std::optional<std::string> LocateSourceFile(
60+
std::string name, const std::list<std::string> &searchPath) {
61+
if (name == "-" || llvm::sys::path::is_absolute(name)) {
6262
return name;
6363
}
6464
for (const std::string &dir : searchPath) {
@@ -70,7 +70,7 @@ std::string LocateSourceFile(
7070
return path.str().str();
7171
}
7272
}
73-
return name;
73+
return std::nullopt;
7474
}
7575

7676
std::size_t RemoveCarriageReturns(llvm::MutableArrayRef<char> buf) {
@@ -123,7 +123,6 @@ bool SourceFile::Open(std::string path, llvm::raw_ostream &error) {
123123
bool SourceFile::ReadStandardInput(llvm::raw_ostream &error) {
124124
Close();
125125
path_ = "standard input";
126-
127126
auto buf_or = llvm::MemoryBuffer::getSTDIN();
128127
if (!buf_or) {
129128
auto err = buf_or.getError();
@@ -146,7 +145,6 @@ void SourceFile::ReadFile() {
146145
auto tmp_buf{llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
147146
content().size() + 1)};
148147
llvm::copy(content(), tmp_buf->getBufferStart());
149-
Close();
150148
buf_ = std::move(tmp_buf);
151149
}
152150
buf_end_++;
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
NOT A REAL MODULE FILE - USE THIS ONLY FOR TESTING THE DRIVER
1+
!mod$ v1 sum:1f5a35ada852dc66
2+
module basictestmoduleone
3+
type::t1
4+
end type
5+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
!mod$ v1 sum:449b70509dd4bce3
2+
module basictestmoduleone
3+
type::t2
4+
end type
5+
end
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
NOT A REAL MODULE FILE - USE THIS ONLY FOR TESTING THE DRIVER
1+
!mod$ v1 sum:563b9a1f049282d2
2+
module basictestmoduletwo
3+
end

flang/test/Flang-Driver/include-header.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
!--------------------------------------------
2222
! EXPECTED OUTPUT FOR MISSING INCLUDED FILE
2323
!--------------------------------------------
24-
! UNINCLUDED:No such file or directory
24+
! UNINCLUDED:#include: Source file 'basic-header-one.h' was not found
2525
! UNINCLUDED-NOT:program b
2626
! UNINCLUDED-NOT:program c
2727

flang/test/Flang-Driver/include-module.f90

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
! Ensure argument -I works as expected with module files.
2-
! The module files for this test are not real module files.
32

43
! REQUIRES: new-flang-driver
54

@@ -18,15 +17,21 @@
1817
!-----------------------------------------
1918
! EXPECTED OUTPUT FOR MISSING MODULE FILE
2019
!-----------------------------------------
21-
! SINGLEINCLUDE:No such file or directory
20+
! SINGLEINCLUDE:Error reading module file for module 'basictestmoduletwo'
2221
! SINGLEINCLUDE-NOT:Error reading module file for module 'basictestmoduletwo'
22+
! SINGLEINCLUDE-NOT:error: Derived type 't1' not found
23+
! SINGLEINCLUDE:error: Derived type 't2' not found
2324

2425
!---------------------------------------
2526
! EXPECTED OUTPUT FOR ALL MODULES FOUND
2627
!---------------------------------------
27-
! INCLUDED-NOT:No such file or directory
28+
! INCLUDED-NOT:Error reading module file
29+
! INCLUDED-NOT:error: Derived type 't1' not found
30+
! INCLUDED:error: Derived type 't2' not found
2831

2932
program test_dash_I_with_mod_files
3033
USE basictestmoduleone
3134
USE basictestmoduletwo
35+
type(t1) :: x1 ! t1 defined in Inputs/basictestmoduleone.mod
36+
type(t2) :: x2 ! t2 defined in Inputs/module-dir/basictestmoduleone.mod
3237
end

flang/tools/f18/f18.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ struct DriverOptions {
8484
bool verbose{false}; // -v
8585
bool compileOnly{false}; // -c
8686
std::string outputPath; // -o path
87-
std::vector<std::string> searchDirectories{"."s}; // -I dir
87+
std::vector<std::string> searchDirectories; // -I dir
8888
std::string moduleDirectory{"."s}; // -module dir
8989
std::string moduleFileSuffix{".mod"}; // -moduleSuffix suff
9090
bool forcedForm{false}; // -Mfixed or -Mfree appeared

flang/unittests/Frontend/FrontendActionTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ TEST_F(FrontendActionTest, ParseSyntaxOnly) {
157157
EXPECT_TRUE(!outputDiagBuffer.empty());
158158
EXPECT_TRUE(
159159
llvm::StringRef(outputDiagBuffer.data())
160-
.startswith(
160+
.contains(
161161
":1:14: error: IF statement is not allowed in IF statement\n"));
162162
}
163163
} // namespace

0 commit comments

Comments
 (0)