2018-05-01 21:50:34 +02:00
|
|
|
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2018-02-08 01:24:02 +01:00
|
|
|
#include "provenance.h"
|
2018-06-18 20:03:43 +02:00
|
|
|
#include "../common/idioms.h"
|
2018-02-08 01:24:02 +01:00
|
|
|
#include <utility>
|
2018-02-15 19:42:36 +01:00
|
|
|
|
2018-05-02 22:48:12 +02:00
|
|
|
namespace Fortran::parser {
|
2018-02-08 01:24:02 +01:00
|
|
|
|
2018-02-15 19:42:36 +01:00
|
|
|
void OffsetToProvenanceMappings::clear() { provenanceMap_.clear(); }
|
|
|
|
|
2018-05-11 20:32:10 +02:00
|
|
|
void OffsetToProvenanceMappings::swap(OffsetToProvenanceMappings &that) {
|
|
|
|
provenanceMap_.swap(that.provenanceMap_);
|
|
|
|
}
|
|
|
|
|
2018-06-22 23:51:15 +02:00
|
|
|
void OffsetToProvenanceMappings::shrink_to_fit() {
|
|
|
|
provenanceMap_.shrink_to_fit();
|
|
|
|
}
|
|
|
|
|
2018-03-20 18:59:07 +01:00
|
|
|
std::size_t OffsetToProvenanceMappings::size() const {
|
2018-02-15 19:42:36 +01:00
|
|
|
if (provenanceMap_.empty()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
const ContiguousProvenanceMapping &last{provenanceMap_.back()};
|
|
|
|
return last.start + last.range.size();
|
2018-02-10 00:56:02 +01:00
|
|
|
}
|
|
|
|
|
2018-02-09 23:04:11 +01:00
|
|
|
void OffsetToProvenanceMappings::Put(ProvenanceRange range) {
|
|
|
|
if (provenanceMap_.empty()) {
|
2018-02-15 19:42:36 +01:00
|
|
|
provenanceMap_.push_back({0, range});
|
2018-02-09 23:04:11 +01:00
|
|
|
} else {
|
|
|
|
ContiguousProvenanceMapping &last{provenanceMap_.back()};
|
2018-02-15 19:42:36 +01:00
|
|
|
if (!last.range.AnnexIfPredecessor(range)) {
|
|
|
|
provenanceMap_.push_back({last.start + last.range.size(), range});
|
2018-02-09 23:04:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-08 01:24:02 +01:00
|
|
|
|
2018-02-09 23:04:11 +01:00
|
|
|
void OffsetToProvenanceMappings::Put(const OffsetToProvenanceMappings &that) {
|
|
|
|
for (const auto &map : that.provenanceMap_) {
|
|
|
|
Put(map.range);
|
|
|
|
}
|
2018-02-08 01:24:02 +01:00
|
|
|
}
|
|
|
|
|
2018-03-20 18:59:07 +01:00
|
|
|
ProvenanceRange OffsetToProvenanceMappings::Map(std::size_t at) const {
|
2018-03-23 23:14:52 +01:00
|
|
|
// CHECK(!provenanceMap_.empty());
|
2018-03-20 18:59:07 +01:00
|
|
|
std::size_t low{0}, count{provenanceMap_.size()};
|
2018-02-09 23:04:11 +01:00
|
|
|
while (count > 1) {
|
2018-03-20 18:59:07 +01:00
|
|
|
std::size_t mid{low + (count >> 1)};
|
2018-02-09 23:04:11 +01:00
|
|
|
if (provenanceMap_[mid].start > at) {
|
|
|
|
count = mid - low;
|
|
|
|
} else {
|
|
|
|
count -= mid - low;
|
|
|
|
low = mid;
|
|
|
|
}
|
|
|
|
}
|
2018-03-20 18:59:07 +01:00
|
|
|
std::size_t offset{at - provenanceMap_[low].start};
|
2018-02-15 19:42:36 +01:00
|
|
|
return provenanceMap_[low].range.Suffix(offset);
|
2018-02-09 23:04:11 +01:00
|
|
|
}
|
|
|
|
|
2018-03-20 18:59:07 +01:00
|
|
|
void OffsetToProvenanceMappings::RemoveLastBytes(std::size_t bytes) {
|
2018-02-09 23:04:11 +01:00
|
|
|
for (; bytes > 0; provenanceMap_.pop_back()) {
|
2018-02-15 19:42:36 +01:00
|
|
|
CHECK(!provenanceMap_.empty());
|
2018-02-09 23:04:11 +01:00
|
|
|
ContiguousProvenanceMapping &last{provenanceMap_.back()};
|
2018-03-20 18:59:07 +01:00
|
|
|
std::size_t chunk{last.range.size()};
|
2018-02-15 19:42:36 +01:00
|
|
|
if (bytes < chunk) {
|
|
|
|
last.range = last.range.Prefix(chunk - bytes);
|
2018-02-09 23:04:11 +01:00
|
|
|
break;
|
|
|
|
}
|
2018-02-15 19:42:36 +01:00
|
|
|
bytes -= chunk;
|
2018-02-09 23:04:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-15 19:42:36 +01:00
|
|
|
AllSources::AllSources() : range_{1, 1} {
|
2018-05-02 21:07:49 +02:00
|
|
|
// Start the origin_ array with a dummy entry that has a forced provenance,
|
2018-02-15 19:42:36 +01:00
|
|
|
// so that provenance offset 0 remains reserved as an uninitialized
|
|
|
|
// value.
|
|
|
|
origin_.emplace_back(range_, std::string{'?'});
|
2018-02-08 01:24:02 +01:00
|
|
|
}
|
|
|
|
|
2018-02-13 23:22:08 +01:00
|
|
|
AllSources::~AllSources() {}
|
|
|
|
|
2018-02-09 23:04:11 +01:00
|
|
|
const char &AllSources::operator[](Provenance at) const {
|
|
|
|
const Origin &origin{MapToOrigin(at)};
|
2018-02-27 23:02:10 +01:00
|
|
|
return origin[origin.covers.MemberOffset(at)];
|
2018-02-09 23:04:11 +01:00
|
|
|
}
|
|
|
|
|
2018-02-14 00:24:43 +01:00
|
|
|
void AllSources::PushSearchPathDirectory(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;
|
|
|
|
}
|
|
|
|
|
2018-02-13 23:22:08 +01:00
|
|
|
const SourceFile *AllSources::Open(std::string path, std::stringstream *error) {
|
|
|
|
std::unique_ptr<SourceFile> source{std::make_unique<SourceFile>()};
|
2018-02-14 00:24:43 +01:00
|
|
|
if (source->Open(LocateSourceFile(path, searchPath_), error)) {
|
2018-02-13 23:22:08 +01:00
|
|
|
return ownedSourceFiles_.emplace_back(std::move(source)).get();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-04-06 19:34:59 +02:00
|
|
|
const SourceFile *AllSources::ReadStandardInput(std::stringstream *error) {
|
|
|
|
std::unique_ptr<SourceFile> source{std::make_unique<SourceFile>()};
|
|
|
|
if (source->ReadStandardInput(error)) {
|
|
|
|
return ownedSourceFiles_.emplace_back(std::move(source)).get();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-02-09 23:04:11 +01:00
|
|
|
ProvenanceRange AllSources::AddIncludedFile(
|
2018-02-15 19:42:36 +01:00
|
|
|
const SourceFile &source, ProvenanceRange from, bool isModule) {
|
|
|
|
ProvenanceRange covers{range_.NextAfter(), source.bytes()};
|
|
|
|
CHECK(range_.AnnexIfPredecessor(covers));
|
2018-02-27 23:02:10 +01:00
|
|
|
CHECK(origin_.back().covers.ImmediatelyPrecedes(covers));
|
2018-02-15 19:42:36 +01:00
|
|
|
origin_.emplace_back(covers, source, from, isModule);
|
|
|
|
return covers;
|
2018-02-09 23:04:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ProvenanceRange AllSources::AddMacroCall(
|
|
|
|
ProvenanceRange def, ProvenanceRange use, const std::string &expansion) {
|
2018-02-15 19:42:36 +01:00
|
|
|
ProvenanceRange covers{range_.NextAfter(), expansion.size()};
|
|
|
|
CHECK(range_.AnnexIfPredecessor(covers));
|
2018-02-27 23:02:10 +01:00
|
|
|
CHECK(origin_.back().covers.ImmediatelyPrecedes(covers));
|
2018-02-15 19:42:36 +01:00
|
|
|
origin_.emplace_back(covers, def, use, expansion);
|
|
|
|
return covers;
|
2018-02-09 23:04:11 +01:00
|
|
|
}
|
|
|
|
|
2018-02-15 19:42:36 +01:00
|
|
|
ProvenanceRange AllSources::AddCompilerInsertion(std::string text) {
|
|
|
|
ProvenanceRange covers{range_.NextAfter(), text.size()};
|
|
|
|
CHECK(range_.AnnexIfPredecessor(covers));
|
2018-02-27 23:02:10 +01:00
|
|
|
CHECK(origin_.back().covers.ImmediatelyPrecedes(covers));
|
2018-02-15 19:42:36 +01:00
|
|
|
origin_.emplace_back(covers, text);
|
|
|
|
return covers;
|
2018-02-09 23:04:11 +01:00
|
|
|
}
|
|
|
|
|
2018-05-02 21:07:49 +02:00
|
|
|
void AllSources::EmitMessage(std::ostream &o, ProvenanceRange range,
|
|
|
|
const std::string &message, bool echoSourceLine) const {
|
2018-04-21 01:56:58 +02:00
|
|
|
CHECK(IsValid(range));
|
|
|
|
const Origin &origin{MapToOrigin(range.start())};
|
2018-02-08 01:24:02 +01:00
|
|
|
std::visit(
|
2018-06-18 20:03:43 +02:00
|
|
|
common::visitors{
|
2018-02-15 19:42:36 +01:00
|
|
|
[&](const Inclusion &inc) {
|
2018-05-02 21:07:49 +02:00
|
|
|
o << inc.source.path();
|
2018-04-21 01:56:58 +02:00
|
|
|
std::size_t offset{origin.covers.MemberOffset(range.start())};
|
2018-02-15 19:42:36 +01:00
|
|
|
std::pair<int, int> pos{inc.source.FindOffsetLineAndColumn(offset)};
|
2018-05-02 21:07:49 +02:00
|
|
|
o << ':' << pos.first << ':' << pos.second;
|
|
|
|
o << ": " << message << '\n';
|
2018-02-15 22:13:28 +01:00
|
|
|
if (echoSourceLine) {
|
|
|
|
const char *text{inc.source.content() +
|
|
|
|
inc.source.GetLineStartOffset(pos.first)};
|
2018-05-02 21:07:49 +02:00
|
|
|
o << " ";
|
2018-02-15 22:13:28 +01:00
|
|
|
for (const char *p{text}; *p != '\n'; ++p) {
|
|
|
|
o << *p;
|
|
|
|
}
|
2018-05-02 21:07:49 +02:00
|
|
|
o << "\n ";
|
2018-02-15 22:13:28 +01:00
|
|
|
for (int j{1}; j < pos.second; ++j) {
|
|
|
|
char ch{text[j - 1]};
|
|
|
|
o << (ch == '\t' ? '\t' : ' ');
|
|
|
|
}
|
2018-04-23 21:17:11 +02:00
|
|
|
o << '^';
|
|
|
|
if (range.size() > 1) {
|
2018-07-11 02:09:07 +02:00
|
|
|
auto last{range.start() + range.size() - 1};
|
2018-04-23 21:17:11 +02:00
|
|
|
if (&MapToOrigin(last) == &origin) {
|
2018-07-11 02:09:07 +02:00
|
|
|
auto endOffset{origin.covers.MemberOffset(last)};
|
|
|
|
auto endPos{inc.source.FindOffsetLineAndColumn(endOffset)};
|
2018-04-23 21:17:11 +02:00
|
|
|
if (pos.first == endPos.first) {
|
|
|
|
for (int j{pos.second}; j < endPos.second; ++j) {
|
|
|
|
o << '^';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-02 21:07:49 +02:00
|
|
|
o << '\n';
|
2018-02-15 22:13:28 +01:00
|
|
|
}
|
2018-02-15 19:42:36 +01:00
|
|
|
if (IsValid(origin.replaces)) {
|
2018-05-02 21:07:49 +02:00
|
|
|
EmitMessage(o, origin.replaces,
|
|
|
|
inc.isModule ? "used here"s : "included here"s,
|
|
|
|
echoSourceLine);
|
2018-02-15 19:42:36 +01:00
|
|
|
}
|
|
|
|
},
|
2018-02-08 01:24:02 +01:00
|
|
|
[&](const Macro &mac) {
|
2018-05-02 21:07:49 +02:00
|
|
|
EmitMessage(o, origin.replaces, message, echoSourceLine);
|
|
|
|
EmitMessage(
|
|
|
|
o, mac.definition, "in a macro defined here", echoSourceLine);
|
2018-02-15 22:36:50 +01:00
|
|
|
if (echoSourceLine) {
|
2018-05-02 21:07:49 +02:00
|
|
|
o << "that expanded to:\n " << mac.expansion << "\n ";
|
2018-04-21 01:56:58 +02:00
|
|
|
for (std::size_t j{0};
|
|
|
|
origin.covers.OffsetMember(j) < range.start(); ++j) {
|
2018-02-15 22:36:50 +01:00
|
|
|
o << (mac.expansion[j] == '\t' ? '\t' : ' ');
|
|
|
|
}
|
|
|
|
o << "^\n";
|
|
|
|
}
|
2018-02-09 23:04:11 +01:00
|
|
|
},
|
2018-05-02 21:07:49 +02:00
|
|
|
[&](const CompilerInsertion &ins) { o << message << '\n'; }},
|
2018-02-09 23:04:11 +01:00
|
|
|
origin.u);
|
2018-02-08 01:24:02 +01:00
|
|
|
}
|
|
|
|
|
2018-02-15 19:42:36 +01:00
|
|
|
const SourceFile *AllSources::GetSourceFile(
|
2018-03-20 18:59:07 +01:00
|
|
|
Provenance at, std::size_t *offset) const {
|
2018-02-09 23:04:11 +01:00
|
|
|
const Origin &origin{MapToOrigin(at)};
|
2018-06-18 20:03:43 +02:00
|
|
|
return std::visit(common::visitors{[&](const Inclusion &inc) {
|
|
|
|
if (offset != nullptr) {
|
|
|
|
*offset =
|
|
|
|
origin.covers.MemberOffset(at);
|
|
|
|
}
|
|
|
|
return &inc.source;
|
|
|
|
},
|
2018-02-27 23:02:10 +01:00
|
|
|
[&](const Macro &mac) {
|
|
|
|
return GetSourceFile(origin.replaces.start(), offset);
|
|
|
|
},
|
|
|
|
[offset](const CompilerInsertion &) {
|
|
|
|
if (offset != nullptr) {
|
|
|
|
*offset = 0;
|
|
|
|
}
|
|
|
|
return static_cast<const SourceFile *>(nullptr);
|
|
|
|
}},
|
2018-02-09 23:04:11 +01:00
|
|
|
origin.u);
|
2018-02-08 01:24:02 +01:00
|
|
|
}
|
|
|
|
|
2018-02-15 19:42:36 +01:00
|
|
|
ProvenanceRange AllSources::GetContiguousRangeAround(
|
|
|
|
ProvenanceRange range) const {
|
|
|
|
CHECK(IsValid(range));
|
2018-02-27 23:02:10 +01:00
|
|
|
const Origin &origin{MapToOrigin(range.start())};
|
2018-02-15 19:42:36 +01:00
|
|
|
CHECK(origin.covers.Contains(range));
|
|
|
|
return origin.covers;
|
2018-02-13 21:24:54 +01:00
|
|
|
}
|
|
|
|
|
2018-02-09 23:04:11 +01:00
|
|
|
std::string AllSources::GetPath(Provenance at) const {
|
|
|
|
const SourceFile *source{GetSourceFile(at)};
|
|
|
|
return source ? source->path() : ""s;
|
2018-02-08 01:24:02 +01:00
|
|
|
}
|
|
|
|
|
2018-02-09 23:04:11 +01:00
|
|
|
int AllSources::GetLineNumber(Provenance at) const {
|
2018-03-20 18:59:07 +01:00
|
|
|
std::size_t offset{0};
|
2018-02-15 19:42:36 +01:00
|
|
|
const SourceFile *source{GetSourceFile(at, &offset)};
|
|
|
|
return source ? source->FindOffsetLineAndColumn(offset).first : 0;
|
2018-02-09 23:04:11 +01:00
|
|
|
}
|
|
|
|
|
2018-02-16 20:14:11 +01:00
|
|
|
Provenance AllSources::CompilerInsertionProvenance(char ch) {
|
2018-07-11 02:09:07 +02:00
|
|
|
auto iter{compilerInsertionProvenance_.find(ch)};
|
2018-02-16 20:14:11 +01:00
|
|
|
if (iter != compilerInsertionProvenance_.end()) {
|
|
|
|
return iter->second;
|
|
|
|
}
|
|
|
|
ProvenanceRange newCharRange{AddCompilerInsertion(std::string{ch})};
|
2018-02-27 23:02:10 +01:00
|
|
|
Provenance newCharProvenance{newCharRange.start()};
|
2018-02-16 20:14:11 +01:00
|
|
|
compilerInsertionProvenance_.insert(std::make_pair(ch, newCharProvenance));
|
|
|
|
return newCharProvenance;
|
2018-02-13 21:24:54 +01:00
|
|
|
}
|
|
|
|
|
2018-02-15 19:42:36 +01:00
|
|
|
AllSources::Origin::Origin(ProvenanceRange r, const SourceFile &source)
|
|
|
|
: u{Inclusion{source}}, covers{r} {}
|
2018-02-15 22:13:28 +01:00
|
|
|
AllSources::Origin::Origin(ProvenanceRange r, const SourceFile &included,
|
|
|
|
ProvenanceRange from, bool isModule)
|
2018-02-15 19:42:36 +01:00
|
|
|
: u{Inclusion{included, isModule}}, covers{r}, replaces{from} {}
|
|
|
|
AllSources::Origin::Origin(ProvenanceRange r, ProvenanceRange def,
|
|
|
|
ProvenanceRange use, const std::string &expansion)
|
|
|
|
: u{Macro{def, expansion}}, covers{r}, replaces{use} {}
|
|
|
|
AllSources::Origin::Origin(ProvenanceRange r, const std::string &text)
|
|
|
|
: u{CompilerInsertion{text}}, covers{r} {}
|
2018-02-09 23:04:11 +01:00
|
|
|
|
2018-03-20 18:59:07 +01:00
|
|
|
const char &AllSources::Origin::operator[](std::size_t n) const {
|
2018-02-09 23:04:11 +01:00
|
|
|
return std::visit(
|
2018-06-18 20:03:43 +02:00
|
|
|
common::visitors{[n](const Inclusion &inc) -> const char & {
|
|
|
|
return inc.source.content()[n];
|
|
|
|
},
|
2018-02-09 23:04:11 +01:00
|
|
|
[n](const Macro &mac) -> const char & { return mac.expansion[n]; },
|
|
|
|
[n](const CompilerInsertion &ins) -> const char & {
|
|
|
|
return ins.text[n];
|
|
|
|
}},
|
|
|
|
u);
|
|
|
|
}
|
|
|
|
|
|
|
|
const AllSources::Origin &AllSources::MapToOrigin(Provenance at) const {
|
2018-02-15 19:42:36 +01:00
|
|
|
CHECK(range_.Contains(at));
|
2018-03-20 18:59:07 +01:00
|
|
|
std::size_t low{0}, count{origin_.size()};
|
2018-02-08 01:24:02 +01:00
|
|
|
while (count > 1) {
|
2018-03-20 18:59:07 +01:00
|
|
|
std::size_t mid{low + (count >> 1)};
|
2018-02-27 23:02:10 +01:00
|
|
|
if (at < origin_[mid].covers.start()) {
|
2018-02-08 01:24:02 +01:00
|
|
|
count = mid - low;
|
|
|
|
} else {
|
|
|
|
count -= mid - low;
|
|
|
|
low = mid;
|
|
|
|
}
|
|
|
|
}
|
2018-02-15 19:42:36 +01:00
|
|
|
CHECK(origin_[low].covers.Contains(at));
|
2018-02-09 23:04:11 +01:00
|
|
|
return origin_[low];
|
2018-02-08 01:24:02 +01:00
|
|
|
}
|
|
|
|
|
2018-05-03 20:09:04 +02:00
|
|
|
ProvenanceRange CookedSource::GetProvenanceRange(CharBlock cookedRange) const {
|
2018-04-21 01:56:58 +02:00
|
|
|
ProvenanceRange range{provenanceMap_.Map(cookedRange.begin() - &data_[0])};
|
|
|
|
if (cookedRange.size() < range.size()) {
|
|
|
|
return {range.start(), cookedRange.size()};
|
|
|
|
}
|
|
|
|
return range;
|
2018-02-09 23:04:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CookedSource::Marshal() {
|
2018-02-10 00:56:02 +01:00
|
|
|
CHECK(provenanceMap_.size() == buffer_.size());
|
2018-03-23 23:14:52 +01:00
|
|
|
provenanceMap_.Put(allSources_.AddCompilerInsertion("(after end of source)"));
|
2018-02-09 23:04:11 +01:00
|
|
|
data_.resize(buffer_.size());
|
|
|
|
char *p{&data_[0]};
|
|
|
|
for (char ch : buffer_) {
|
|
|
|
*p++ = ch;
|
|
|
|
}
|
|
|
|
buffer_.clear();
|
2018-02-08 01:24:02 +01:00
|
|
|
}
|
2018-02-15 19:42:36 +01:00
|
|
|
|
2018-02-27 23:02:10 +01:00
|
|
|
static void DumpRange(std::ostream &o, const ProvenanceRange &r) {
|
|
|
|
o << "[" << r.start().offset() << ".." << r.Last().offset() << "] ("
|
|
|
|
<< r.size() << " bytes)";
|
2018-02-15 19:42:36 +01:00
|
|
|
}
|
|
|
|
|
2018-06-22 23:51:15 +02:00
|
|
|
std::ostream &OffsetToProvenanceMappings::Dump(std::ostream &o) const {
|
2018-02-15 19:42:36 +01:00
|
|
|
for (const ContiguousProvenanceMapping &m : provenanceMap_) {
|
2018-03-20 18:59:07 +01:00
|
|
|
std::size_t n{m.range.size()};
|
2018-02-15 19:42:36 +01:00
|
|
|
o << "offsets [" << m.start << ".." << (m.start + n - 1)
|
|
|
|
<< "] -> provenances ";
|
2018-02-27 23:02:10 +01:00
|
|
|
DumpRange(o, m.range);
|
2018-02-15 19:42:36 +01:00
|
|
|
o << '\n';
|
|
|
|
}
|
2018-06-22 23:51:15 +02:00
|
|
|
return o;
|
2018-02-15 19:42:36 +01:00
|
|
|
}
|
|
|
|
|
2018-06-22 23:51:15 +02:00
|
|
|
std::ostream &AllSources::Dump(std::ostream &o) const {
|
2018-02-15 19:42:36 +01:00
|
|
|
o << "AllSources range_ ";
|
2018-02-27 23:02:10 +01:00
|
|
|
DumpRange(o, range_);
|
2018-02-15 19:42:36 +01:00
|
|
|
o << '\n';
|
|
|
|
for (const Origin &m : origin_) {
|
|
|
|
o << " ";
|
2018-02-27 23:02:10 +01:00
|
|
|
DumpRange(o, m.covers);
|
2018-02-15 19:42:36 +01:00
|
|
|
o << " -> ";
|
2018-06-18 20:03:43 +02:00
|
|
|
std::visit(common::visitors{[&](const Inclusion &inc) {
|
|
|
|
if (inc.isModule) {
|
|
|
|
o << "module ";
|
|
|
|
}
|
|
|
|
o << "file " << inc.source.path();
|
|
|
|
},
|
2018-02-15 19:42:36 +01:00
|
|
|
[&](const Macro &mac) { o << "macro " << mac.expansion; },
|
|
|
|
[&](const CompilerInsertion &ins) {
|
2018-03-01 01:56:10 +01:00
|
|
|
o << "compiler '" << ins.text << '\'';
|
|
|
|
if (ins.text.length() == 1) {
|
|
|
|
int ch = ins.text[0];
|
|
|
|
o << " (0x" << std::hex << (ch & 0xff) << std::dec
|
|
|
|
<< ")";
|
|
|
|
}
|
2018-02-15 19:42:36 +01:00
|
|
|
}},
|
|
|
|
m.u);
|
2018-05-02 21:07:49 +02:00
|
|
|
if (IsValid(m.replaces)) {
|
|
|
|
o << " replaces ";
|
|
|
|
DumpRange(o, m.replaces);
|
|
|
|
}
|
2018-02-15 19:42:36 +01:00
|
|
|
o << '\n';
|
|
|
|
}
|
2018-06-22 23:51:15 +02:00
|
|
|
return o;
|
2018-02-15 19:42:36 +01:00
|
|
|
}
|
|
|
|
|
2018-06-22 23:51:15 +02:00
|
|
|
std::ostream &CookedSource::Dump(std::ostream &o) const {
|
2018-02-15 19:42:36 +01:00
|
|
|
o << "CookedSource:\n";
|
2018-03-23 23:14:52 +01:00
|
|
|
allSources_.Dump(o);
|
2018-02-15 19:42:36 +01:00
|
|
|
o << "CookedSource::provenanceMap_:\n";
|
|
|
|
provenanceMap_.Dump(o);
|
2018-06-22 23:51:15 +02:00
|
|
|
return o;
|
2018-02-15 19:42:36 +01:00
|
|
|
}
|
2018-05-02 22:48:12 +02:00
|
|
|
|
|
|
|
} // namespace Fortran::parser
|