mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 11:39:35 +00:00
[flang] Search for #include "file" in right directory
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 after the original. Differential Revision: https://reviews.llvm.org/D95388
This commit is contained in:
parent
f50b8ee71f
commit
d987b61b1d
@ -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,
|
||||
const std::optional<std::string> &prependPath);
|
||||
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};
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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, 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,7 @@ 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, prependPath)};
|
||||
if (!included) {
|
||||
prescanner->Say(dir.GetTokenProvenanceRange(dirOffset),
|
||||
"#include: %s"_err_en_US, error.str());
|
||||
|
@ -760,14 +760,11 @@ 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, prependPath)};
|
||||
if (!included) {
|
||||
Say(provenance, "INCLUDE: %s"_err_en_US, error.str());
|
||||
} else if (included->bytes() > 0) {
|
||||
|
@ -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,
|
||||
const 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_.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)) {
|
||||
return ownedSourceFiles_.emplace_back(std::move(source)).get();
|
||||
} else {
|
||||
return nullptr;
|
||||
|
@ -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_++;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user