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);
|
||||
}
|
||||
}
|
||||
Prescanner prescanner{messages_, *cooked_, preprocessor, options.features};
|
||||
Prescanner prescanner{messages_, cooked_, preprocessor, options.features};
|
||||
prescanner.set_fixedForm(options.isFixedForm)
|
||||
.set_fixedFormColumnLimit(options.fixedFormColumns)
|
||||
.set_encoding(options.encoding)
|
||||
|
@ -75,30 +75,30 @@ void Parsing::Prescan(const std::string &path, Options options) {
|
|||
ProvenanceRange range{
|
||||
allSources_.AddIncludedFile(*sourceFile, ProvenanceRange{})};
|
||||
prescanner.Prescan(range);
|
||||
cooked_->Marshal();
|
||||
cooked_.Marshal();
|
||||
}
|
||||
|
||||
void Parsing::DumpCookedChars(std::ostream &out) const {
|
||||
UserState userState{*cooked_, LanguageFeatureControl{}};
|
||||
ParseState parseState{*cooked_};
|
||||
UserState userState{cooked_, LanguageFeatureControl{}};
|
||||
ParseState parseState{cooked_};
|
||||
parseState.set_inFixedForm(options_.isFixedForm).set_userState(&userState);
|
||||
while (std::optional<const char *> p{parseState.GetNextChar()}) {
|
||||
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 {
|
||||
log_.Dump(out, *cooked_);
|
||||
log_.Dump(out, cooked_);
|
||||
}
|
||||
|
||||
void Parsing::Parse(std::ostream *out) {
|
||||
UserState userState{*cooked_, options_.features};
|
||||
UserState userState{cooked_, options_.features};
|
||||
userState.set_debugOutput(out)
|
||||
.set_instrumentedParse(options_.instrumentedParse)
|
||||
.set_log(&log_);
|
||||
ParseState parseState{*cooked_};
|
||||
ParseState parseState{cooked_};
|
||||
parseState.set_inFixedForm(options_.isFixedForm)
|
||||
.set_encoding(options_.encoding)
|
||||
.set_userState(&userState);
|
||||
|
@ -115,12 +115,12 @@ void Parsing::ClearLog() { log_.clear(); }
|
|||
bool Parsing::ForTesting(std::string path, std::ostream &err) {
|
||||
Prescan(path, Options{});
|
||||
if (messages_.AnyFatalError()) {
|
||||
messages_.Emit(err, *cooked_);
|
||||
messages_.Emit(err, cooked_);
|
||||
err << "could not scan " << path << '\n';
|
||||
return false;
|
||||
}
|
||||
Parse();
|
||||
messages_.Emit(err, *cooked_);
|
||||
messages_.Emit(err, cooked_);
|
||||
if (!consumedWholeFile_) {
|
||||
EmitMessage(err, finalRestingPlace_, "parser FAIL; final position");
|
||||
return false;
|
||||
|
|
|
@ -50,8 +50,7 @@ public:
|
|||
|
||||
bool consumedWholeFile() const { return consumedWholeFile_; }
|
||||
const char *finalRestingPlace() const { return finalRestingPlace_; }
|
||||
CookedSource &cooked() { return *cooked_; }
|
||||
std::unique_ptr<CookedSource> MoveCooked() { return std::move(cooked_); }
|
||||
CookedSource &cooked() { return cooked_; }
|
||||
Messages &messages() { return messages_; }
|
||||
std::optional<Program> &parseTree() { return parseTree_; }
|
||||
|
||||
|
@ -65,7 +64,7 @@ public:
|
|||
void EmitMessage(std::ostream &o, const char *at, const std::string &message,
|
||||
bool echoSourceLine = false) const {
|
||||
allSources_.EmitMessage(
|
||||
o, cooked_->GetProvenanceRange(at).start(), message, echoSourceLine);
|
||||
o, cooked_.GetProvenanceRange(at).start(), message, echoSourceLine);
|
||||
}
|
||||
|
||||
bool ForTesting(std::string path, std::ostream &);
|
||||
|
@ -73,8 +72,7 @@ public:
|
|||
private:
|
||||
Options options_;
|
||||
AllSources allSources_;
|
||||
std::unique_ptr<parser::CookedSource> cooked_{
|
||||
std::make_unique<parser::CookedSource>(allSources_)};
|
||||
CookedSource cooked_{allSources_};
|
||||
Messages messages_;
|
||||
bool consumedWholeFile_{false};
|
||||
const char *finalRestingPlace_{nullptr};
|
||||
|
|
|
@ -303,19 +303,19 @@ const AllSources::Origin &AllSources::MapToOrigin(Provenance at) 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()) {
|
||||
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()};
|
||||
}
|
||||
|
||||
void CookedSource::Marshal() {
|
||||
CHECK(provenanceMap_.size() == buffer_.size());
|
||||
provenanceMap_.Put(allSources_.AddCompilerInsertion("(after end of source)"));
|
||||
data_.resize(buffer_.size());
|
||||
char *p{&data_[0]};
|
||||
data_ = std::make_unique<std::vector<char>>(buffer_.size());
|
||||
char *p{&(*data_)[0]};
|
||||
for (char ch : buffer_) {
|
||||
*p++ = ch;
|
||||
}
|
||||
|
|
|
@ -184,14 +184,14 @@ class CookedSource {
|
|||
public:
|
||||
explicit CookedSource(AllSources &sources) : allSources_{sources} {}
|
||||
|
||||
std::size_t size() const { return data_.size(); }
|
||||
const char &operator[](std::size_t n) const { return data_[n]; }
|
||||
const char &at(std::size_t n) const { return data_.at(n); }
|
||||
std::size_t size() const { return data_->size(); }
|
||||
const char &operator[](std::size_t n) const { return (*data_)[n]; }
|
||||
const char &at(std::size_t n) const { return data_->at(n); }
|
||||
|
||||
AllSources &allSources() const { return allSources_; }
|
||||
|
||||
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 {
|
||||
return !range.empty() && IsValid(range.begin()) && IsValid(range.end() - 1);
|
||||
|
@ -211,12 +211,14 @@ public:
|
|||
provenanceMap_.Put(pm);
|
||||
}
|
||||
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;
|
||||
|
||||
private:
|
||||
AllSources &allSources_;
|
||||
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_;
|
||||
};
|
||||
|
||||
|
|
|
@ -364,15 +364,14 @@ bool ModFileReader::Read(const SourceName &modName) {
|
|||
modName.ToString(), *path));
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<parser::CookedSource> cooked_{parsing.MoveCooked()};
|
||||
ResolveNames(*parseTree, *cooked_, directories_);
|
||||
ResolveNames(*parseTree, parsing.cooked(), directories_);
|
||||
|
||||
const auto &it{Scope::globalScope.find(modName)};
|
||||
if (it == Scope::globalScope.end()) {
|
||||
return false;
|
||||
}
|
||||
auto &modSymbol{*it->second};
|
||||
modSymbol.scope()->set_cookedSource(std::move(cooked_));
|
||||
modSymbol.scope()->set_chars(parsing.cooked().MoveChars());
|
||||
modSymbol.set(Symbol::Flag::ModFile);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -92,9 +92,6 @@ public:
|
|||
|
||||
private:
|
||||
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::optional<std::string> FindModFile(const SourceName &);
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "attr.h"
|
||||
#include "symbol.h"
|
||||
#include "../common/idioms.h"
|
||||
#include "../parser/parse-tree.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
@ -106,9 +105,10 @@ public:
|
|||
|
||||
DerivedTypeSpec &MakeDerivedTypeSpec(const SourceName &);
|
||||
|
||||
std::unique_ptr<parser::CookedSource> cooked_;
|
||||
void set_cookedSource(std::unique_ptr<parser::CookedSource> cooked) {
|
||||
cooked_ = std::move(cooked);
|
||||
// For modules read from module files, this is the stream of characters
|
||||
// that are referenced by SourceName objects.
|
||||
void set_chars(std::unique_ptr<std::vector<char>> chars) {
|
||||
chars_ = std::move(chars);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -118,6 +118,7 @@ private:
|
|||
std::list<Scope> children_;
|
||||
mapType symbols_;
|
||||
std::list<DerivedTypeSpec> derivedTypeSpecs_;
|
||||
std::unique_ptr<std::vector<char>> chars_;
|
||||
|
||||
// Storage for all Symbols. Every Symbol is in allSymbols and every Symbol*
|
||||
// or Symbol& points to one in there.
|
||||
|
|
|
@ -19,9 +19,6 @@
|
|||
|
||||
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) {
|
||||
return os << name.ToString();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue