mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 08:02:08 +00:00
[flang] Add nonfatal message classes
F18 presently has fatal and non-fatal diagnostic messages. We'd like to make non-fatal warnings stand out better in the output of the compiler. This will turn out to be a large change that affects many files. This patch is just the first part. It converts a Boolean isFatal_ data member of the message classes into a severity code, and defines four of these codes (Error, Warning, Portability, and a catch-all Other). Later patches will result from sweeping over the parser and semantics, changing most non-fatal diagnostic messages into warnings and portability notes. Differential Revision: https://reviews.llvm.org/D121228
This commit is contained in:
parent
1712254b3f
commit
2895771faf
@ -133,10 +133,20 @@ indicators within the parser and in the parse tree.
|
||||
|
||||
Message texts, and snprintf-like formatting strings for constructing
|
||||
messages, are instantiated in the various components of the parser with
|
||||
C++ user defined character literals tagged with `_err_en_US` and `_en_US`
|
||||
(signifying fatality and language, with the default being the dialect of
|
||||
English used in the United States) so that they may be easily identified
|
||||
for localization. As described above, messages are associated with
|
||||
C++ user defined character literals tagged with `_err_en_US`, `_warn_en_US`,
|
||||
`port_en_US`, and `_en_US` to signify severity and language; the default
|
||||
language is the dialect of English used in the United States.
|
||||
|
||||
All "fatal" errors that do not immediately abort compilation but do
|
||||
prevent the generation of binary and module files are `_err_en_US`.
|
||||
Warnings about detected flaws in the program that probably indicate
|
||||
problems worth attention are `_warn_en_US`.
|
||||
Non-conforming extensions, legacy features, and obsolescent or deleted
|
||||
features will raise `_port_en_US` messages when those are enabled.
|
||||
Other messages have a simple `_en_US` suffix, including all messages
|
||||
that are explanatory attachments.
|
||||
|
||||
As described above, messages are associated with
|
||||
source code positions by means of provenance values.
|
||||
|
||||
## The Parse Tree
|
||||
|
@ -29,34 +29,45 @@
|
||||
|
||||
namespace Fortran::parser {
|
||||
|
||||
// Use "..."_err_en_US and "..."_en_US literals to define the static
|
||||
// text and fatality of a message.
|
||||
// Use "..."_err_en_US, "..."_warn_en_US, and "..."_en_US literals to define
|
||||
// the static text and fatality of a message.
|
||||
enum class Severity { Error, Warning, Portability, None };
|
||||
|
||||
class MessageFixedText {
|
||||
public:
|
||||
constexpr MessageFixedText() {}
|
||||
constexpr MessageFixedText(
|
||||
const char str[], std::size_t n, bool isFatal = false)
|
||||
: text_{str, n}, isFatal_{isFatal} {}
|
||||
const char str[], std::size_t n, Severity severity = Severity::None)
|
||||
: text_{str, n}, severity_{severity} {}
|
||||
constexpr MessageFixedText(const MessageFixedText &) = default;
|
||||
constexpr MessageFixedText(MessageFixedText &&) = default;
|
||||
constexpr MessageFixedText &operator=(const MessageFixedText &) = default;
|
||||
constexpr MessageFixedText &operator=(MessageFixedText &&) = default;
|
||||
|
||||
CharBlock text() const { return text_; }
|
||||
bool isFatal() const { return isFatal_; }
|
||||
Severity severity() const { return severity_; }
|
||||
bool isFatal() const { return severity_ == Severity::Error; }
|
||||
|
||||
private:
|
||||
CharBlock text_;
|
||||
bool isFatal_{false};
|
||||
Severity severity_{Severity::None};
|
||||
};
|
||||
|
||||
inline namespace literals {
|
||||
constexpr MessageFixedText operator""_en_US(const char str[], std::size_t n) {
|
||||
return MessageFixedText{str, n, false /* not fatal */};
|
||||
}
|
||||
|
||||
constexpr MessageFixedText operator""_err_en_US(
|
||||
const char str[], std::size_t n) {
|
||||
return MessageFixedText{str, n, true /* fatal */};
|
||||
return MessageFixedText{str, n, Severity::Error};
|
||||
}
|
||||
constexpr MessageFixedText operator""_warn_en_US(
|
||||
const char str[], std::size_t n) {
|
||||
return MessageFixedText{str, n, Severity::Warning};
|
||||
}
|
||||
constexpr MessageFixedText operator""_port_en_US(
|
||||
const char str[], std::size_t n) {
|
||||
return MessageFixedText{str, n, Severity::Portability};
|
||||
}
|
||||
constexpr MessageFixedText operator""_en_US(const char str[], std::size_t n) {
|
||||
return MessageFixedText{str, n, Severity::None};
|
||||
}
|
||||
} // namespace literals
|
||||
|
||||
@ -69,7 +80,7 @@ class MessageFormattedText {
|
||||
public:
|
||||
template <typename... A>
|
||||
MessageFormattedText(const MessageFixedText &text, A &&...x)
|
||||
: isFatal_{text.isFatal()} {
|
||||
: severity_{text.severity()} {
|
||||
Format(&text, Convert(std::forward<A>(x))...);
|
||||
}
|
||||
MessageFormattedText(const MessageFormattedText &) = default;
|
||||
@ -77,7 +88,8 @@ public:
|
||||
MessageFormattedText &operator=(const MessageFormattedText &) = default;
|
||||
MessageFormattedText &operator=(MessageFormattedText &&) = default;
|
||||
const std::string &string() const { return string_; }
|
||||
bool isFatal() const { return isFatal_; }
|
||||
bool isFatal() const { return severity_ == Severity::Error; }
|
||||
Severity severity() const { return severity_; }
|
||||
std::string MoveString() { return std::move(string_); }
|
||||
|
||||
private:
|
||||
@ -104,7 +116,7 @@ private:
|
||||
std::intmax_t Convert(std::int64_t x) { return x; }
|
||||
std::uintmax_t Convert(std::uint64_t x) { return x; }
|
||||
|
||||
bool isFatal_{false};
|
||||
Severity severity_;
|
||||
std::string string_;
|
||||
std::forward_list<std::string> conversions_; // preserves created strings
|
||||
};
|
||||
@ -186,6 +198,7 @@ public:
|
||||
|
||||
bool SortBefore(const Message &that) const;
|
||||
bool IsFatal() const;
|
||||
Severity severity() const;
|
||||
std::string ToString() const;
|
||||
std::optional<ProvenanceRange> GetProvenanceRange(
|
||||
const AllCookedSources &) const;
|
||||
|
@ -155,12 +155,14 @@ bool Message::SortBefore(const Message &that) const {
|
||||
location_, that.location_);
|
||||
}
|
||||
|
||||
bool Message::IsFatal() const {
|
||||
bool Message::IsFatal() const { return severity() == Severity::Error; }
|
||||
|
||||
Severity Message::severity() const {
|
||||
return std::visit(
|
||||
common::visitors{
|
||||
[](const MessageExpectedText &) { return true; },
|
||||
[](const MessageFixedText &x) { return x.isFatal(); },
|
||||
[](const MessageFormattedText &x) { return x.isFatal(); },
|
||||
[](const MessageExpectedText &) { return Severity::Error; },
|
||||
[](const MessageFixedText &x) { return x.severity(); },
|
||||
[](const MessageFormattedText &x) { return x.severity(); },
|
||||
},
|
||||
text_);
|
||||
}
|
||||
@ -203,8 +205,18 @@ void Message::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
|
||||
bool echoSourceLine) const {
|
||||
std::optional<ProvenanceRange> provenanceRange{GetProvenanceRange(allCooked)};
|
||||
std::string text;
|
||||
if (IsFatal()) {
|
||||
text += "error: ";
|
||||
switch (severity()) {
|
||||
case Severity::Error:
|
||||
text = "error: ";
|
||||
break;
|
||||
case Severity::Warning:
|
||||
text = "warning: ";
|
||||
break;
|
||||
case Severity::Portability:
|
||||
text = "portability: ";
|
||||
break;
|
||||
case Severity::None:
|
||||
break;
|
||||
}
|
||||
text += ToString();
|
||||
const AllSources &sources{allCooked.allSources()};
|
||||
|
@ -38,7 +38,8 @@ bool FormatErrorReporter::Say(const common::FormatMessage &msg) {
|
||||
return false;
|
||||
}
|
||||
parser::MessageFormattedText text{
|
||||
parser::MessageFixedText(msg.text, strlen(msg.text), msg.isError),
|
||||
parser::MessageFixedText{msg.text, strlen(msg.text),
|
||||
msg.isError ? parser::Severity::Error : parser::Severity::Warning},
|
||||
msg.arg};
|
||||
if (formatCharBlock_.size()) {
|
||||
// The input format is a folded expression. Error markers span the full
|
||||
|
@ -946,7 +946,8 @@ Scope *ModFileReader::Read(const SourceName &name,
|
||||
for (auto &msg : parsing.messages().messages()) {
|
||||
std::string str{msg.ToString()};
|
||||
Say(name, ancestorName,
|
||||
parser::MessageFixedText{str.c_str(), str.size()}, path);
|
||||
parser::MessageFixedText{str.c_str(), str.size(), msg.severity()},
|
||||
path);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -44,10 +44,10 @@ Symbol &Resolve(const parser::Name &name, Symbol &symbol) {
|
||||
return *Resolve(name, &symbol);
|
||||
}
|
||||
|
||||
parser::MessageFixedText WithIsFatal(
|
||||
const parser::MessageFixedText &msg, bool isFatal) {
|
||||
parser::MessageFixedText WithSeverity(
|
||||
const parser::MessageFixedText &msg, parser::Severity severity) {
|
||||
return parser::MessageFixedText{
|
||||
msg.text().begin(), msg.text().size(), isFatal};
|
||||
msg.text().begin(), msg.text().size(), severity};
|
||||
}
|
||||
|
||||
bool IsIntrinsicOperator(
|
||||
@ -576,7 +576,7 @@ bool EquivalenceSets::CheckObject(const parser::Name &name) {
|
||||
return false; // an error has already occurred
|
||||
}
|
||||
currObject_.symbol = name.symbol;
|
||||
parser::MessageFixedText msg{"", 0};
|
||||
parser::MessageFixedText msg;
|
||||
const Symbol &symbol{*name.symbol};
|
||||
if (symbol.owner().IsDerivedType()) { // C8107
|
||||
msg = "Derived type component '%s'"
|
||||
|
@ -44,9 +44,9 @@ class SemanticsContext;
|
||||
Symbol &Resolve(const parser::Name &, Symbol &);
|
||||
Symbol *Resolve(const parser::Name &, Symbol *);
|
||||
|
||||
// Create a copy of msg with a new isFatal value.
|
||||
parser::MessageFixedText WithIsFatal(
|
||||
const parser::MessageFixedText &msg, bool isFatal);
|
||||
// Create a copy of msg with a new severity.
|
||||
parser::MessageFixedText WithSeverity(
|
||||
const parser::MessageFixedText &msg, parser::Severity);
|
||||
|
||||
bool IsIntrinsicOperator(const SemanticsContext &, const SourceName &);
|
||||
bool IsLogicalConstant(const SemanticsContext &, const SourceName &);
|
||||
|
@ -6654,9 +6654,9 @@ Symbol &ModuleVisitor::SetAccess(
|
||||
// PUBLIC/PRIVATE already set: make it a fatal error if it changed
|
||||
Attr prev = attrs.test(Attr::PUBLIC) ? Attr::PUBLIC : Attr::PRIVATE;
|
||||
Say(name,
|
||||
WithIsFatal(
|
||||
WithSeverity(
|
||||
"The accessibility of '%s' has already been specified as %s"_en_US,
|
||||
attr != prev),
|
||||
attr != prev ? parser::Severity::Error : parser::Severity::Warning),
|
||||
MakeOpName(name), EnumToString(prev));
|
||||
} else {
|
||||
attrs.set(attr);
|
||||
|
Loading…
Reference in New Issue
Block a user