diff --git a/flang/include/flang/Parser/parse-state.h b/flang/include/flang/Parser/parse-state.h --- a/flang/include/flang/Parser/parse-state.h +++ b/flang/include/flang/Parser/parse-state.h @@ -36,7 +36,7 @@ public: // TODO: Add a constructor for parsing a normalized module file. ParseState(const CookedSource &cooked) - : p_{&cooked.data().front()}, limit_{&cooked.data().back() + 1} {} + : p_{cooked.AsCharBlock().begin()}, limit_{cooked.AsCharBlock().end()} {} ParseState(const ParseState &that) : p_{that.p_}, limit_{that.limit_}, context_{that.context_}, userState_{that.userState_}, inFixedForm_{that.inFixedForm_}, diff --git a/flang/include/flang/Parser/provenance.h b/flang/include/flang/Parser/provenance.h --- a/flang/include/flang/Parser/provenance.h +++ b/flang/include/flang/Parser/provenance.h @@ -167,6 +167,7 @@ const std::string &message, bool echoSourceLine = false) const; const SourceFile *GetSourceFile( Provenance, std::size_t *offset = nullptr) const; + const char *GetSource(ProvenanceRange) const; std::optional GetSourcePosition(Provenance) const; std::optional GetFirstFileProvenance() const; std::string GetPath(Provenance) const; // __FILE__ @@ -219,16 +220,7 @@ // single instances of CookedSource. class CookedSource { public: - const std::string &data() const { return data_; } - - bool Contains(const char *p) const { - return p >= &data_.front() && p <= &data_.back() + 1; - } - bool Contains(CharBlock range) const { - return !range.empty() && Contains(range.begin()) && - Contains(range.end() - 1); - } - + CharBlock AsCharBlock() const { return CharBlock{data_}; } std::optional GetProvenanceRange(CharBlock) const; std::optional GetCharBlock(ProvenanceRange) const; @@ -253,7 +245,6 @@ std::size_t BufferedBytes() const; void Marshal(AllSources &); // marshals text into one contiguous block void CompileProvenanceRangeToOffsetMappings(AllSources &); - std::string AcquireData() { return std::move(data_); } llvm::raw_ostream &Dump(llvm::raw_ostream &) const; private: @@ -276,7 +267,7 @@ template // const char * or CharBlock const CookedSource *Find(A x) const { for (const auto &c : cooked_) { - if (c.Contains(x)) { + if (c.AsCharBlock().Contains(x)) { return &c; } } diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h --- a/flang/include/flang/Semantics/semantics.h +++ b/flang/include/flang/Semantics/semantics.h @@ -204,10 +204,10 @@ class Semantics { public: explicit Semantics(SemanticsContext &context, parser::Program &program, - const parser::CookedSource &cooked, bool debugModuleWriter = false) + parser::CharBlock charBlock, bool debugModuleWriter = false) : context_{context}, program_{program} { context.set_debugModuleWriter(debugModuleWriter); - context.globalScope().AddSourceRange(parser::CharBlock{cooked.data()}); + context.globalScope().AddSourceRange(charBlock); } SemanticsContext &context() const { return context_; } diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -1,4 +1,4 @@ -//===-- OpenMP.cpp -- OpenACC directive lowering --------------------------===// +//===-- OpenACC.cpp -- OpenACC directive lowering -------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp --- a/flang/lib/Parser/prescan.cpp +++ b/flang/lib/Parser/prescan.cpp @@ -62,11 +62,8 @@ void Prescanner::Prescan(ProvenanceRange range) { startProvenance_ = range.start(); - std::size_t offset{0}; - const SourceFile *source{ - allSources_.GetSourceFile(startProvenance_, &offset)}; - CHECK(source); - start_ = source->content().data() + offset; + start_ = allSources_.GetSource(range); + CHECK(start_); limit_ = start_ + range.size(); nextLine_ = start_; const bool beganInFixedForm{inFixedForm_}; @@ -75,7 +72,7 @@ "too many nested INCLUDE/#include files, possibly circular"_err_en_US); return; } - while (nextLine_ < limit_) { + while (!IsAtEnd()) { Statement(); } if (inFixedForm_ != beganInFixedForm) { @@ -232,7 +229,7 @@ } TokenSequence Prescanner::TokenizePreprocessorDirective() { - CHECK(nextLine_ < limit_ && !inPreprocessorDirective_); + CHECK(!IsAtEnd() && !inPreprocessorDirective_); inPreprocessorDirective_ = true; BeginStatementAndAdvance(); TokenSequence tokens; @@ -360,7 +357,7 @@ break; } } else if (inPreprocessorDirective_ && at_[0] == '\\' && at_ + 2 < limit_ && - at_[1] == '\n' && nextLine_ < limit_) { + at_[1] == '\n' && !IsAtEnd()) { BeginSourceLineAndAdvance(); } else { break; @@ -804,7 +801,7 @@ } bool Prescanner::SkipCommentLine(bool afterAmpersand) { - if (nextLine_ >= limit_) { + if (IsAtEnd()) { if (afterAmpersand && prescannerNesting_ > 0) { // A continuation marker at the end of the last line in an // include file inhibits the newline for that line. @@ -843,7 +840,7 @@ } const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) { - if (nextLine_ >= limit_) { + if (IsAtEnd()) { return nullptr; } tabInCurrentLine_ = false; @@ -995,7 +992,7 @@ // arguments to span multiple lines. bool Prescanner::IsImplicitContinuation() const { return !inPreprocessorDirective_ && !inCharLiteral_ && - delimiterNesting_ > 0 && nextLine_ < limit_ && + delimiterNesting_ > 0 && !IsAtEnd() && ClassifyLine(nextLine_).kind == LineClassification::Kind::Source; } diff --git a/flang/lib/Parser/provenance.cpp b/flang/lib/Parser/provenance.cpp --- a/flang/lib/Parser/provenance.cpp +++ b/flang/lib/Parser/provenance.cpp @@ -301,6 +301,14 @@ origin.u); } +const char *AllSources::GetSource(ProvenanceRange range) const { + Provenance start{range.start()}; + const Origin &origin{MapToOrigin(start)}; + return origin.covers.Contains(range) + ? &origin[origin.covers.MemberOffset(start)] + : nullptr; +} + std::optional AllSources::GetSourcePosition( Provenance prov) const { const Origin &origin{MapToOrigin(prov)}; @@ -402,7 +410,7 @@ std::optional CookedSource::GetProvenanceRange( CharBlock cookedRange) const { - if (!Contains(cookedRange)) { + if (!AsCharBlock().Contains(cookedRange)) { return std::nullopt; } ProvenanceRange first{provenanceMap_.Map(cookedRange.begin() - &data_[0])}; diff --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp --- a/flang/tools/f18/f18.cpp +++ b/flang/tools/f18/f18.cpp @@ -251,7 +251,7 @@ driver.dumpSymbols || driver.dumpUnparseWithSymbols || driver.getDefinition || driver.getSymbolsSources) { Fortran::semantics::Semantics semantics{semanticsContext, parseTree, - parsing.cooked(), driver.debugModuleWriter}; + parsing.cooked().AsCharBlock(), driver.debugModuleWriter}; semantics.Perform(); semantics.EmitMessages(llvm::errs()); if (driver.dumpSymbols) { diff --git a/flang/unittests/Evaluate/intrinsics.cpp b/flang/unittests/Evaluate/intrinsics.cpp --- a/flang/unittests/Evaluate/intrinsics.cpp +++ b/flang/unittests/Evaluate/intrinsics.cpp @@ -26,10 +26,10 @@ } void Marshal() { cooked_.Marshal(allSources_); } parser::CharBlock operator()(const std::string &s) { - return {cooked_.data().data() + offsets_[s], s.size()}; + return {cooked_.AsCharBlock().begin() + offsets_[s], s.size()}; } parser::ContextualMessages Messages(parser::Messages &buffer) { - return parser::ContextualMessages{cooked_.data(), &buffer}; + return parser::ContextualMessages{cooked_.AsCharBlock(), &buffer}; } void Emit(llvm::raw_ostream &o, const parser::Messages &messages) { messages.Emit(o, allCookedSources_);