forked from OSchip/llvm-project
[flang] Change how cooked source is saved
Rather than save the entire CookedSource object in the module scope, all we need is the vector of characters that CharBlock has references into. This avoids the problem that CookedSource object has a dangling reference to an AllSources object (which shouldn't be needed by the CharBlocks in the symbol table, but is there). This also decouples Scope from parser classes other than CharBlock. Original-commit: flang-compiler/f18@fdbf5c841e Reviewed-on: https://github.com/flang-compiler/f18/pull/149 Tree-same-pre-rewrite: false
This commit is contained in:
parent
9e48304374
commit
6f4f772685
|
@ -63,7 +63,7 @@ void Parsing::Prescan(const std::string &path, Options options) {
|
||||||
preprocessor.Undefine(predef.first);
|
preprocessor.Undefine(predef.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Prescanner prescanner{messages_, *cooked_, preprocessor, options.features};
|
Prescanner prescanner{messages_, cooked_, preprocessor, options.features};
|
||||||
prescanner.set_fixedForm(options.isFixedForm)
|
prescanner.set_fixedForm(options.isFixedForm)
|
||||||
.set_fixedFormColumnLimit(options.fixedFormColumns)
|
.set_fixedFormColumnLimit(options.fixedFormColumns)
|
||||||
.set_encoding(options.encoding)
|
.set_encoding(options.encoding)
|
||||||
|
@ -75,30 +75,30 @@ void Parsing::Prescan(const std::string &path, Options options) {
|
||||||
ProvenanceRange range{
|
ProvenanceRange range{
|
||||||
allSources_.AddIncludedFile(*sourceFile, ProvenanceRange{})};
|
allSources_.AddIncludedFile(*sourceFile, ProvenanceRange{})};
|
||||||
prescanner.Prescan(range);
|
prescanner.Prescan(range);
|
||||||
cooked_->Marshal();
|
cooked_.Marshal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parsing::DumpCookedChars(std::ostream &out) const {
|
void Parsing::DumpCookedChars(std::ostream &out) const {
|
||||||
UserState userState{*cooked_, LanguageFeatureControl{}};
|
UserState userState{cooked_, LanguageFeatureControl{}};
|
||||||
ParseState parseState{*cooked_};
|
ParseState parseState{cooked_};
|
||||||
parseState.set_inFixedForm(options_.isFixedForm).set_userState(&userState);
|
parseState.set_inFixedForm(options_.isFixedForm).set_userState(&userState);
|
||||||
while (std::optional<const char *> p{parseState.GetNextChar()}) {
|
while (std::optional<const char *> p{parseState.GetNextChar()}) {
|
||||||
out << **p;
|
out << **p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parsing::DumpProvenance(std::ostream &out) const { cooked_->Dump(out); }
|
void Parsing::DumpProvenance(std::ostream &out) const { cooked_.Dump(out); }
|
||||||
|
|
||||||
void Parsing::DumpParsingLog(std::ostream &out) const {
|
void Parsing::DumpParsingLog(std::ostream &out) const {
|
||||||
log_.Dump(out, *cooked_);
|
log_.Dump(out, cooked_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parsing::Parse(std::ostream *out) {
|
void Parsing::Parse(std::ostream *out) {
|
||||||
UserState userState{*cooked_, options_.features};
|
UserState userState{cooked_, options_.features};
|
||||||
userState.set_debugOutput(out)
|
userState.set_debugOutput(out)
|
||||||
.set_instrumentedParse(options_.instrumentedParse)
|
.set_instrumentedParse(options_.instrumentedParse)
|
||||||
.set_log(&log_);
|
.set_log(&log_);
|
||||||
ParseState parseState{*cooked_};
|
ParseState parseState{cooked_};
|
||||||
parseState.set_inFixedForm(options_.isFixedForm)
|
parseState.set_inFixedForm(options_.isFixedForm)
|
||||||
.set_encoding(options_.encoding)
|
.set_encoding(options_.encoding)
|
||||||
.set_userState(&userState);
|
.set_userState(&userState);
|
||||||
|
@ -115,12 +115,12 @@ void Parsing::ClearLog() { log_.clear(); }
|
||||||
bool Parsing::ForTesting(std::string path, std::ostream &err) {
|
bool Parsing::ForTesting(std::string path, std::ostream &err) {
|
||||||
Prescan(path, Options{});
|
Prescan(path, Options{});
|
||||||
if (messages_.AnyFatalError()) {
|
if (messages_.AnyFatalError()) {
|
||||||
messages_.Emit(err, *cooked_);
|
messages_.Emit(err, cooked_);
|
||||||
err << "could not scan " << path << '\n';
|
err << "could not scan " << path << '\n';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Parse();
|
Parse();
|
||||||
messages_.Emit(err, *cooked_);
|
messages_.Emit(err, cooked_);
|
||||||
if (!consumedWholeFile_) {
|
if (!consumedWholeFile_) {
|
||||||
EmitMessage(err, finalRestingPlace_, "parser FAIL; final position");
|
EmitMessage(err, finalRestingPlace_, "parser FAIL; final position");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -50,8 +50,7 @@ public:
|
||||||
|
|
||||||
bool consumedWholeFile() const { return consumedWholeFile_; }
|
bool consumedWholeFile() const { return consumedWholeFile_; }
|
||||||
const char *finalRestingPlace() const { return finalRestingPlace_; }
|
const char *finalRestingPlace() const { return finalRestingPlace_; }
|
||||||
CookedSource &cooked() { return *cooked_; }
|
CookedSource &cooked() { return cooked_; }
|
||||||
std::unique_ptr<CookedSource> MoveCooked() { return std::move(cooked_); }
|
|
||||||
Messages &messages() { return messages_; }
|
Messages &messages() { return messages_; }
|
||||||
std::optional<Program> &parseTree() { return parseTree_; }
|
std::optional<Program> &parseTree() { return parseTree_; }
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ public:
|
||||||
void EmitMessage(std::ostream &o, const char *at, const std::string &message,
|
void EmitMessage(std::ostream &o, const char *at, const std::string &message,
|
||||||
bool echoSourceLine = false) const {
|
bool echoSourceLine = false) const {
|
||||||
allSources_.EmitMessage(
|
allSources_.EmitMessage(
|
||||||
o, cooked_->GetProvenanceRange(at).start(), message, echoSourceLine);
|
o, cooked_.GetProvenanceRange(at).start(), message, echoSourceLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ForTesting(std::string path, std::ostream &);
|
bool ForTesting(std::string path, std::ostream &);
|
||||||
|
@ -73,8 +72,7 @@ public:
|
||||||
private:
|
private:
|
||||||
Options options_;
|
Options options_;
|
||||||
AllSources allSources_;
|
AllSources allSources_;
|
||||||
std::unique_ptr<parser::CookedSource> cooked_{
|
CookedSource cooked_{allSources_};
|
||||||
std::make_unique<parser::CookedSource>(allSources_)};
|
|
||||||
Messages messages_;
|
Messages messages_;
|
||||||
bool consumedWholeFile_{false};
|
bool consumedWholeFile_{false};
|
||||||
const char *finalRestingPlace_{nullptr};
|
const char *finalRestingPlace_{nullptr};
|
||||||
|
|
|
@ -303,19 +303,19 @@ const AllSources::Origin &AllSources::MapToOrigin(Provenance at) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ProvenanceRange CookedSource::GetProvenanceRange(CharBlock cookedRange) const {
|
ProvenanceRange CookedSource::GetProvenanceRange(CharBlock cookedRange) const {
|
||||||
ProvenanceRange first{provenanceMap_.Map(cookedRange.begin() - &data_[0])};
|
ProvenanceRange first{provenanceMap_.Map(cookedRange.begin() - &(*data_)[0])};
|
||||||
if (cookedRange.size() <= first.size()) {
|
if (cookedRange.size() <= first.size()) {
|
||||||
return first.Prefix(cookedRange.size());
|
return first.Prefix(cookedRange.size());
|
||||||
}
|
}
|
||||||
ProvenanceRange last{provenanceMap_.Map(cookedRange.end() - &data_[0])};
|
ProvenanceRange last{provenanceMap_.Map(cookedRange.end() - &(*data_)[0])};
|
||||||
return {first.start(), last.start() - first.start()};
|
return {first.start(), last.start() - first.start()};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CookedSource::Marshal() {
|
void CookedSource::Marshal() {
|
||||||
CHECK(provenanceMap_.size() == buffer_.size());
|
CHECK(provenanceMap_.size() == buffer_.size());
|
||||||
provenanceMap_.Put(allSources_.AddCompilerInsertion("(after end of source)"));
|
provenanceMap_.Put(allSources_.AddCompilerInsertion("(after end of source)"));
|
||||||
data_.resize(buffer_.size());
|
data_ = std::make_unique<std::vector<char>>(buffer_.size());
|
||||||
char *p{&data_[0]};
|
char *p{&(*data_)[0]};
|
||||||
for (char ch : buffer_) {
|
for (char ch : buffer_) {
|
||||||
*p++ = ch;
|
*p++ = ch;
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,14 +184,14 @@ class CookedSource {
|
||||||
public:
|
public:
|
||||||
explicit CookedSource(AllSources &sources) : allSources_{sources} {}
|
explicit CookedSource(AllSources &sources) : allSources_{sources} {}
|
||||||
|
|
||||||
std::size_t size() const { return data_.size(); }
|
std::size_t size() const { return data_->size(); }
|
||||||
const char &operator[](std::size_t n) const { return data_[n]; }
|
const char &operator[](std::size_t n) const { return (*data_)[n]; }
|
||||||
const char &at(std::size_t n) const { return data_.at(n); }
|
const char &at(std::size_t n) const { return data_->at(n); }
|
||||||
|
|
||||||
AllSources &allSources() const { return allSources_; }
|
AllSources &allSources() const { return allSources_; }
|
||||||
|
|
||||||
bool IsValid(const char *p) const {
|
bool IsValid(const char *p) const {
|
||||||
return p >= &data_.front() && p <= &data_.back() + 1;
|
return p >= &data_->front() && p <= &data_->back() + 1;
|
||||||
}
|
}
|
||||||
bool IsValid(CharBlock range) const {
|
bool IsValid(CharBlock range) const {
|
||||||
return !range.empty() && IsValid(range.begin()) && IsValid(range.end() - 1);
|
return !range.empty() && IsValid(range.begin()) && IsValid(range.end() - 1);
|
||||||
|
@ -211,12 +211,14 @@ public:
|
||||||
provenanceMap_.Put(pm);
|
provenanceMap_.Put(pm);
|
||||||
}
|
}
|
||||||
void Marshal(); // marshals all text into one contiguous block
|
void Marshal(); // marshals all text into one contiguous block
|
||||||
|
std::unique_ptr<std::vector<char>> MoveChars() { return std::move(data_); }
|
||||||
std::ostream &Dump(std::ostream &) const;
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AllSources &allSources_;
|
AllSources &allSources_;
|
||||||
CharBuffer buffer_; // before Marshal()
|
CharBuffer buffer_; // before Marshal()
|
||||||
std::vector<char> data_; // all of it, prescanned and preprocessed
|
// all source, prescanned and preprocessed:
|
||||||
|
std::unique_ptr<std::vector<char>> data_;
|
||||||
OffsetToProvenanceMappings provenanceMap_;
|
OffsetToProvenanceMappings provenanceMap_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -364,15 +364,14 @@ bool ModFileReader::Read(const SourceName &modName) {
|
||||||
modName.ToString(), *path));
|
modName.ToString(), *path));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::unique_ptr<parser::CookedSource> cooked_{parsing.MoveCooked()};
|
ResolveNames(*parseTree, parsing.cooked(), directories_);
|
||||||
ResolveNames(*parseTree, *cooked_, directories_);
|
|
||||||
|
|
||||||
const auto &it{Scope::globalScope.find(modName)};
|
const auto &it{Scope::globalScope.find(modName)};
|
||||||
if (it == Scope::globalScope.end()) {
|
if (it == Scope::globalScope.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto &modSymbol{*it->second};
|
auto &modSymbol{*it->second};
|
||||||
modSymbol.scope()->set_cookedSource(std::move(cooked_));
|
modSymbol.scope()->set_chars(parsing.cooked().MoveChars());
|
||||||
modSymbol.set(Symbol::Flag::ModFile);
|
modSymbol.set(Symbol::Flag::ModFile);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,9 +92,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> directories_;
|
std::vector<std::string> directories_;
|
||||||
parser::AllSources allSources_;
|
|
||||||
std::unique_ptr<parser::CookedSource> cooked_{
|
|
||||||
std::make_unique<parser::CookedSource>(allSources_)};
|
|
||||||
std::vector<parser::Message> errors_;
|
std::vector<parser::Message> errors_;
|
||||||
|
|
||||||
std::optional<std::string> FindModFile(const SourceName &);
|
std::optional<std::string> FindModFile(const SourceName &);
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "attr.h"
|
#include "attr.h"
|
||||||
#include "symbol.h"
|
#include "symbol.h"
|
||||||
#include "../common/idioms.h"
|
#include "../common/idioms.h"
|
||||||
#include "../parser/parse-tree.h"
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -106,9 +105,10 @@ public:
|
||||||
|
|
||||||
DerivedTypeSpec &MakeDerivedTypeSpec(const SourceName &);
|
DerivedTypeSpec &MakeDerivedTypeSpec(const SourceName &);
|
||||||
|
|
||||||
std::unique_ptr<parser::CookedSource> cooked_;
|
// For modules read from module files, this is the stream of characters
|
||||||
void set_cookedSource(std::unique_ptr<parser::CookedSource> cooked) {
|
// that are referenced by SourceName objects.
|
||||||
cooked_ = std::move(cooked);
|
void set_chars(std::unique_ptr<std::vector<char>> chars) {
|
||||||
|
chars_ = std::move(chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -118,6 +118,7 @@ private:
|
||||||
std::list<Scope> children_;
|
std::list<Scope> children_;
|
||||||
mapType symbols_;
|
mapType symbols_;
|
||||||
std::list<DerivedTypeSpec> derivedTypeSpecs_;
|
std::list<DerivedTypeSpec> derivedTypeSpecs_;
|
||||||
|
std::unique_ptr<std::vector<char>> chars_;
|
||||||
|
|
||||||
// Storage for all Symbols. Every Symbol is in allSymbols and every Symbol*
|
// Storage for all Symbols. Every Symbol is in allSymbols and every Symbol*
|
||||||
// or Symbol& points to one in there.
|
// or Symbol& points to one in there.
|
||||||
|
|
|
@ -19,9 +19,6 @@
|
||||||
|
|
||||||
namespace Fortran::semantics {
|
namespace Fortran::semantics {
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const parser::Name &name) {
|
|
||||||
return os << name.ToString();
|
|
||||||
}
|
|
||||||
std::ostream &operator<<(std::ostream &os, const parser::CharBlock &name) {
|
std::ostream &operator<<(std::ostream &os, const parser::CharBlock &name) {
|
||||||
return os << name.ToString();
|
return os << name.ToString();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue