xref: /llvm-project/flang/lib/Parser/provenance.cpp (revision c1a750b8bf7c7bfcd4e72537fcf76e5f23d0f06a)
164ab3302SCarolineConcatto //===-- lib/Parser/provenance.cpp -----------------------------------------===//
264ab3302SCarolineConcatto //
364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664ab3302SCarolineConcatto //
764ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
864ab3302SCarolineConcatto 
964ab3302SCarolineConcatto #include "flang/Parser/provenance.h"
1064ab3302SCarolineConcatto #include "flang/Common/idioms.h"
118670e499SCaroline Concatto #include "llvm/Support/raw_ostream.h"
1264ab3302SCarolineConcatto #include <algorithm>
13e12ffe6aSPeter Klausler #include <set>
1464ab3302SCarolineConcatto #include <utility>
1564ab3302SCarolineConcatto 
1664ab3302SCarolineConcatto namespace Fortran::parser {
1764ab3302SCarolineConcatto 
1864ab3302SCarolineConcatto ProvenanceRangeToOffsetMappings::ProvenanceRangeToOffsetMappings() {}
1964ab3302SCarolineConcatto ProvenanceRangeToOffsetMappings::~ProvenanceRangeToOffsetMappings() {}
2064ab3302SCarolineConcatto 
2164ab3302SCarolineConcatto void ProvenanceRangeToOffsetMappings::Put(
2264ab3302SCarolineConcatto     ProvenanceRange range, std::size_t offset) {
2364ab3302SCarolineConcatto   auto fromTo{map_.equal_range(range)};
2464ab3302SCarolineConcatto   for (auto iter{fromTo.first}; iter != fromTo.second; ++iter) {
2564ab3302SCarolineConcatto     if (range == iter->first) {
2664ab3302SCarolineConcatto       iter->second = std::min(offset, iter->second);
2764ab3302SCarolineConcatto       return;
2864ab3302SCarolineConcatto     }
2964ab3302SCarolineConcatto   }
3064ab3302SCarolineConcatto   if (fromTo.second != map_.end()) {
3164ab3302SCarolineConcatto     map_.emplace_hint(fromTo.second, range, offset);
3264ab3302SCarolineConcatto   } else {
3364ab3302SCarolineConcatto     map_.emplace(range, offset);
3464ab3302SCarolineConcatto   }
3564ab3302SCarolineConcatto }
3664ab3302SCarolineConcatto 
3764ab3302SCarolineConcatto std::optional<std::size_t> ProvenanceRangeToOffsetMappings::Map(
3864ab3302SCarolineConcatto     ProvenanceRange range) const {
3964ab3302SCarolineConcatto   auto fromTo{map_.equal_range(range)};
4064ab3302SCarolineConcatto   std::optional<std::size_t> result;
4164ab3302SCarolineConcatto   for (auto iter{fromTo.first}; iter != fromTo.second; ++iter) {
4264ab3302SCarolineConcatto     ProvenanceRange that{iter->first};
4364ab3302SCarolineConcatto     if (that.Contains(range)) {
4464ab3302SCarolineConcatto       std::size_t offset{iter->second + that.MemberOffset(range.start())};
4564ab3302SCarolineConcatto       if (!result || offset < *result) {
4664ab3302SCarolineConcatto         result = offset;
4764ab3302SCarolineConcatto       }
4864ab3302SCarolineConcatto     }
4964ab3302SCarolineConcatto   }
5064ab3302SCarolineConcatto   return result;
5164ab3302SCarolineConcatto }
5264ab3302SCarolineConcatto 
5364ab3302SCarolineConcatto bool ProvenanceRangeToOffsetMappings::WhollyPrecedes::operator()(
5464ab3302SCarolineConcatto     ProvenanceRange before, ProvenanceRange after) const {
5564ab3302SCarolineConcatto   return before.start() + before.size() <= after.start();
5664ab3302SCarolineConcatto }
5764ab3302SCarolineConcatto 
5864ab3302SCarolineConcatto void OffsetToProvenanceMappings::clear() { provenanceMap_.clear(); }
5964ab3302SCarolineConcatto 
6064ab3302SCarolineConcatto void OffsetToProvenanceMappings::swap(OffsetToProvenanceMappings &that) {
6164ab3302SCarolineConcatto   provenanceMap_.swap(that.provenanceMap_);
6264ab3302SCarolineConcatto }
6364ab3302SCarolineConcatto 
6464ab3302SCarolineConcatto void OffsetToProvenanceMappings::shrink_to_fit() {
6564ab3302SCarolineConcatto   provenanceMap_.shrink_to_fit();
6664ab3302SCarolineConcatto }
6764ab3302SCarolineConcatto 
6864ab3302SCarolineConcatto std::size_t OffsetToProvenanceMappings::SizeInBytes() const {
6964ab3302SCarolineConcatto   if (provenanceMap_.empty()) {
7064ab3302SCarolineConcatto     return 0;
7164ab3302SCarolineConcatto   } else {
7264ab3302SCarolineConcatto     const ContiguousProvenanceMapping &last{provenanceMap_.back()};
7364ab3302SCarolineConcatto     return last.start + last.range.size();
7464ab3302SCarolineConcatto   }
7564ab3302SCarolineConcatto }
7664ab3302SCarolineConcatto 
7764ab3302SCarolineConcatto void OffsetToProvenanceMappings::Put(ProvenanceRange range) {
7864ab3302SCarolineConcatto   if (provenanceMap_.empty()) {
7964ab3302SCarolineConcatto     provenanceMap_.push_back({0, range});
8064ab3302SCarolineConcatto   } else {
8164ab3302SCarolineConcatto     ContiguousProvenanceMapping &last{provenanceMap_.back()};
8264ab3302SCarolineConcatto     if (!last.range.AnnexIfPredecessor(range)) {
8364ab3302SCarolineConcatto       provenanceMap_.push_back({last.start + last.range.size(), range});
8464ab3302SCarolineConcatto     }
8564ab3302SCarolineConcatto   }
8664ab3302SCarolineConcatto }
8764ab3302SCarolineConcatto 
8864ab3302SCarolineConcatto void OffsetToProvenanceMappings::Put(const OffsetToProvenanceMappings &that) {
8964ab3302SCarolineConcatto   for (const auto &map : that.provenanceMap_) {
9064ab3302SCarolineConcatto     Put(map.range);
9164ab3302SCarolineConcatto   }
9264ab3302SCarolineConcatto }
9364ab3302SCarolineConcatto 
9464ab3302SCarolineConcatto ProvenanceRange OffsetToProvenanceMappings::Map(std::size_t at) const {
950eb3299dSpeter klausler   if (provenanceMap_.empty()) {
960eb3299dSpeter klausler     CHECK(at == 0);
970eb3299dSpeter klausler     return {};
980eb3299dSpeter klausler   }
9964ab3302SCarolineConcatto   std::size_t low{0}, count{provenanceMap_.size()};
10064ab3302SCarolineConcatto   while (count > 1) {
10164ab3302SCarolineConcatto     std::size_t mid{low + (count >> 1)};
10264ab3302SCarolineConcatto     if (provenanceMap_[mid].start > at) {
10364ab3302SCarolineConcatto       count = mid - low;
10464ab3302SCarolineConcatto     } else {
10564ab3302SCarolineConcatto       count -= mid - low;
10664ab3302SCarolineConcatto       low = mid;
10764ab3302SCarolineConcatto     }
10864ab3302SCarolineConcatto   }
10964ab3302SCarolineConcatto   std::size_t offset{at - provenanceMap_[low].start};
11064ab3302SCarolineConcatto   return provenanceMap_[low].range.Suffix(offset);
11164ab3302SCarolineConcatto }
11264ab3302SCarolineConcatto 
11364ab3302SCarolineConcatto void OffsetToProvenanceMappings::RemoveLastBytes(std::size_t bytes) {
11464ab3302SCarolineConcatto   for (; bytes > 0; provenanceMap_.pop_back()) {
11564ab3302SCarolineConcatto     CHECK(!provenanceMap_.empty());
11664ab3302SCarolineConcatto     ContiguousProvenanceMapping &last{provenanceMap_.back()};
11764ab3302SCarolineConcatto     std::size_t chunk{last.range.size()};
11864ab3302SCarolineConcatto     if (bytes < chunk) {
11964ab3302SCarolineConcatto       last.range = last.range.Prefix(chunk - bytes);
12064ab3302SCarolineConcatto       break;
12164ab3302SCarolineConcatto     }
12264ab3302SCarolineConcatto     bytes -= chunk;
12364ab3302SCarolineConcatto   }
12464ab3302SCarolineConcatto }
12564ab3302SCarolineConcatto 
12664ab3302SCarolineConcatto ProvenanceRangeToOffsetMappings OffsetToProvenanceMappings::Invert(
12764ab3302SCarolineConcatto     const AllSources &allSources) const {
12864ab3302SCarolineConcatto   ProvenanceRangeToOffsetMappings result;
12964ab3302SCarolineConcatto   for (const auto &contig : provenanceMap_) {
13064ab3302SCarolineConcatto     ProvenanceRange range{contig.range};
13164ab3302SCarolineConcatto     while (!range.empty()) {
13264ab3302SCarolineConcatto       ProvenanceRange source{allSources.IntersectionWithSourceFiles(range)};
13364ab3302SCarolineConcatto       if (source.empty()) {
13464ab3302SCarolineConcatto         break;
13564ab3302SCarolineConcatto       }
13664ab3302SCarolineConcatto       result.Put(
13764ab3302SCarolineConcatto           source, contig.start + contig.range.MemberOffset(source.start()));
13864ab3302SCarolineConcatto       Provenance after{source.NextAfter()};
13964ab3302SCarolineConcatto       if (range.Contains(after)) {
14064ab3302SCarolineConcatto         range = range.Suffix(range.MemberOffset(after));
14164ab3302SCarolineConcatto       } else {
14264ab3302SCarolineConcatto         break;
14364ab3302SCarolineConcatto       }
14464ab3302SCarolineConcatto     }
14564ab3302SCarolineConcatto   }
14664ab3302SCarolineConcatto   return result;
14764ab3302SCarolineConcatto }
14864ab3302SCarolineConcatto 
14964ab3302SCarolineConcatto AllSources::AllSources() : range_{1, 1} {
15064ab3302SCarolineConcatto   // Start the origin_ array with a dummy entry that has a forced provenance,
15164ab3302SCarolineConcatto   // so that provenance offset 0 remains reserved as an uninitialized
15264ab3302SCarolineConcatto   // value.
15364ab3302SCarolineConcatto   origin_.emplace_back(range_, std::string{'?'});
15464ab3302SCarolineConcatto }
15564ab3302SCarolineConcatto 
15664ab3302SCarolineConcatto AllSources::~AllSources() {}
15764ab3302SCarolineConcatto 
15864ab3302SCarolineConcatto const char &AllSources::operator[](Provenance at) const {
15964ab3302SCarolineConcatto   const Origin &origin{MapToOrigin(at)};
16064ab3302SCarolineConcatto   return origin[origin.covers.MemberOffset(at)];
16164ab3302SCarolineConcatto }
16264ab3302SCarolineConcatto 
16352a1346bSPeter Klausler void AllSources::ClearSearchPath() { searchPath_.clear(); }
16452a1346bSPeter Klausler 
1656110e771Speter klausler void AllSources::AppendSearchPathDirectory(std::string directory) {
16664ab3302SCarolineConcatto   // gfortran and ifort append to current path, PGI prepends
16764ab3302SCarolineConcatto   searchPath_.push_back(directory);
16864ab3302SCarolineConcatto }
16964ab3302SCarolineConcatto 
170f7a15e00SPeter Klausler const SourceFile *AllSources::OpenPath(
171f7a15e00SPeter Klausler     std::string path, llvm::raw_ostream &error) {
172f7a15e00SPeter Klausler   std::unique_ptr<SourceFile> source{std::make_unique<SourceFile>(encoding_)};
173f7a15e00SPeter Klausler   if (source->Open(path, error)) {
174f7a15e00SPeter Klausler     return ownedSourceFiles_.emplace_back(std::move(source)).get();
175f7a15e00SPeter Klausler   } else {
176f7a15e00SPeter Klausler     return nullptr;
177f7a15e00SPeter Klausler   }
178f7a15e00SPeter Klausler }
179f7a15e00SPeter Klausler 
1806110e771Speter klausler const SourceFile *AllSources::Open(std::string path, llvm::raw_ostream &error,
1816110e771Speter klausler     std::optional<std::string> &&prependPath) {
18264ab3302SCarolineConcatto   std::unique_ptr<SourceFile> source{std::make_unique<SourceFile>(encoding_)};
1836110e771Speter klausler   if (prependPath) {
1846110e771Speter klausler     // Set to "." for the initial source file; set to the directory name
1856110e771Speter klausler     // of the including file for #include "quoted-file" directives &
1866110e771Speter klausler     // INCLUDE statements.
1876110e771Speter klausler     searchPath_.emplace_front(std::move(*prependPath));
1886110e771Speter klausler   }
1896110e771Speter klausler   std::optional<std::string> found{LocateSourceFile(path, searchPath_)};
1906110e771Speter klausler   if (prependPath) {
1916110e771Speter klausler     searchPath_.pop_front();
1926110e771Speter klausler   }
193f7a15e00SPeter Klausler   if (found) {
194f7a15e00SPeter Klausler     return OpenPath(*found, error);
19564ab3302SCarolineConcatto   } else {
196f7a15e00SPeter Klausler     error << "Source file '" << path << "' was not found";
19764ab3302SCarolineConcatto     return nullptr;
19864ab3302SCarolineConcatto   }
19964ab3302SCarolineConcatto }
20064ab3302SCarolineConcatto 
2018670e499SCaroline Concatto const SourceFile *AllSources::ReadStandardInput(llvm::raw_ostream &error) {
20264ab3302SCarolineConcatto   std::unique_ptr<SourceFile> source{std::make_unique<SourceFile>(encoding_)};
20364ab3302SCarolineConcatto   if (source->ReadStandardInput(error)) {
20464ab3302SCarolineConcatto     return ownedSourceFiles_.emplace_back(std::move(source)).get();
20564ab3302SCarolineConcatto   }
20664ab3302SCarolineConcatto   return nullptr;
20764ab3302SCarolineConcatto }
20864ab3302SCarolineConcatto 
20964ab3302SCarolineConcatto ProvenanceRange AllSources::AddIncludedFile(
21064ab3302SCarolineConcatto     const SourceFile &source, ProvenanceRange from, bool isModule) {
21164ab3302SCarolineConcatto   ProvenanceRange covers{range_.NextAfter(), source.bytes()};
21264ab3302SCarolineConcatto   CHECK(range_.AnnexIfPredecessor(covers));
21364ab3302SCarolineConcatto   CHECK(origin_.back().covers.ImmediatelyPrecedes(covers));
21464ab3302SCarolineConcatto   origin_.emplace_back(covers, source, from, isModule);
21564ab3302SCarolineConcatto   return covers;
21664ab3302SCarolineConcatto }
21764ab3302SCarolineConcatto 
21864ab3302SCarolineConcatto ProvenanceRange AllSources::AddMacroCall(
21964ab3302SCarolineConcatto     ProvenanceRange def, ProvenanceRange use, const std::string &expansion) {
22064ab3302SCarolineConcatto   ProvenanceRange covers{range_.NextAfter(), expansion.size()};
22164ab3302SCarolineConcatto   CHECK(range_.AnnexIfPredecessor(covers));
22264ab3302SCarolineConcatto   CHECK(origin_.back().covers.ImmediatelyPrecedes(covers));
22364ab3302SCarolineConcatto   origin_.emplace_back(covers, def, use, expansion);
22464ab3302SCarolineConcatto   return covers;
22564ab3302SCarolineConcatto }
22664ab3302SCarolineConcatto 
22764ab3302SCarolineConcatto ProvenanceRange AllSources::AddCompilerInsertion(std::string text) {
22864ab3302SCarolineConcatto   ProvenanceRange covers{range_.NextAfter(), text.size()};
22964ab3302SCarolineConcatto   CHECK(range_.AnnexIfPredecessor(covers));
23064ab3302SCarolineConcatto   CHECK(origin_.back().covers.ImmediatelyPrecedes(covers));
23164ab3302SCarolineConcatto   origin_.emplace_back(covers, text);
23264ab3302SCarolineConcatto   return covers;
23364ab3302SCarolineConcatto }
23464ab3302SCarolineConcatto 
2358df63a23SPeixin Qiao static void EmitPrefix(llvm::raw_ostream &o, llvm::raw_ostream::Colors color,
2368df63a23SPeixin Qiao     const std::string &prefix, bool showColors) {
2378df63a23SPeixin Qiao   if (prefix.empty()) {
2388df63a23SPeixin Qiao     return;
2398df63a23SPeixin Qiao   }
2408df63a23SPeixin Qiao   if (showColors) {
2418df63a23SPeixin Qiao     o.changeColor(color, true);
2428df63a23SPeixin Qiao   }
2438df63a23SPeixin Qiao   o << prefix;
2448df63a23SPeixin Qiao   if (showColors) {
2458df63a23SPeixin Qiao     o.resetColor();
2468df63a23SPeixin Qiao   }
2478df63a23SPeixin Qiao }
2488df63a23SPeixin Qiao 
2490ee0eeb4SValentin Clement (バレンタイン クレメン) std::optional<ProvenanceRange> AllSources::GetInclusionInfo(
2500ee0eeb4SValentin Clement (バレンタイン クレメン)     const std::optional<ProvenanceRange> &range) const {
251*c1a750b8SValentin Clement (バレンタイン クレメン)   if (!range || !IsValid(range->start()))
2520ee0eeb4SValentin Clement (バレンタイン クレメン)     return std::nullopt;
2530ee0eeb4SValentin Clement (バレンタイン クレメン)   const Origin &origin{MapToOrigin(range->start())};
2540ee0eeb4SValentin Clement (バレンタイン クレメン) 
2550ee0eeb4SValentin Clement (バレンタイン クレメン)   return common::visit(
2560ee0eeb4SValentin Clement (バレンタイン クレメン)       common::visitors{
2570ee0eeb4SValentin Clement (バレンタイン クレメン)           [&](const Inclusion &inc) -> std::optional<ProvenanceRange> {
2580ee0eeb4SValentin Clement (バレンタイン クレメン)             if (IsValid(origin.replaces) &&
2590ee0eeb4SValentin Clement (バレンタイン クレメン)                 range_.Contains(origin.replaces.start()))
2600ee0eeb4SValentin Clement (バレンタイン クレメン)               return origin.replaces;
2610ee0eeb4SValentin Clement (バレンタイン クレメン)             return std::nullopt;
2620ee0eeb4SValentin Clement (バレンタイン クレメン)           },
2630ee0eeb4SValentin Clement (バレンタイン クレメン)           [&](const auto &) -> std::optional<ProvenanceRange> {
2640ee0eeb4SValentin Clement (バレンタイン クレメン)             return std::nullopt;
2650ee0eeb4SValentin Clement (バレンタイン クレメン)           },
2660ee0eeb4SValentin Clement (バレンタイン クレメン)       },
2670ee0eeb4SValentin Clement (バレンタイン クレメン)       origin.u);
2680ee0eeb4SValentin Clement (バレンタイン クレメン) }
2690ee0eeb4SValentin Clement (バレンタイン クレメン) 
2708670e499SCaroline Concatto void AllSources::EmitMessage(llvm::raw_ostream &o,
27164ab3302SCarolineConcatto     const std::optional<ProvenanceRange> &range, const std::string &message,
2728df63a23SPeixin Qiao     const std::string &prefix, llvm::raw_ostream::Colors color,
27364ab3302SCarolineConcatto     bool echoSourceLine) const {
27464ab3302SCarolineConcatto   if (!range) {
2758df63a23SPeixin Qiao     EmitPrefix(o, color, prefix, this->getShowColors());
27664ab3302SCarolineConcatto     o << message << '\n';
27764ab3302SCarolineConcatto     return;
27864ab3302SCarolineConcatto   }
27964ab3302SCarolineConcatto   CHECK(IsValid(*range));
28064ab3302SCarolineConcatto   const Origin &origin{MapToOrigin(range->start())};
281cd03e96fSPeter Klausler   common::visit(
28264ab3302SCarolineConcatto       common::visitors{
28364ab3302SCarolineConcatto           [&](const Inclusion &inc) {
28464ab3302SCarolineConcatto             std::size_t offset{origin.covers.MemberOffset(range->start())};
285e12ffe6aSPeter Klausler             SourcePosition pos{inc.source.GetSourcePosition(offset)};
286e12ffe6aSPeter Klausler             o << pos.path << ':' << pos.line << ':' << pos.column << ": ";
2878df63a23SPeixin Qiao             EmitPrefix(o, color, prefix, this->getShowColors());
2888df63a23SPeixin Qiao             o << message << '\n';
28964ab3302SCarolineConcatto             if (echoSourceLine) {
29013ea73e4SDavid Truby               const char *text{inc.source.content().data() +
291e12ffe6aSPeter Klausler                   inc.source.GetLineStartOffset(pos.trueLineNumber)};
29264ab3302SCarolineConcatto               o << "  ";
29364ab3302SCarolineConcatto               for (const char *p{text}; *p != '\n'; ++p) {
29464ab3302SCarolineConcatto                 o << *p;
29564ab3302SCarolineConcatto               }
29664ab3302SCarolineConcatto               o << "\n  ";
29764ab3302SCarolineConcatto               for (int j{1}; j < pos.column; ++j) {
29864ab3302SCarolineConcatto                 char ch{text[j - 1]};
29964ab3302SCarolineConcatto                 o << (ch == '\t' ? '\t' : ' ');
30064ab3302SCarolineConcatto               }
30164ab3302SCarolineConcatto               o << '^';
30264ab3302SCarolineConcatto               if (range->size() > 1) {
30364ab3302SCarolineConcatto                 auto last{range->start() + range->size() - 1};
30464ab3302SCarolineConcatto                 if (&MapToOrigin(last) == &origin) {
30564ab3302SCarolineConcatto                   auto endOffset{origin.covers.MemberOffset(last)};
306e12ffe6aSPeter Klausler                   auto endPos{inc.source.GetSourcePosition(endOffset)};
30764ab3302SCarolineConcatto                   if (pos.line == endPos.line) {
30864ab3302SCarolineConcatto                     for (int j{pos.column}; j < endPos.column; ++j) {
30964ab3302SCarolineConcatto                       o << '^';
31064ab3302SCarolineConcatto                     }
31164ab3302SCarolineConcatto                   }
31264ab3302SCarolineConcatto                 }
31364ab3302SCarolineConcatto               }
31464ab3302SCarolineConcatto               o << '\n';
31564ab3302SCarolineConcatto             }
31664ab3302SCarolineConcatto             if (IsValid(origin.replaces)) {
31764ab3302SCarolineConcatto               EmitMessage(o, origin.replaces,
3188df63a23SPeixin Qiao                   inc.isModule ? "used here"s : "included here"s, prefix, color,
31964ab3302SCarolineConcatto                   echoSourceLine);
32064ab3302SCarolineConcatto             }
32164ab3302SCarolineConcatto           },
32264ab3302SCarolineConcatto           [&](const Macro &mac) {
32364ab3302SCarolineConcatto             EmitMessage(
3248df63a23SPeixin Qiao                 o, origin.replaces, message, prefix, color, echoSourceLine);
325042c964dSPeter Klausler             EmitMessage(o, mac.definition, "in a macro defined here", ""s,
3268df63a23SPeixin Qiao                 color, echoSourceLine);
32764ab3302SCarolineConcatto             if (echoSourceLine) {
32864ab3302SCarolineConcatto               o << "that expanded to:\n  " << mac.expansion << "\n  ";
32964ab3302SCarolineConcatto               for (std::size_t j{0};
33064ab3302SCarolineConcatto                    origin.covers.OffsetMember(j) < range->start(); ++j) {
33164ab3302SCarolineConcatto                 o << (mac.expansion[j] == '\t' ? '\t' : ' ');
33264ab3302SCarolineConcatto               }
33364ab3302SCarolineConcatto               o << "^\n";
33464ab3302SCarolineConcatto             }
33564ab3302SCarolineConcatto           },
3368df63a23SPeixin Qiao           [&](const CompilerInsertion &) {
3378df63a23SPeixin Qiao             EmitPrefix(o, color, prefix, this->getShowColors());
3388df63a23SPeixin Qiao             o << message << '\n';
3398df63a23SPeixin Qiao           },
34064ab3302SCarolineConcatto       },
34164ab3302SCarolineConcatto       origin.u);
34264ab3302SCarolineConcatto }
34364ab3302SCarolineConcatto 
34464ab3302SCarolineConcatto const SourceFile *AllSources::GetSourceFile(
3455024a6ecSPeter Klausler     Provenance at, std::size_t *offset, bool topLevel) const {
34664ab3302SCarolineConcatto   const Origin &origin{MapToOrigin(at)};
347cd03e96fSPeter Klausler   return common::visit(common::visitors{
34864ab3302SCarolineConcatto                            [&](const Inclusion &inc) {
3495024a6ecSPeter Klausler                              if (topLevel && !origin.replaces.empty()) {
3505024a6ecSPeter Klausler                                return GetSourceFile(
3515024a6ecSPeter Klausler                                    origin.replaces.start(), offset, topLevel);
3525024a6ecSPeter Klausler                              } else {
35364ab3302SCarolineConcatto                                if (offset) {
35464ab3302SCarolineConcatto                                  *offset = origin.covers.MemberOffset(at);
35564ab3302SCarolineConcatto                                }
35664ab3302SCarolineConcatto                                return &inc.source;
3575024a6ecSPeter Klausler                              }
35864ab3302SCarolineConcatto                            },
35964ab3302SCarolineConcatto                            [&](const Macro &) {
360cd03e96fSPeter Klausler                              return GetSourceFile(
361cd03e96fSPeter Klausler                                  origin.replaces.start(), offset);
36264ab3302SCarolineConcatto                            },
36364ab3302SCarolineConcatto                            [offset](const CompilerInsertion &) {
36464ab3302SCarolineConcatto                              if (offset) {
36564ab3302SCarolineConcatto                                *offset = 0;
36664ab3302SCarolineConcatto                              }
36764ab3302SCarolineConcatto                              return static_cast<const SourceFile *>(nullptr);
36864ab3302SCarolineConcatto                            },
36964ab3302SCarolineConcatto                        },
37064ab3302SCarolineConcatto       origin.u);
37164ab3302SCarolineConcatto }
37264ab3302SCarolineConcatto 
3735881bf00Speter klausler const char *AllSources::GetSource(ProvenanceRange range) const {
3745881bf00Speter klausler   Provenance start{range.start()};
3755881bf00Speter klausler   const Origin &origin{MapToOrigin(start)};
3765881bf00Speter klausler   return origin.covers.Contains(range)
3775881bf00Speter klausler       ? &origin[origin.covers.MemberOffset(start)]
3785881bf00Speter klausler       : nullptr;
3795881bf00Speter klausler }
3805881bf00Speter klausler 
38164ab3302SCarolineConcatto std::optional<SourcePosition> AllSources::GetSourcePosition(
38264ab3302SCarolineConcatto     Provenance prov) const {
38364ab3302SCarolineConcatto   const Origin &origin{MapToOrigin(prov)};
384cd03e96fSPeter Klausler   return common::visit(
3853338ef93Speter klausler       common::visitors{
3863338ef93Speter klausler           [&](const Inclusion &inc) -> std::optional<SourcePosition> {
38764ab3302SCarolineConcatto             std::size_t offset{origin.covers.MemberOffset(prov)};
388e12ffe6aSPeter Klausler             return inc.source.GetSourcePosition(offset);
3893338ef93Speter klausler           },
3903338ef93Speter klausler           [&](const Macro &) {
3913338ef93Speter klausler             return GetSourcePosition(origin.replaces.start());
3923338ef93Speter klausler           },
3933338ef93Speter klausler           [](const CompilerInsertion &) -> std::optional<SourcePosition> {
39464ab3302SCarolineConcatto             return std::nullopt;
3953338ef93Speter klausler           },
3963338ef93Speter klausler       },
3973338ef93Speter klausler       origin.u);
39864ab3302SCarolineConcatto }
39964ab3302SCarolineConcatto 
40064ab3302SCarolineConcatto std::optional<ProvenanceRange> AllSources::GetFirstFileProvenance() const {
40164ab3302SCarolineConcatto   for (const auto &origin : origin_) {
40264ab3302SCarolineConcatto     if (std::holds_alternative<Inclusion>(origin.u)) {
40364ab3302SCarolineConcatto       return origin.covers;
40464ab3302SCarolineConcatto     }
40564ab3302SCarolineConcatto   }
40664ab3302SCarolineConcatto   return std::nullopt;
40764ab3302SCarolineConcatto }
40864ab3302SCarolineConcatto 
4095024a6ecSPeter Klausler std::string AllSources::GetPath(Provenance at, bool topLevel) const {
410e12ffe6aSPeter Klausler   std::size_t offset{0};
4115024a6ecSPeter Klausler   const SourceFile *source{GetSourceFile(at, &offset, topLevel)};
412e12ffe6aSPeter Klausler   return source ? *source->GetSourcePosition(offset).path : ""s;
41364ab3302SCarolineConcatto }
41464ab3302SCarolineConcatto 
41564ab3302SCarolineConcatto int AllSources::GetLineNumber(Provenance at) const {
41664ab3302SCarolineConcatto   std::size_t offset{0};
41764ab3302SCarolineConcatto   const SourceFile *source{GetSourceFile(at, &offset)};
418e12ffe6aSPeter Klausler   return source ? source->GetSourcePosition(offset).line : 0;
41964ab3302SCarolineConcatto }
42064ab3302SCarolineConcatto 
42164ab3302SCarolineConcatto Provenance AllSources::CompilerInsertionProvenance(char ch) {
42264ab3302SCarolineConcatto   auto iter{compilerInsertionProvenance_.find(ch)};
42364ab3302SCarolineConcatto   if (iter != compilerInsertionProvenance_.end()) {
42464ab3302SCarolineConcatto     return iter->second;
42564ab3302SCarolineConcatto   }
42664ab3302SCarolineConcatto   ProvenanceRange newCharRange{AddCompilerInsertion(std::string{ch})};
42764ab3302SCarolineConcatto   Provenance newCharProvenance{newCharRange.start()};
42864ab3302SCarolineConcatto   compilerInsertionProvenance_.insert(std::make_pair(ch, newCharProvenance));
42964ab3302SCarolineConcatto   return newCharProvenance;
43064ab3302SCarolineConcatto }
43164ab3302SCarolineConcatto 
43264ab3302SCarolineConcatto ProvenanceRange AllSources::IntersectionWithSourceFiles(
43364ab3302SCarolineConcatto     ProvenanceRange range) const {
43464ab3302SCarolineConcatto   if (range.empty()) {
43564ab3302SCarolineConcatto     return {};
43664ab3302SCarolineConcatto   } else {
43764ab3302SCarolineConcatto     const Origin &origin{MapToOrigin(range.start())};
43864ab3302SCarolineConcatto     if (std::holds_alternative<Inclusion>(origin.u)) {
43964ab3302SCarolineConcatto       return range.Intersection(origin.covers);
44064ab3302SCarolineConcatto     } else {
44164ab3302SCarolineConcatto       auto skip{
44264ab3302SCarolineConcatto           origin.covers.size() - origin.covers.MemberOffset(range.start())};
44364ab3302SCarolineConcatto       return IntersectionWithSourceFiles(range.Suffix(skip));
44464ab3302SCarolineConcatto     }
44564ab3302SCarolineConcatto   }
44664ab3302SCarolineConcatto }
44764ab3302SCarolineConcatto 
44864ab3302SCarolineConcatto AllSources::Origin::Origin(ProvenanceRange r, const SourceFile &source)
44964ab3302SCarolineConcatto     : u{Inclusion{source}}, covers{r} {}
45064ab3302SCarolineConcatto AllSources::Origin::Origin(ProvenanceRange r, const SourceFile &included,
45164ab3302SCarolineConcatto     ProvenanceRange from, bool isModule)
45264ab3302SCarolineConcatto     : u{Inclusion{included, isModule}}, covers{r}, replaces{from} {}
45364ab3302SCarolineConcatto AllSources::Origin::Origin(ProvenanceRange r, ProvenanceRange def,
45464ab3302SCarolineConcatto     ProvenanceRange use, const std::string &expansion)
45564ab3302SCarolineConcatto     : u{Macro{def, expansion}}, covers{r}, replaces{use} {}
45664ab3302SCarolineConcatto AllSources::Origin::Origin(ProvenanceRange r, const std::string &text)
45764ab3302SCarolineConcatto     : u{CompilerInsertion{text}}, covers{r} {}
45864ab3302SCarolineConcatto 
45964ab3302SCarolineConcatto const char &AllSources::Origin::operator[](std::size_t n) const {
460cd03e96fSPeter Klausler   return common::visit(
46164ab3302SCarolineConcatto       common::visitors{
46264ab3302SCarolineConcatto           [n](const Inclusion &inc) -> const char & {
46364ab3302SCarolineConcatto             return inc.source.content()[n];
46464ab3302SCarolineConcatto           },
46564ab3302SCarolineConcatto           [n](const Macro &mac) -> const char & { return mac.expansion[n]; },
46664ab3302SCarolineConcatto           [n](const CompilerInsertion &ins) -> const char & {
46764ab3302SCarolineConcatto             return ins.text[n];
46864ab3302SCarolineConcatto           },
46964ab3302SCarolineConcatto       },
47064ab3302SCarolineConcatto       u);
47164ab3302SCarolineConcatto }
47264ab3302SCarolineConcatto 
47364ab3302SCarolineConcatto const AllSources::Origin &AllSources::MapToOrigin(Provenance at) const {
47464ab3302SCarolineConcatto   CHECK(range_.Contains(at));
47564ab3302SCarolineConcatto   std::size_t low{0}, count{origin_.size()};
47664ab3302SCarolineConcatto   while (count > 1) {
47764ab3302SCarolineConcatto     std::size_t mid{low + (count >> 1)};
47864ab3302SCarolineConcatto     if (at < origin_[mid].covers.start()) {
47964ab3302SCarolineConcatto       count = mid - low;
48064ab3302SCarolineConcatto     } else {
48164ab3302SCarolineConcatto       count -= mid - low;
48264ab3302SCarolineConcatto       low = mid;
48364ab3302SCarolineConcatto     }
48464ab3302SCarolineConcatto   }
48564ab3302SCarolineConcatto   CHECK(origin_[low].covers.Contains(at));
48664ab3302SCarolineConcatto   return origin_[low];
48764ab3302SCarolineConcatto }
48864ab3302SCarolineConcatto 
489c87e94b0SjeanPerier Provenance AllSources::GetReplacedProvenance(Provenance provenance) const {
490c87e94b0SjeanPerier   const Origin &origin{MapToOrigin(provenance)};
491c87e94b0SjeanPerier   if (std::holds_alternative<Macro>(origin.u)) {
492c87e94b0SjeanPerier     return origin.replaces.start();
493c87e94b0SjeanPerier   }
494c87e94b0SjeanPerier   return provenance;
495c87e94b0SjeanPerier }
496c87e94b0SjeanPerier 
49764ab3302SCarolineConcatto std::optional<ProvenanceRange> CookedSource::GetProvenanceRange(
49864ab3302SCarolineConcatto     CharBlock cookedRange) const {
4995881bf00Speter klausler   if (!AsCharBlock().Contains(cookedRange)) {
50064ab3302SCarolineConcatto     return std::nullopt;
50164ab3302SCarolineConcatto   }
50264ab3302SCarolineConcatto   ProvenanceRange first{provenanceMap_.Map(cookedRange.begin() - &data_[0])};
503d7ea6068SPeter Klausler   if (cookedRange.size() <= first.size()) { // always true when empty
50464ab3302SCarolineConcatto     return first.Prefix(cookedRange.size());
50564ab3302SCarolineConcatto   }
506d7ea6068SPeter Klausler   ProvenanceRange last{provenanceMap_.Map(cookedRange.end() - 1 - &data_[0])};
507d7ea6068SPeter Klausler   if (first.start() <= last.start()) {
508d7ea6068SPeter Klausler     return {ProvenanceRange{first.start(), last.start() - first.start() + 1}};
509d7ea6068SPeter Klausler   } else {
510c87e94b0SjeanPerier     // cookedRange may start (resp. end) in a macro expansion while it does not
511c87e94b0SjeanPerier     // end (resp. start) in this macro expansion. Attempt to build a range
512c87e94b0SjeanPerier     // over the replaced source.
513c87e94b0SjeanPerier     Provenance firstStart{allSources_.GetReplacedProvenance(first.start())};
514c87e94b0SjeanPerier     Provenance lastStart{allSources_.GetReplacedProvenance(last.start())};
515c87e94b0SjeanPerier     if (firstStart <= lastStart) {
516c87e94b0SjeanPerier       return {ProvenanceRange{firstStart, lastStart - firstStart + 1}};
517c87e94b0SjeanPerier     } else {
518d7ea6068SPeter Klausler       return std::nullopt;
519d7ea6068SPeter Klausler     }
52064ab3302SCarolineConcatto   }
521c87e94b0SjeanPerier }
52264ab3302SCarolineConcatto 
52364ab3302SCarolineConcatto std::optional<CharBlock> CookedSource::GetCharBlock(
52464ab3302SCarolineConcatto     ProvenanceRange range) const {
52564ab3302SCarolineConcatto   CHECK(!invertedMap_.empty() &&
52664ab3302SCarolineConcatto       "CompileProvenanceRangeToOffsetMappings not called");
52764ab3302SCarolineConcatto   if (auto to{invertedMap_.Map(range)}) {
52864ab3302SCarolineConcatto     return CharBlock{data_.c_str() + *to, range.size()};
52964ab3302SCarolineConcatto   } else {
53064ab3302SCarolineConcatto     return std::nullopt;
53164ab3302SCarolineConcatto   }
53264ab3302SCarolineConcatto }
53364ab3302SCarolineConcatto 
53464ab3302SCarolineConcatto std::size_t CookedSource::BufferedBytes() const { return buffer_.bytes(); }
53564ab3302SCarolineConcatto 
53646ade6d0Speter klausler void CookedSource::Marshal(AllCookedSources &allCookedSources) {
53764ab3302SCarolineConcatto   CHECK(provenanceMap_.SizeInBytes() == buffer_.bytes());
53846ade6d0Speter klausler   provenanceMap_.Put(allCookedSources.allSources().AddCompilerInsertion(
53946ade6d0Speter klausler       "(after end of source)"));
54064ab3302SCarolineConcatto   data_ = buffer_.Marshal();
54164ab3302SCarolineConcatto   buffer_.clear();
54286bee819SPeter Klausler   for (std::size_t ffStart : possibleFixedFormContinuations_) {
54386bee819SPeter Klausler     if (ffStart > 0 && ffStart + 1 < data_.size() &&
54486bee819SPeter Klausler         data_[ffStart - 1] == '\n' && data_[ffStart] == ' ') {
54586bee819SPeter Klausler       // This fixed form include line is the first source line in an
54686bee819SPeter Klausler       // #include file (or after an empty one).  Connect it with the previous
54786bee819SPeter Klausler       // source line by deleting its terminal newline.
54886bee819SPeter Klausler       data_[ffStart - 1] = ' ';
54986bee819SPeter Klausler     }
55086bee819SPeter Klausler   }
55186bee819SPeter Klausler   possibleFixedFormContinuations_.clear();
55246ade6d0Speter klausler   allCookedSources.Register(*this);
55364ab3302SCarolineConcatto }
55464ab3302SCarolineConcatto 
55592a54197Speter klausler void CookedSource::CompileProvenanceRangeToOffsetMappings(
55692a54197Speter klausler     AllSources &allSources) {
55764ab3302SCarolineConcatto   if (invertedMap_.empty()) {
55892a54197Speter klausler     invertedMap_ = provenanceMap_.Invert(allSources);
55964ab3302SCarolineConcatto   }
56064ab3302SCarolineConcatto }
56164ab3302SCarolineConcatto 
5628670e499SCaroline Concatto static void DumpRange(llvm::raw_ostream &o, const ProvenanceRange &r) {
56364ab3302SCarolineConcatto   o << "[" << r.start().offset() << ".." << r.Last().offset() << "] ("
56464ab3302SCarolineConcatto     << r.size() << " bytes)";
56564ab3302SCarolineConcatto }
56664ab3302SCarolineConcatto 
5678670e499SCaroline Concatto llvm::raw_ostream &ProvenanceRangeToOffsetMappings::Dump(
5688670e499SCaroline Concatto     llvm::raw_ostream &o) const {
56964ab3302SCarolineConcatto   for (const auto &m : map_) {
57064ab3302SCarolineConcatto     o << "provenances ";
57164ab3302SCarolineConcatto     DumpRange(o, m.first);
57264ab3302SCarolineConcatto     o << " -> offsets [" << m.second << ".." << (m.second + m.first.size() - 1)
57364ab3302SCarolineConcatto       << "]\n";
57464ab3302SCarolineConcatto   }
57564ab3302SCarolineConcatto   return o;
57664ab3302SCarolineConcatto }
57764ab3302SCarolineConcatto 
5788670e499SCaroline Concatto llvm::raw_ostream &OffsetToProvenanceMappings::Dump(
5798670e499SCaroline Concatto     llvm::raw_ostream &o) const {
58064ab3302SCarolineConcatto   for (const ContiguousProvenanceMapping &m : provenanceMap_) {
58164ab3302SCarolineConcatto     std::size_t n{m.range.size()};
58264ab3302SCarolineConcatto     o << "offsets [" << m.start << ".." << (m.start + n - 1)
58364ab3302SCarolineConcatto       << "] -> provenances ";
58464ab3302SCarolineConcatto     DumpRange(o, m.range);
58564ab3302SCarolineConcatto     o << '\n';
58664ab3302SCarolineConcatto   }
58764ab3302SCarolineConcatto   return o;
58864ab3302SCarolineConcatto }
58964ab3302SCarolineConcatto 
5908670e499SCaroline Concatto llvm::raw_ostream &AllSources::Dump(llvm::raw_ostream &o) const {
59164ab3302SCarolineConcatto   o << "AllSources range_ ";
59264ab3302SCarolineConcatto   DumpRange(o, range_);
59364ab3302SCarolineConcatto   o << '\n';
594e12ffe6aSPeter Klausler   std::set<const SourceFile *> sources;
59564ab3302SCarolineConcatto   for (const Origin &m : origin_) {
59664ab3302SCarolineConcatto     o << "   ";
59764ab3302SCarolineConcatto     DumpRange(o, m.covers);
59864ab3302SCarolineConcatto     o << " -> ";
599cd03e96fSPeter Klausler     common::visit(common::visitors{
60064ab3302SCarolineConcatto                       [&](const Inclusion &inc) {
60164ab3302SCarolineConcatto                         if (inc.isModule) {
60264ab3302SCarolineConcatto                           o << "module ";
60364ab3302SCarolineConcatto                         }
60464ab3302SCarolineConcatto                         o << "file " << inc.source.path();
605e12ffe6aSPeter Klausler                         sources.emplace(&inc.source);
60664ab3302SCarolineConcatto                       },
60764ab3302SCarolineConcatto                       [&](const Macro &mac) { o << "macro " << mac.expansion; },
60864ab3302SCarolineConcatto                       [&](const CompilerInsertion &ins) {
60964ab3302SCarolineConcatto                         o << "compiler '" << ins.text << '\'';
61064ab3302SCarolineConcatto                         if (ins.text.length() == 1) {
61164ab3302SCarolineConcatto                           int ch = ins.text[0];
6128670e499SCaroline Concatto                           o << "(0x";
6138670e499SCaroline Concatto                           o.write_hex(ch & 0xff) << ")";
61464ab3302SCarolineConcatto                         }
61564ab3302SCarolineConcatto                       },
61664ab3302SCarolineConcatto                   },
61764ab3302SCarolineConcatto         m.u);
61864ab3302SCarolineConcatto     if (IsValid(m.replaces)) {
61964ab3302SCarolineConcatto       o << " replaces ";
62064ab3302SCarolineConcatto       DumpRange(o, m.replaces);
62164ab3302SCarolineConcatto     }
62264ab3302SCarolineConcatto     o << '\n';
62364ab3302SCarolineConcatto   }
624e12ffe6aSPeter Klausler   for (const SourceFile *sf : sources) {
625e12ffe6aSPeter Klausler     sf->Dump(o);
626e12ffe6aSPeter Klausler   }
62764ab3302SCarolineConcatto   return o;
62864ab3302SCarolineConcatto }
62964ab3302SCarolineConcatto 
6308670e499SCaroline Concatto llvm::raw_ostream &CookedSource::Dump(llvm::raw_ostream &o) const {
63164ab3302SCarolineConcatto   o << "CookedSource::provenanceMap_:\n";
63264ab3302SCarolineConcatto   provenanceMap_.Dump(o);
63364ab3302SCarolineConcatto   o << "CookedSource::invertedMap_:\n";
63464ab3302SCarolineConcatto   invertedMap_.Dump(o);
63564ab3302SCarolineConcatto   return o;
63664ab3302SCarolineConcatto }
63792a54197Speter klausler 
63892a54197Speter klausler AllCookedSources::AllCookedSources(AllSources &s) : allSources_{s} {}
63992a54197Speter klausler AllCookedSources::~AllCookedSources() {}
64092a54197Speter klausler 
64192a54197Speter klausler CookedSource &AllCookedSources::NewCookedSource() {
642c87e94b0SjeanPerier   return cooked_.emplace_back(allSources_);
64392a54197Speter klausler }
64492a54197Speter klausler 
64546ade6d0Speter klausler const CookedSource *AllCookedSources::Find(CharBlock x) const {
64646ade6d0Speter klausler   auto pair{index_.equal_range(x)};
64746ade6d0Speter klausler   for (auto iter{pair.first}; iter != pair.second; ++iter) {
64846ade6d0Speter klausler     if (iter->second.AsCharBlock().Contains(x)) {
64946ade6d0Speter klausler       return &iter->second;
65046ade6d0Speter klausler     }
65146ade6d0Speter klausler   }
65246ade6d0Speter klausler   return nullptr;
65346ade6d0Speter klausler }
65446ade6d0Speter klausler 
65592a54197Speter klausler std::optional<ProvenanceRange> AllCookedSources::GetProvenanceRange(
65692a54197Speter klausler     CharBlock cb) const {
65792a54197Speter klausler   if (const CookedSource * c{Find(cb)}) {
65892a54197Speter klausler     return c->GetProvenanceRange(cb);
65992a54197Speter klausler   } else {
66092a54197Speter klausler     return std::nullopt;
66192a54197Speter klausler   }
66292a54197Speter klausler }
66392a54197Speter klausler 
66492a54197Speter klausler std::optional<CharBlock> AllCookedSources::GetCharBlockFromLineAndColumns(
66592a54197Speter klausler     int line, int startColumn, int endColumn) const {
66692a54197Speter klausler   // 2nd column is exclusive, meaning it is target column + 1.
66792a54197Speter klausler   CHECK(line > 0 && startColumn > 0 && endColumn > 0);
66892a54197Speter klausler   CHECK(startColumn < endColumn);
66992a54197Speter klausler   auto provenanceStart{allSources_.GetFirstFileProvenance().value().start()};
67092a54197Speter klausler   if (auto sourceFile{allSources_.GetSourceFile(provenanceStart)}) {
67192a54197Speter klausler     CHECK(line <= static_cast<int>(sourceFile->lines()));
67292a54197Speter klausler     return GetCharBlock(ProvenanceRange(sourceFile->GetLineStartOffset(line) +
67392a54197Speter klausler             provenanceStart.offset() + startColumn - 1,
67492a54197Speter klausler         endColumn - startColumn));
67592a54197Speter klausler   }
67692a54197Speter klausler   return std::nullopt;
67792a54197Speter klausler }
67892a54197Speter klausler 
67992a54197Speter klausler std::optional<std::pair<SourcePosition, SourcePosition>>
68092a54197Speter klausler AllCookedSources::GetSourcePositionRange(CharBlock cookedRange) const {
68192a54197Speter klausler   if (auto range{GetProvenanceRange(cookedRange)}) {
68292a54197Speter klausler     if (auto firstOffset{allSources_.GetSourcePosition(range->start())}) {
68392a54197Speter klausler       if (auto secondOffset{
68492a54197Speter klausler               allSources_.GetSourcePosition(range->start() + range->size())}) {
68592a54197Speter klausler         return std::pair{*firstOffset, *secondOffset};
68692a54197Speter klausler       }
68792a54197Speter klausler     }
68892a54197Speter klausler   }
68992a54197Speter klausler   return std::nullopt;
69092a54197Speter klausler }
69192a54197Speter klausler 
69292a54197Speter klausler std::optional<CharBlock> AllCookedSources::GetCharBlock(
69392a54197Speter klausler     ProvenanceRange range) const {
69492a54197Speter klausler   for (const auto &c : cooked_) {
69592a54197Speter klausler     if (auto result{c.GetCharBlock(range)}) {
69692a54197Speter klausler       return result;
69792a54197Speter klausler     }
69892a54197Speter klausler   }
6993338ef93Speter klausler   return std::nullopt;
70092a54197Speter klausler }
70192a54197Speter klausler 
70292a54197Speter klausler void AllCookedSources::Dump(llvm::raw_ostream &o) const {
70392a54197Speter klausler   o << "AllSources:\n";
70492a54197Speter klausler   allSources_.Dump(o);
70592a54197Speter klausler   for (const auto &c : cooked_) {
70692a54197Speter klausler     c.Dump(o);
70792a54197Speter klausler   }
70892a54197Speter klausler }
70992a54197Speter klausler 
71046ade6d0Speter klausler bool AllCookedSources::Precedes(CharBlock x, CharBlock y) const {
71146ade6d0Speter klausler   if (const CookedSource * xSource{Find(x)}) {
7120d8331c0Speter klausler     if (xSource->AsCharBlock().Contains(y)) {
7130d8331c0Speter klausler       return x.begin() < y.begin();
7140d8331c0Speter klausler     } else if (const CookedSource * ySource{Find(y)}) {
7150d8331c0Speter klausler       return xSource->number() < ySource->number();
71646ade6d0Speter klausler     } else {
71746ade6d0Speter klausler       return true; // by fiat, all cooked source < anything outside
71846ade6d0Speter klausler     }
7190d8331c0Speter klausler   } else if (Find(y)) {
72046ade6d0Speter klausler     return false;
72146ade6d0Speter klausler   } else {
72246ade6d0Speter klausler     // Both names are compiler-created (SaveTempName).
72346ade6d0Speter klausler     return x < y;
72446ade6d0Speter klausler   }
72546ade6d0Speter klausler }
72646ade6d0Speter klausler 
72746ade6d0Speter klausler void AllCookedSources::Register(CookedSource &cooked) {
72846ade6d0Speter klausler   index_.emplace(cooked.AsCharBlock(), cooked);
72946ade6d0Speter klausler   cooked.set_number(static_cast<int>(index_.size()));
73046ade6d0Speter klausler }
73146ade6d0Speter klausler 
7321f879005STim Keith } // namespace Fortran::parser
733