mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 19:44:38 +08:00
[flang] Make messages more like clang's.
Original-commit: flang-compiler/f18@176cdf8e6c Reviewed-on: https://github.com/flang-compiler/f18/pull/81 Tree-same-pre-rewrite: false
This commit is contained in:
@@ -22,13 +22,13 @@ namespace Fortran::parser {
|
||||
std::optional<Success> DebugParser::Parse(ParseState &state) const {
|
||||
if (auto ustate = state.userState()) {
|
||||
if (auto out = ustate->debugOutput()) {
|
||||
const CookedSource &cooked{ustate->cooked()};
|
||||
if (auto context = state.context()) {
|
||||
context->Emit(*out, cooked);
|
||||
std::string note{str_, length_};
|
||||
Message message{state.GetLocation(),
|
||||
MessageFormattedText{"parser debug: %s"_en_US, note.data()}};
|
||||
if (Message * context{state.context().get()}) {
|
||||
message.set_context(context);
|
||||
}
|
||||
Provenance p{cooked.GetProvenance(state.GetLocation()).start()};
|
||||
cooked.allSources().Identify(*out, p, "", true);
|
||||
*out << " parser debug: " << std::string{str_, length_} << "\n\n";
|
||||
message.Emit(*out, ustate->cooked(), true);
|
||||
}
|
||||
}
|
||||
return {Success{}};
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
|
||||
#include "message.h"
|
||||
#include "char-set.h"
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Fortran::parser {
|
||||
|
||||
@@ -112,20 +114,21 @@ ProvenanceRange Message::GetProvenance(const CookedSource &cooked) const {
|
||||
void Message::Emit(
|
||||
std::ostream &o, const CookedSource &cooked, bool echoSourceLine) const {
|
||||
ProvenanceRange provenanceRange{GetProvenance(cooked)};
|
||||
bool doIdentify{true};
|
||||
if (context_) {
|
||||
bool sameProvenance{provenanceRange == context_->GetProvenance(cooked)};
|
||||
context_->Emit(o, cooked, echoSourceLine && sameProvenance);
|
||||
doIdentify = !sameProvenance;
|
||||
}
|
||||
if (doIdentify) {
|
||||
cooked.allSources().Identify(o, provenanceRange, "", echoSourceLine);
|
||||
}
|
||||
o << " ";
|
||||
std::string text;
|
||||
if (isFatal_) {
|
||||
o << "ERROR: ";
|
||||
text += "ERROR: ";
|
||||
}
|
||||
text += ToString();
|
||||
cooked.allSources().EmitMessage(o, provenanceRange, text, echoSourceLine);
|
||||
for (const Message *context{context_.get()}; context != nullptr;
|
||||
context = context->context_.get()) {
|
||||
ProvenanceRange contextProvenance{context->GetProvenance(cooked)};
|
||||
text = "in the context: ";
|
||||
text += context->ToString();
|
||||
cooked.allSources().EmitMessage(o, contextProvenance, text,
|
||||
echoSourceLine && contextProvenance != provenanceRange);
|
||||
provenanceRange = contextProvenance;
|
||||
}
|
||||
o << ToString() << '\n';
|
||||
}
|
||||
|
||||
void Messages::Incorporate(Messages &that) {
|
||||
@@ -143,16 +146,16 @@ void Messages::Copy(const Messages &that) {
|
||||
}
|
||||
}
|
||||
|
||||
void Messages::Emit(std::ostream &o, const CookedSource &cooked,
|
||||
const char *prefix, bool echoSourceLines) const {
|
||||
void Messages::Emit(
|
||||
std::ostream &o, const CookedSource &cooked, bool echoSourceLines) const {
|
||||
std::vector<const Message *> sorted;
|
||||
for (const auto &msg : messages_) {
|
||||
if (prefix) {
|
||||
o << prefix;
|
||||
}
|
||||
if (msg.context()) {
|
||||
o << "In the context ";
|
||||
}
|
||||
msg.Emit(o, cooked, echoSourceLines);
|
||||
sorted.push_back(&msg);
|
||||
}
|
||||
std::sort(sorted.begin(), sorted.end(),
|
||||
[](const Message *x, const Message *y) { return *x < *y; });
|
||||
for (const Message *msg : sorted) {
|
||||
msg->Emit(o, cooked, echoSourceLines);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,9 +207,8 @@ public:
|
||||
|
||||
void Incorporate(Messages &);
|
||||
void Copy(const Messages &);
|
||||
|
||||
void Emit(std::ostream &, const CookedSource &cooked,
|
||||
const char *prefix = nullptr, bool echoSourceLines = true) const;
|
||||
bool echoSourceLines = true) const;
|
||||
|
||||
bool AnyFatalError() const;
|
||||
|
||||
|
||||
@@ -122,8 +122,7 @@ bool Parsing::ForTesting(std::string path, std::ostream &err) {
|
||||
Parse();
|
||||
messages_.Emit(err, cooked_);
|
||||
if (!consumedWholeFile_) {
|
||||
err << "f18 parser FAIL; final position: ";
|
||||
Identify(err, finalRestingPlace_, " ");
|
||||
EmitMessage(err, finalRestingPlace_, "parser FAIL; final position");
|
||||
return false;
|
||||
}
|
||||
if (messages_.AnyFatalError() || !parseTree_.has_value()) {
|
||||
|
||||
@@ -61,10 +61,10 @@ public:
|
||||
void Parse(std::ostream *debugOutput = nullptr);
|
||||
void ClearLog();
|
||||
|
||||
void Identify(std::ostream &o, const char *at, const std::string &prefix,
|
||||
void EmitMessage(std::ostream &o, const char *at, const std::string &message,
|
||||
bool echoSourceLine = false) const {
|
||||
allSources_.Identify(
|
||||
o, cooked_.GetProvenance(at).start(), prefix, echoSourceLine);
|
||||
allSources_.EmitMessage(
|
||||
o, cooked_.GetProvenance(at).start(), message, echoSourceLine);
|
||||
}
|
||||
|
||||
bool ForTesting(std::string path, std::ostream &);
|
||||
|
||||
@@ -75,7 +75,7 @@ void OffsetToProvenanceMappings::RemoveLastBytes(std::size_t bytes) {
|
||||
}
|
||||
|
||||
AllSources::AllSources() : range_{1, 1} {
|
||||
// Start the origin_ array with a dummy that has a forced provenance,
|
||||
// Start the origin_ array with a dummy entry that has a forced provenance,
|
||||
// so that provenance offset 0 remains reserved as an uninitialized
|
||||
// value.
|
||||
origin_.emplace_back(range_, std::string{'?'});
|
||||
@@ -141,25 +141,26 @@ ProvenanceRange AllSources::AddCompilerInsertion(std::string text) {
|
||||
return covers;
|
||||
}
|
||||
|
||||
void AllSources::Identify(std::ostream &o, ProvenanceRange range,
|
||||
const std::string &prefix, bool echoSourceLine) const {
|
||||
void AllSources::EmitMessage(std::ostream &o, ProvenanceRange range,
|
||||
const std::string &message, bool echoSourceLine) const {
|
||||
CHECK(IsValid(range));
|
||||
static const std::string indented{prefix + " "};
|
||||
const Origin &origin{MapToOrigin(range.start())};
|
||||
std::visit(
|
||||
visitors{
|
||||
[&](const Inclusion &inc) {
|
||||
o << inc.source.path();
|
||||
std::size_t offset{origin.covers.MemberOffset(range.start())};
|
||||
std::pair<int, int> pos{inc.source.FindOffsetLineAndColumn(offset)};
|
||||
o << prefix << "at line " << pos.first << ", column " << pos.second;
|
||||
o << ':' << pos.first << ':' << pos.second;
|
||||
o << ": " << message << '\n';
|
||||
if (echoSourceLine) {
|
||||
o << ":\n" << indented << " ";
|
||||
const char *text{inc.source.content() +
|
||||
inc.source.GetLineStartOffset(pos.first)};
|
||||
o << " ";
|
||||
for (const char *p{text}; *p != '\n'; ++p) {
|
||||
o << *p;
|
||||
}
|
||||
o << '\n' << indented << " ";
|
||||
o << "\n ";
|
||||
for (int j{1}; j < pos.second; ++j) {
|
||||
char ch{text[j - 1]};
|
||||
o << (ch == '\t' ? '\t' : ' ');
|
||||
@@ -177,28 +178,20 @@ void AllSources::Identify(std::ostream &o, ProvenanceRange range,
|
||||
}
|
||||
}
|
||||
}
|
||||
o << '\n' << prefix;
|
||||
} else {
|
||||
o << ' ';
|
||||
}
|
||||
o << "in the " << (inc.isModule ? "module " : "file ")
|
||||
<< inc.source.path();
|
||||
if (IsValid(origin.replaces)) {
|
||||
o << (inc.isModule ? " used\n" : " included\n");
|
||||
Identify(o, origin.replaces.start(), indented);
|
||||
} else {
|
||||
o << '\n';
|
||||
}
|
||||
if (IsValid(origin.replaces)) {
|
||||
EmitMessage(o, origin.replaces,
|
||||
inc.isModule ? "used here"s : "included here"s,
|
||||
echoSourceLine);
|
||||
}
|
||||
},
|
||||
[&](const Macro &mac) {
|
||||
o << prefix << "in the expansion of a macro that was defined\n";
|
||||
Identify(o, mac.definition.start(), indented, echoSourceLine);
|
||||
o << prefix << "and called\n";
|
||||
Identify(o, origin.replaces.start(), indented, echoSourceLine);
|
||||
EmitMessage(o, origin.replaces, message, echoSourceLine);
|
||||
EmitMessage(
|
||||
o, mac.definition, "in a macro defined here", echoSourceLine);
|
||||
if (echoSourceLine) {
|
||||
o << prefix << "and expanded to\n"
|
||||
<< indented << " " << mac.expansion << '\n'
|
||||
<< indented << " ";
|
||||
o << "that expanded to:\n " << mac.expansion << "\n ";
|
||||
for (std::size_t j{0};
|
||||
origin.covers.OffsetMember(j) < range.start(); ++j) {
|
||||
o << (mac.expansion[j] == '\t' ? '\t' : ' ');
|
||||
@@ -206,9 +199,7 @@ void AllSources::Identify(std::ostream &o, ProvenanceRange range,
|
||||
o << "^\n";
|
||||
}
|
||||
},
|
||||
[&](const CompilerInsertion &ins) {
|
||||
o << prefix << ins.text << '\n';
|
||||
}},
|
||||
[&](const CompilerInsertion &ins) { o << message << '\n'; }},
|
||||
origin.u);
|
||||
}
|
||||
|
||||
@@ -360,6 +351,10 @@ void AllSources::Dump(std::ostream &o) const {
|
||||
}
|
||||
}},
|
||||
m.u);
|
||||
if (IsValid(m.replaces)) {
|
||||
o << " replaces ";
|
||||
DumpRange(o, m.replaces);
|
||||
}
|
||||
o << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public:
|
||||
bool IsValid(ProvenanceRange range) const {
|
||||
return range.size() > 0 && range_.Contains(range);
|
||||
}
|
||||
void Identify(std::ostream &, ProvenanceRange, const std::string &prefix,
|
||||
void EmitMessage(std::ostream &, ProvenanceRange, const std::string &message,
|
||||
bool echoSourceLine = false) const;
|
||||
const SourceFile *GetSourceFile(
|
||||
Provenance, std::size_t *offset = nullptr) const;
|
||||
|
||||
@@ -164,7 +164,7 @@ std::string CompileFortran(
|
||||
if (!parsing.messages().empty() &&
|
||||
(driver.warningsAreErrors || parsing.messages().AnyFatalError())) {
|
||||
std::cerr << driver.prefix << "could not scan " << path << '\n';
|
||||
parsing.messages().Emit(std::cerr, parsing.cooked(), driver.prefix);
|
||||
parsing.messages().Emit(std::cerr, parsing.cooked());
|
||||
exitStatus = EXIT_FAILURE;
|
||||
return {};
|
||||
}
|
||||
@@ -182,10 +182,10 @@ std::string CompileFortran(
|
||||
return {};
|
||||
}
|
||||
parsing.ClearLog();
|
||||
parsing.messages().Emit(std::cerr, parsing.cooked(), driver.prefix);
|
||||
parsing.messages().Emit(std::cerr, parsing.cooked());
|
||||
if (!parsing.consumedWholeFile()) {
|
||||
std::cerr << "f18 parser FAIL; final position: ";
|
||||
parsing.Identify(std::cerr, parsing.finalRestingPlace(), " ");
|
||||
parsing.EmitMessage(std::cerr, parsing.finalRestingPlace(),
|
||||
"parser FAIL (final position)");
|
||||
exitStatus = EXIT_FAILURE;
|
||||
return {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user