forked from OSchip/llvm-project
[flang] Replace formatting of CharBlock & string
Preserve generated strings until consumed by formatting. bugfix from premature push Address review comments Last fix(?) Use %s formatting for CharBlocks and strings Use new formatting and fix usage of std::forward<>() Use forward_list rather than vector to save strings Original-commit: flang-compiler/f18@8ea478420f Reviewed-on: https://github.com/flang-compiler/f18/pull/444 Tree-same-pre-rewrite: false
This commit is contained in:
parent
7334b71023
commit
ec6cf76536
|
@ -36,7 +36,7 @@ bool TypeAndShape::IsCompatibleWith(
|
|||
parser::ContextualMessages &messages, const TypeAndShape &that) const {
|
||||
if (!type_.IsTypeCompatibleWith(that.type_)) {
|
||||
messages.Say("Target type '%s' is not compatible with '%s'"_err_en_US,
|
||||
that.type_.AsFortran().c_str(), type_.AsFortran().c_str());
|
||||
that.type_.AsFortran(), type_.AsFortran());
|
||||
return false;
|
||||
}
|
||||
return CheckConformance(messages, shape_, that.shape_);
|
||||
|
|
|
@ -589,8 +589,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldOperation(FoldingContext &context,
|
|||
context, std::move(funcRef), *callable);
|
||||
} else {
|
||||
context.messages().Say(
|
||||
"%s(real(kind=%d)) cannot be folded on host"_en_US, name.c_str(),
|
||||
KIND);
|
||||
"%s(real(kind=%d)) cannot be folded on host"_en_US, name, KIND);
|
||||
}
|
||||
}
|
||||
if (name == "atan" || name == "atan2" || name == "hypot" || name == "mod") {
|
||||
|
@ -604,7 +603,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldOperation(FoldingContext &context,
|
|||
} else {
|
||||
context.messages().Say(
|
||||
"%s(real(kind=%d), real(kind%d)) cannot be folded on host"_en_US,
|
||||
name.c_str(), KIND, KIND);
|
||||
name, KIND, KIND);
|
||||
}
|
||||
} else if (name == "bessel_jn" || name == "bessel_yn") {
|
||||
if (args.size() == 2) { // elemental
|
||||
|
@ -624,7 +623,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldOperation(FoldingContext &context,
|
|||
} else {
|
||||
context.messages().Say(
|
||||
"%s(integer(kind=4), real(kind=%d)) cannot be folded on host"_en_US,
|
||||
name.c_str(), KIND);
|
||||
name, KIND);
|
||||
}
|
||||
}
|
||||
} else if (name == "abs") {
|
||||
|
@ -661,7 +660,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldOperation(FoldingContext &context,
|
|||
ValueWithRealFlags<Scalar<T>> y{x.AINT()};
|
||||
if (y.flags.test(RealFlag::Overflow)) {
|
||||
context.messages().Say(
|
||||
"%s intrinsic folding overflow"_en_US, name.c_str());
|
||||
"%s intrinsic folding overflow"_en_US, name);
|
||||
}
|
||||
return y.value;
|
||||
}));
|
||||
|
@ -714,8 +713,7 @@ Expr<Type<TypeCategory::Complex, KIND>> FoldOperation(FoldingContext &context,
|
|||
context, std::move(funcRef), *callable);
|
||||
} else {
|
||||
context.messages().Say(
|
||||
"%s(complex(kind=%d)) cannot be folded on host"_en_US, name.c_str(),
|
||||
KIND);
|
||||
"%s(complex(kind=%d)) cannot be folded on host"_en_US, name, KIND);
|
||||
}
|
||||
} else if (name == "conjg") {
|
||||
return FoldElementalIntrinsic<T, T>(
|
||||
|
|
|
@ -908,7 +908,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
|
|||
return std::nullopt;
|
||||
} else if (!d.typePattern.categorySet.test(type->category)) {
|
||||
messages.Say("Actual argument for '%s=' has bad type '%s'"_err_en_US,
|
||||
d.keyword, type->AsFortran().data());
|
||||
d.keyword, type->AsFortran());
|
||||
return std::nullopt; // argument has invalid type category
|
||||
}
|
||||
bool argOk{false};
|
||||
|
@ -961,7 +961,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
|
|||
if (!argOk) {
|
||||
messages.Say(
|
||||
"actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
|
||||
d.keyword, type->AsFortran().data());
|
||||
d.keyword, type->AsFortran());
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
@ -1315,7 +1315,7 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
|
|||
} else if (arguments[0].has_value() && arguments[0]->keyword.has_value() &&
|
||||
arguments[0]->keyword->ToString() != "mold") {
|
||||
context.messages().Say("Unknown argument '%s' to NULL()"_err_en_US,
|
||||
arguments[0]->keyword->ToString().data());
|
||||
arguments[0]->keyword->ToString());
|
||||
} else {
|
||||
if (Expr<SomeType> * mold{arguments[0]->GetExpr()}) {
|
||||
if (IsAllocatableOrPointer(*mold)) {
|
||||
|
|
|
@ -23,7 +23,7 @@ std::optional<Success> DebugParser::Parse(ParseState &state) const {
|
|||
if (auto ustate{state.userState()}) {
|
||||
if (auto out{ustate->debugOutput()}) {
|
||||
std::string note{str_, length_};
|
||||
Message message{state.GetLocation(), "parser debug: %S"_en_US, note};
|
||||
Message message{state.GetLocation(), "parser debug: %s"_en_US, note};
|
||||
message.SetContext(state.context().get());
|
||||
message.Emit(*out, ustate->cooked(), true);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "message.h"
|
||||
#include "char-set.h"
|
||||
#include "parse-tree.h"
|
||||
#include "../common/idioms.h"
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
|
@ -33,95 +34,62 @@ std::ostream &operator<<(std::ostream &o, const MessageFixedText &t) {
|
|||
return o;
|
||||
}
|
||||
|
||||
static bool NeedsSpecialFormatting(const char *p) {
|
||||
bool result{false};
|
||||
bool tooLate{false};
|
||||
while (*p != '\0') {
|
||||
if (*p++ == '%') {
|
||||
if (*p == 'S' || *p == 'B') {
|
||||
CHECK(!tooLate);
|
||||
result = true;
|
||||
} else if (*p != '%' && *p != 's' && *p != 'd' &&
|
||||
!((*p == 'z' || *p == 'j') && (p[1] == 'd' || p[1] == 'u'))) {
|
||||
tooLate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Some standard formatting codes (e.g., %d) are handled here
|
||||
// rather than in vsnprintf() because once we have to call vsnprintf(),
|
||||
// we're no longer able to process our special codes like %S and %B,
|
||||
// and it's possible that a format might use a common standard formatting
|
||||
// code before one of our special codes.
|
||||
static std::string SpecialFormatting(const char *p, va_list &ap) {
|
||||
std::string result;
|
||||
while (*p != '\0') {
|
||||
if (*p != '%') {
|
||||
result += *p++;
|
||||
} else {
|
||||
++p;
|
||||
switch (*p++) {
|
||||
case '%': result += '%'; break;
|
||||
case 's': result += va_arg(ap, const char *); break;
|
||||
case 'd': result += std::to_string(va_arg(ap, int)); break;
|
||||
case 'S': result += va_arg(ap, std::string); break;
|
||||
case 'B': result += va_arg(ap, CharBlock).ToString(); break;
|
||||
default:
|
||||
if (p[-1] == 'z' && (*p == 'u' || *p == 'd')) {
|
||||
result += std::to_string(va_arg(ap, std::size_t));
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
if (p[-1] == 'j') {
|
||||
if (*p == 'd') {
|
||||
result += std::to_string(va_arg(ap, std::intmax_t));
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
if (*p == 'u') {
|
||||
result += std::to_string(va_arg(ap, std::uintmax_t));
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
char buffer[256];
|
||||
vsnprintf(buffer, sizeof buffer, p - 2, ap);
|
||||
result += buffer;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MessageFormattedText::MessageFormattedText(MessageFixedText text, ...)
|
||||
: isFatal_{text.isFatal()} {
|
||||
const char *p{text.text().begin()};
|
||||
void MessageFormattedText::Format(const MessageFixedText *text, ...) {
|
||||
const char *p{text->text().begin()};
|
||||
std::string asString;
|
||||
if (*text.text().end() != '\0') {
|
||||
if (*text->text().end() != '\0') {
|
||||
// not NUL-terminated
|
||||
asString = text.text().NULTerminatedToString();
|
||||
asString = text->text().NULTerminatedToString();
|
||||
p = asString.c_str();
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, text);
|
||||
if (NeedsSpecialFormatting(p)) {
|
||||
string_ = SpecialFormatting(p, ap);
|
||||
} else {
|
||||
char buffer[256];
|
||||
vsnprintf(buffer, sizeof buffer, p, ap);
|
||||
string_ = buffer;
|
||||
}
|
||||
int need{vsnprintf(nullptr, 0, p, ap)};
|
||||
CHECK(need >= 0);
|
||||
char *buffer{
|
||||
static_cast<char *>(std::malloc(static_cast<std::size_t>(need) + 1))};
|
||||
CHECK(buffer != nullptr);
|
||||
va_end(ap);
|
||||
va_start(ap, text);
|
||||
int need2{vsnprintf(buffer, need + 1, p, ap)};
|
||||
CHECK(need2 == need);
|
||||
va_end(ap);
|
||||
string_ = buffer;
|
||||
std::free(buffer);
|
||||
conversions_.clear();
|
||||
}
|
||||
|
||||
const char *MessageFormattedText::Convert(const std::string &s) {
|
||||
conversions_.emplace_front(s);
|
||||
return conversions_.front().c_str();
|
||||
}
|
||||
|
||||
const char *MessageFormattedText::Convert(std::string &&s) {
|
||||
conversions_.emplace_front(std::move(s));
|
||||
return conversions_.front().c_str();
|
||||
}
|
||||
|
||||
const char *MessageFormattedText::Convert(const CharBlock &x) {
|
||||
return Convert(x.ToString());
|
||||
}
|
||||
|
||||
const char *MessageFormattedText::Convert(CharBlock &&x) {
|
||||
return Convert(x.ToString());
|
||||
}
|
||||
|
||||
const char *MessageFormattedText::Convert(const Name &n) {
|
||||
return Convert(n.source);
|
||||
}
|
||||
|
||||
const char *MessageFormattedText::Convert(Name &&n) {
|
||||
return Convert(n.source);
|
||||
}
|
||||
|
||||
std::string MessageExpectedText::ToString() const {
|
||||
return std::visit(
|
||||
common::visitors{
|
||||
[](const CharBlock &cb) {
|
||||
return MessageFormattedText("expected '%B'"_err_en_US, cb)
|
||||
return MessageFormattedText("expected '%s'"_err_en_US, cb)
|
||||
.MoveString();
|
||||
},
|
||||
[](const SetOfChars &set) {
|
||||
|
@ -134,21 +102,21 @@ std::string MessageExpectedText::ToString() const {
|
|||
std::string s{expect.ToString()};
|
||||
if (s.size() == 1) {
|
||||
return MessageFormattedText(
|
||||
"expected end of line or '%S'"_err_en_US, s)
|
||||
"expected end of line or '%s'"_err_en_US, s)
|
||||
.MoveString();
|
||||
} else {
|
||||
return MessageFormattedText(
|
||||
"expected end of line or one of '%S'"_err_en_US, s)
|
||||
"expected end of line or one of '%s'"_err_en_US, s)
|
||||
.MoveString();
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string s{expect.ToString()};
|
||||
if (s.size() != 1) {
|
||||
return MessageFormattedText("expected one of '%S'"_err_en_US, s)
|
||||
return MessageFormattedText("expected one of '%s'"_err_en_US, s)
|
||||
.MoveString();
|
||||
} else {
|
||||
return MessageFormattedText("expected '%S'"_err_en_US, s)
|
||||
return MessageFormattedText("expected '%s'"_err_en_US, s)
|
||||
.MoveString();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
namespace Fortran::parser {
|
||||
|
||||
struct Name;
|
||||
|
||||
// Use "..."_err_en_US and "..."_en_US literals to define the static
|
||||
// text and fatality of a message.
|
||||
class MessageFixedText {
|
||||
|
@ -67,14 +69,17 @@ constexpr MessageFixedText operator""_err_en_US(
|
|||
}
|
||||
|
||||
// The construction of a MessageFormattedText uses a MessageFixedText
|
||||
// as a vsnprintf()-like formatting string that is applied to the
|
||||
// following arguments. Additional formatting codes are accepted in
|
||||
// messages:
|
||||
// %B - the corresponding argument is a CharBlock
|
||||
// %S - the corresponding argument is a std::string
|
||||
// as a vsnprintf() formatting string that is applied to the
|
||||
// following arguments. CharBlock and std::string argument values are
|
||||
// also supported; they are automatically converted into char pointers
|
||||
// that are suitable for '%s' formatting.
|
||||
class MessageFormattedText {
|
||||
public:
|
||||
MessageFormattedText(MessageFixedText, ...);
|
||||
template<typename... A>
|
||||
MessageFormattedText(const MessageFixedText &text, A &&... x)
|
||||
: isFatal_{text.isFatal()} {
|
||||
Format(&text, Convert(std::forward<A>(x))...);
|
||||
}
|
||||
MessageFormattedText(const MessageFormattedText &) = default;
|
||||
MessageFormattedText(MessageFormattedText &&) = default;
|
||||
MessageFormattedText &operator=(const MessageFormattedText &) = default;
|
||||
|
@ -84,8 +89,21 @@ public:
|
|||
std::string MoveString() { return std::move(string_); }
|
||||
|
||||
private:
|
||||
std::string string_;
|
||||
void Format(const MessageFixedText *text, ...);
|
||||
template<typename A> A Convert(const A &x) { return x; }
|
||||
template<typename A> common::IfNoLvalue<A, A> Convert(A &&x) {
|
||||
return std::move(x);
|
||||
}
|
||||
const char *Convert(const std::string &);
|
||||
const char *Convert(std::string &&);
|
||||
const char *Convert(const CharBlock &);
|
||||
const char *Convert(CharBlock &&);
|
||||
const char *Convert(const Name &);
|
||||
const char *Convert(Name &&);
|
||||
|
||||
bool isFatal_{false};
|
||||
std::string string_;
|
||||
std::forward_list<std::string> conversions_; // preserves created strings
|
||||
};
|
||||
|
||||
// Represents a formatted rendition of "expected '%s'"_err_en_US
|
||||
|
@ -145,9 +163,10 @@ public:
|
|||
Message(CharBlock csr, const MessageExpectedText &t)
|
||||
: location_{csr}, text_{t} {}
|
||||
|
||||
template<typename RANGE, typename A1, typename... As>
|
||||
Message(RANGE r, const MessageFixedText &t, A1 a1, As... as)
|
||||
: location_{r}, text_{MessageFormattedText{t, a1, as...}} {}
|
||||
template<typename RANGE, typename A, typename... As>
|
||||
Message(RANGE r, const MessageFixedText &t, A &&x, As &&... xs)
|
||||
: location_{r}, text_{MessageFormattedText{
|
||||
t, std::forward<A>(x), std::forward<As>(xs)...}} {}
|
||||
|
||||
bool attachmentIsContext() const { return attachmentIsContext_; }
|
||||
Reference attachment() const { return attachment_; }
|
||||
|
@ -210,7 +229,7 @@ public:
|
|||
|
||||
bool empty() const { return messages_.empty(); }
|
||||
|
||||
template<typename... A> Message &Say(A... args) {
|
||||
template<typename... A> Message &Say(A &&... args) {
|
||||
last_ = messages_.emplace_after(last_, std::forward<A>(args)...);
|
||||
return *last_;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ void Parsing::Prescan(const std::string &path, Options options) {
|
|||
}
|
||||
if (sourceFile == nullptr) {
|
||||
ProvenanceRange range{allSources.AddCompilerInsertion(path)};
|
||||
messages_.Say(range, "%S"_err_en_US, fileError.str());
|
||||
messages_.Say(range, "%s"_err_en_US, fileError.str());
|
||||
return;
|
||||
}
|
||||
if (sourceFile->bytes() == 0) {
|
||||
|
|
|
@ -319,8 +319,7 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement(
|
|||
}
|
||||
}
|
||||
}
|
||||
if (argStart.size() == 1 && k == argStart[0] &&
|
||||
def.argumentCount() == 0) {
|
||||
if (argStart.size() == 1 && k == argStart[0] && def.argumentCount() == 0) {
|
||||
// Subtle: () is zero arguments, not one empty argument,
|
||||
// unless one argument was expected.
|
||||
argStart.clear();
|
||||
|
@ -472,12 +471,12 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
|
|||
if (nameToken.empty()) {
|
||||
prescanner->Say(
|
||||
dir.GetIntervalProvenanceRange(dirOffset, tokens - dirOffset),
|
||||
"#%S: missing name"_err_en_US, dirName);
|
||||
"#%s: missing name"_err_en_US, dirName);
|
||||
} else {
|
||||
j = dir.SkipBlanks(j + 1);
|
||||
if (j != tokens) {
|
||||
prescanner->Say(dir.GetIntervalProvenanceRange(j, tokens - j),
|
||||
"#%S: excess tokens at end of directive"_en_US, dirName);
|
||||
"#%s: excess tokens at end of directive"_en_US, dirName);
|
||||
}
|
||||
doThen = IsNameDefined(nameToken) == (dirName == "ifdef");
|
||||
}
|
||||
|
@ -534,12 +533,12 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
|
|||
} else if (dirName == "error") {
|
||||
prescanner->Say(
|
||||
dir.GetIntervalProvenanceRange(dirOffset, tokens - dirOffset),
|
||||
"%S"_err_en_US, dir.ToString());
|
||||
"%s"_err_en_US, dir.ToString());
|
||||
} else if (dirName == "warning" || dirName == "comment" ||
|
||||
dirName == "note") {
|
||||
prescanner->Say(
|
||||
dir.GetIntervalProvenanceRange(dirOffset, tokens - dirOffset),
|
||||
"%S"_en_US, dir.ToString());
|
||||
"%s"_en_US, dir.ToString());
|
||||
} else if (dirName == "include") {
|
||||
if (j == tokens) {
|
||||
prescanner->Say(
|
||||
|
@ -585,7 +584,7 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
|
|||
const SourceFile *included{allSources_.Open(include, &error)};
|
||||
if (included == nullptr) {
|
||||
prescanner->Say(dir.GetTokenProvenanceRange(dirOffset),
|
||||
"#include: %S"_err_en_US, error.str());
|
||||
"#include: %s"_err_en_US, error.str());
|
||||
} else if (included->bytes() > 0) {
|
||||
ProvenanceRange fileRange{
|
||||
allSources_.AddIncludedFile(*included, dir.GetProvenanceRange())};
|
||||
|
@ -593,7 +592,7 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
|
|||
}
|
||||
} else {
|
||||
prescanner->Say(dir.GetTokenProvenanceRange(dirOffset),
|
||||
"#%S: unknown or unimplemented directive"_err_en_US, dirName);
|
||||
"#%s: unknown or unimplemented directive"_err_en_US, dirName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -654,7 +653,7 @@ void Preprocessor::SkipDisabledConditionalCode(const std::string &dirName,
|
|||
}
|
||||
}
|
||||
}
|
||||
prescanner->Say(provenanceRange, "#%S: missing #endif"_err_en_US, dirName);
|
||||
prescanner->Say(provenanceRange, "#%s: missing #endif"_err_en_US, dirName);
|
||||
}
|
||||
|
||||
// Precedence level codes used here to accommodate mixed Fortran and C:
|
||||
|
@ -773,7 +772,7 @@ static std::int64_t ExpressionValue(const TokenSequence &token,
|
|||
left = std::stoll(t, &consumed, 0 /*base to be detected*/);
|
||||
if (consumed < t.size()) {
|
||||
*error = Message{token.GetTokenProvenanceRange(opAt),
|
||||
"Uninterpretable numeric constant '%S'"_err_en_US, t};
|
||||
"Uninterpretable numeric constant '%s'"_err_en_US, t};
|
||||
return 0;
|
||||
}
|
||||
} else if (IsLegalIdentifierStart(t[0])) {
|
||||
|
|
|
@ -729,7 +729,7 @@ void Prescanner::FortranInclude(const char *firstQuote) {
|
|||
allSources.PopSearchPathDirectory();
|
||||
}
|
||||
if (included == nullptr) {
|
||||
Say(provenance, "INCLUDE: %S"_err_en_US, error.str());
|
||||
Say(provenance, "INCLUDE: %s"_err_en_US, error.str());
|
||||
} else if (included->bytes() > 0) {
|
||||
ProvenanceRange includeLineRange{
|
||||
provenance, static_cast<std::size_t>(p - lineStart_)};
|
||||
|
|
|
@ -38,7 +38,7 @@ void CheckPointerAssignment(parser::ContextualMessages &messages,
|
|||
// Default catch-all when RHS of pointer assignment isn't recognized
|
||||
messages.Say("Pointer target assigned to '%s' must be a designator or "
|
||||
"a call to a pointer-valued function"_err_en_US,
|
||||
symbol.name().ToString().c_str());
|
||||
symbol.name());
|
||||
}
|
||||
|
||||
void CheckPointerAssignment(parser::ContextualMessages &messages,
|
||||
|
@ -99,8 +99,7 @@ void CheckPointerAssignment(parser::ContextualMessages &messages,
|
|||
"result of reference to procedure"_err_en_US;
|
||||
}
|
||||
if (error.has_value()) {
|
||||
if (auto *msg{messages.Say(
|
||||
*error, lhs.name().ToString().c_str(), funcName.c_str())}) {
|
||||
if (auto *msg{messages.Say(*error, lhs.name(), funcName)}) {
|
||||
msg->Attach(lhs.name(), "Declaration of pointer"_en_US);
|
||||
if (ultimate != nullptr) {
|
||||
msg->Attach(ultimate->name(), "Declaration of function"_en_US);
|
||||
|
@ -138,8 +137,7 @@ void CheckPointerAssignment(parser::ContextualMessages &messages,
|
|||
}
|
||||
}
|
||||
if (error.has_value()) {
|
||||
if (auto *msg{messages.Say(*error, lhs.name().ToString().c_str(),
|
||||
ultimate.name().ToString().c_str())}) {
|
||||
if (auto *msg{messages.Say(*error, lhs.name(), ultimate.name())}) {
|
||||
msg->Attach(lhs.name(), "Declaration of pointer being assigned"_en_US)
|
||||
.Attach(ultimate.name(), "Declaration of pointer target"_en_US);
|
||||
}
|
||||
|
@ -184,8 +182,7 @@ void CheckPointerAssignment(parser::ContextualMessages &messages,
|
|||
"is a procedure designator"_err_en_US;
|
||||
}
|
||||
if (error.has_value()) {
|
||||
if (auto *msg{messages.Say(*error, lhs.name().ToString().c_str(),
|
||||
rhsName.ToString().c_str())}) {
|
||||
if (auto *msg{messages.Say(*error, lhs.name(), rhsName)}) {
|
||||
msg->Attach(lhs.name(), "Declaration of pointer being assigned"_en_US);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -541,16 +541,14 @@ bool AllocationCheckerHelper::RunCoarrayRelatedChecks(
|
|||
context
|
||||
.Say(allocateInfo_.typeSpecLoc.value(),
|
||||
"Type-Spec in ALLOCATE must not be TEAM_TYPE from ISO_FORTRAN_ENV when an allocatable object is a coarray"_err_en_US)
|
||||
.Attach(name_.source, "'%s' is a coarray"_en_US,
|
||||
name_.source.ToString().c_str());
|
||||
.Attach(name_.source, "'%s' is a coarray"_en_US, name_.source);
|
||||
return false;
|
||||
} else if (IsDerivedTypeFromModule(derived, "iso_c_binding", "c_ptr") ||
|
||||
IsDerivedTypeFromModule(derived, "iso_c_binding", "c_funptr")) {
|
||||
context
|
||||
.Say(allocateInfo_.typeSpecLoc.value(),
|
||||
"Type-Spec in ALLOCATE must not be C_PTR or C_FUNPTR from ISO_C_BINDING when an allocatable object is a coarray"_err_en_US)
|
||||
.Attach(name_.source, "'%s' is a coarray"_en_US,
|
||||
name_.source.ToString().c_str());
|
||||
.Attach(name_.source, "'%s' is a coarray"_en_US, name_.source);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -562,16 +560,14 @@ bool AllocationCheckerHelper::RunCoarrayRelatedChecks(
|
|||
context
|
||||
.Say(allocateInfo_.sourceExprLoc.value(),
|
||||
"SOURCE or MOLD expression type must not be TEAM_TYPE from ISO_FORTRAN_ENV when an allocatable object is a coarray"_err_en_US)
|
||||
.Attach(name_.source, "'%s' is a coarray"_en_US,
|
||||
name_.source.ToString().c_str());
|
||||
.Attach(name_.source, "'%s' is a coarray"_en_US, name_.source);
|
||||
return false;
|
||||
} else if (IsDerivedTypeFromModule(derived, "iso_c_binding", "c_ptr") ||
|
||||
IsDerivedTypeFromModule(derived, "iso_c_binding", "c_funptr")) {
|
||||
context
|
||||
.Say(allocateInfo_.sourceExprLoc.value(),
|
||||
"SOURCE or MOLD expression type must not be C_PTR or C_FUNPTR from ISO_C_BINDING when an allocatable object is a coarray"_err_en_US)
|
||||
.Attach(name_.source, "'%s' is a coarray"_en_US,
|
||||
name_.source.ToString().c_str());
|
||||
.Attach(name_.source, "'%s' is a coarray"_en_US, name_.source);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,8 +90,8 @@ void CoarrayChecker::CheckNamesAreDistinct(
|
|||
void CoarrayChecker::Say2(const parser::CharBlock &name1,
|
||||
parser::MessageFixedText &&msg1, const parser::CharBlock &name2,
|
||||
parser::MessageFixedText &&msg2) {
|
||||
context_.Say(name1, std::move(msg1), name1.ToString().c_str())
|
||||
.Attach(name2, std::move(msg2), name2.ToString().c_str());
|
||||
context_.Say(name1, std::move(msg1), name1)
|
||||
.Attach(name2, std::move(msg2), name2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -266,15 +266,14 @@ public:
|
|||
if (do_depth_ == 0) {
|
||||
messages_.Say(currentStatementSourcePosition_,
|
||||
"exit from DO CONCURRENT construct (%s)"_err_en_US,
|
||||
doConcurrentSourcePosition_.ToString().data());
|
||||
doConcurrentSourcePosition_);
|
||||
}
|
||||
// nesting of named constructs is assumed to have been previously checked
|
||||
// by the name/label resolution pass
|
||||
} else if (names_.find(nm.value().source) == names_.end()) {
|
||||
messages_.Say(currentStatementSourcePosition_,
|
||||
"exit from DO CONCURRENT construct (%s) to construct with name '%s'"_err_en_US,
|
||||
doConcurrentSourcePosition_.ToString().data(),
|
||||
nm.value().source.ToString().data());
|
||||
doConcurrentSourcePosition_, nm.value().source);
|
||||
}
|
||||
}
|
||||
void checkLabelUse(const parser::Label &labelUsed) {
|
||||
|
|
|
@ -139,7 +139,7 @@ void IoChecker::Enter(const parser::InputItem &spec) {
|
|||
// This check may be superseded by C928 or C1002.
|
||||
context_.Say(name.source,
|
||||
"'%s' must not be a whole assumed size array"_err_en_US,
|
||||
name.ToString().c_str()); // C1231
|
||||
name); // C1231
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ void IoChecker::Enter(const parser::StatusExpr &spec) {
|
|||
CHECK(stmt_ == IoStmtKind::Close);
|
||||
if (s != "DELETE" && s != "KEEP") {
|
||||
context_.Say(parser::FindSourceLocation(spec),
|
||||
"invalid STATUS value '%s'"_err_en_US, (*charConst).c_str());
|
||||
"invalid STATUS value '%s'"_err_en_US, *charConst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -476,7 +476,7 @@ void IoChecker::SetSpecifier(IoSpecKind specKind) {
|
|||
// C1203, C1207, C1210, C1236, C1239, C1242, C1245
|
||||
if (specifierSet_.test(specKind)) {
|
||||
context_.Say("duplicate %s specifier"_err_en_US,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)).c_str());
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)));
|
||||
}
|
||||
specifierSet_.set(specKind);
|
||||
}
|
||||
|
@ -506,8 +506,7 @@ void IoChecker::CheckStringValue(IoSpecKind specKind, const std::string &value,
|
|||
};
|
||||
if (!specValues.at(specKind).count(parser::ToUpperCaseLetters(value))) {
|
||||
context_.Say(source, "invalid %s value '%s'"_err_en_US,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)).c_str(),
|
||||
value.c_str());
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)), value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -520,8 +519,8 @@ void IoChecker::CheckStringValue(IoSpecKind specKind, const std::string &value,
|
|||
void IoChecker::CheckForRequiredSpecifier(IoSpecKind specKind) const {
|
||||
if (!specifierSet_.test(specKind)) {
|
||||
context_.Say("%s statement must have a %s specifier"_err_en_US,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(stmt_)).c_str(),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)).c_str());
|
||||
parser::ToUpperCaseLetters(common::EnumToString(stmt_)),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -529,8 +528,7 @@ void IoChecker::CheckForRequiredSpecifier(
|
|||
bool condition, const std::string &s) const {
|
||||
if (!condition) {
|
||||
context_.Say("%s statement must have a %s specifier"_err_en_US,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(stmt_)).c_str(),
|
||||
s.c_str());
|
||||
parser::ToUpperCaseLetters(common::EnumToString(stmt_)), s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,8 +536,8 @@ void IoChecker::CheckForRequiredSpecifier(
|
|||
IoSpecKind specKind1, IoSpecKind specKind2) const {
|
||||
if (specifierSet_.test(specKind1) && !specifierSet_.test(specKind2)) {
|
||||
context_.Say("if %s appears, %s must also appear"_err_en_US,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind1)).c_str(),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind2)).c_str());
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind1)),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind2)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,32 +545,30 @@ void IoChecker::CheckForRequiredSpecifier(
|
|||
IoSpecKind specKind, bool condition, const std::string &s) const {
|
||||
if (specifierSet_.test(specKind) && !condition) {
|
||||
context_.Say("if %s appears, %s must also appear"_err_en_US,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)).c_str(),
|
||||
s.c_str());
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)), s);
|
||||
}
|
||||
}
|
||||
|
||||
void IoChecker::CheckForRequiredSpecifier(
|
||||
bool condition, const std::string &s, IoSpecKind specKind) const {
|
||||
if (condition && !specifierSet_.test(specKind)) {
|
||||
context_.Say("if %s appears, %s must also appear"_err_en_US, s.c_str(),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)).c_str());
|
||||
context_.Say("if %s appears, %s must also appear"_err_en_US, s,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)));
|
||||
}
|
||||
}
|
||||
|
||||
void IoChecker::CheckForRequiredSpecifier(bool condition1,
|
||||
const std::string &s1, bool condition2, const std::string &s2) const {
|
||||
if (condition1 && !condition2) {
|
||||
context_.Say(
|
||||
"if %s appears, %s must also appear"_err_en_US, s1.c_str(), s2.c_str());
|
||||
context_.Say("if %s appears, %s must also appear"_err_en_US, s1, s2);
|
||||
}
|
||||
}
|
||||
|
||||
void IoChecker::CheckForProhibitedSpecifier(IoSpecKind specKind) const {
|
||||
if (specifierSet_.test(specKind)) {
|
||||
context_.Say("%s statement must not have a %s specifier"_err_en_US,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(stmt_)).c_str(),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)).c_str());
|
||||
parser::ToUpperCaseLetters(common::EnumToString(stmt_)),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,8 +576,8 @@ void IoChecker::CheckForProhibitedSpecifier(
|
|||
IoSpecKind specKind1, IoSpecKind specKind2) const {
|
||||
if (specifierSet_.test(specKind1) && specifierSet_.test(specKind2)) {
|
||||
context_.Say("if %s appears, %s must not appear"_err_en_US,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind1)).c_str(),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind2)).c_str());
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind1)),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind2)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -589,16 +585,15 @@ void IoChecker::CheckForProhibitedSpecifier(
|
|||
IoSpecKind specKind, bool condition, const std::string &s) const {
|
||||
if (specifierSet_.test(specKind) && condition) {
|
||||
context_.Say("if %s appears, %s must not appear"_err_en_US,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)).c_str(),
|
||||
s.c_str());
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)), s);
|
||||
}
|
||||
}
|
||||
|
||||
void IoChecker::CheckForProhibitedSpecifier(
|
||||
bool condition, const std::string &s, IoSpecKind specKind) const {
|
||||
if (condition && specifierSet_.test(specKind)) {
|
||||
context_.Say("if %s appears, %s must not appear"_err_en_US, s.c_str(),
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)).c_str());
|
||||
context_.Say("if %s appears, %s must not appear"_err_en_US, s,
|
||||
parser::ToUpperCaseLetters(common::EnumToString(specKind)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ MaybeExpr ExpressionAnalyzer::Designate(DataRef &&ref) {
|
|||
if (declTypeSpec->category() == semantics::DeclTypeSpec::TypeStar) {
|
||||
Say("TYPE(*) assumed-type dummy argument '%s' may not be "
|
||||
"used except as an actual argument"_err_en_US,
|
||||
symbol.name().ToString().c_str());
|
||||
symbol.name());
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
|
@ -200,7 +200,7 @@ MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
|
|||
}
|
||||
if (subscripts != symbolRank) {
|
||||
Say("Reference to rank-%d object '%s' has %d subscripts"_err_en_US,
|
||||
symbolRank, symbol.name().ToString().c_str(), subscripts);
|
||||
symbolRank, symbol.name(), subscripts);
|
||||
} else if (subscripts == 0) {
|
||||
// nothing to check
|
||||
} else if (Component * component{std::get_if<Component>(&ref.base())}) {
|
||||
|
@ -213,7 +213,7 @@ MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
|
|||
if (subscriptRank > 0) {
|
||||
Say("Subscripts of component '%s' of rank-%d derived type "
|
||||
"array have rank %d but must all be scalar"_err_en_US,
|
||||
symbol.name().ToString().c_str(), baseRank, subscriptRank);
|
||||
symbol.name(), baseRank, subscriptRank);
|
||||
}
|
||||
}
|
||||
} else if (const auto *details{
|
||||
|
@ -223,7 +223,7 @@ MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
|
|||
if (!last->upper().has_value() && details->IsAssumedSize()) {
|
||||
Say("Assumed-size array '%s' must have explicit final "
|
||||
"subscript upper bound value"_err_en_US,
|
||||
symbol.name().ToString().c_str());
|
||||
symbol.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ MaybeExpr ExpressionAnalyzer::TopLevelChecks(DataRef &&dataRef) {
|
|||
if (baseRank > 0) {
|
||||
Say("Reference to whole rank-%d component '%%%s' of "
|
||||
"rank-%d array of derived type is not allowed"_err_en_US,
|
||||
componentRank, symbol.name().ToString().c_str(), baseRank);
|
||||
componentRank, symbol.name(), baseRank);
|
||||
} else {
|
||||
addSubscripts = true;
|
||||
}
|
||||
|
@ -579,7 +579,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::LogicalLiteralConstant &x) {
|
|||
|
||||
// BOZ typeless literals
|
||||
MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
|
||||
const char *p{x.v.data()};
|
||||
const char *p{x.v.c_str()};
|
||||
std::uint64_t base{16};
|
||||
switch (*p++) {
|
||||
case 'b': base = 2; break;
|
||||
|
@ -592,11 +592,11 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
|
|||
++p;
|
||||
auto value{BOZLiteralConstant::Read(p, base, false /*unsigned*/)};
|
||||
if (*p != '"') {
|
||||
Say("invalid digit ('%c') in BOZ literal %s"_err_en_US, *p, x.v.data());
|
||||
Say("Invalid digit ('%c') in BOZ literal '%s'"_err_en_US, *p, x.v);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (value.overflow) {
|
||||
Say("BOZ literal %s too large"_err_en_US, x.v.data());
|
||||
Say("BOZ literal '%s' too large"_err_en_US, x.v);
|
||||
return std::nullopt;
|
||||
}
|
||||
return {AsGenericExpr(std::move(value.value))};
|
||||
|
@ -704,7 +704,8 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) {
|
|||
std::optional<Expr<SubscriptInteger>> last{
|
||||
GetSubstringBound(std::get<1>(range.t))};
|
||||
const Symbol &symbol{checked->GetLastSymbol()};
|
||||
if (std::optional<DynamicType> dynamicType{DynamicType::From(symbol)}) {
|
||||
if (std::optional<DynamicType> dynamicType{
|
||||
DynamicType::From(symbol)}) {
|
||||
if (dynamicType->category == TypeCategory::Character) {
|
||||
return WrapperHelper<TypeCategory::Character, Designator,
|
||||
Substring>(dynamicType->kind,
|
||||
|
@ -911,7 +912,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
|
|||
return Designate(DataRef{std::move(*component)});
|
||||
} else {
|
||||
Say(name, "component is not in scope of derived TYPE(%s)"_err_en_US,
|
||||
dtSpec->typeSymbol().name().ToString().c_str());
|
||||
dtSpec->typeSymbol().name());
|
||||
}
|
||||
} else {
|
||||
Say(name,
|
||||
|
@ -1222,7 +1223,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
if (auto *msg{Say(typeName,
|
||||
"ABSTRACT derived type '%s' may not be used in a "
|
||||
"structure constructor"_err_en_US,
|
||||
typeName.ToString().c_str())}) {
|
||||
typeName)}) {
|
||||
msg->Attach(
|
||||
typeSymbol.name(), "Declaration of ABSTRACT derived type"_en_US);
|
||||
}
|
||||
|
@ -1267,7 +1268,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
if (symbol == nullptr) { // C7101
|
||||
Say(source,
|
||||
"Keyword '%s=' does not name a component of derived type '%s'"_err_en_US,
|
||||
source.ToString().c_str(), typeName.ToString().c_str());
|
||||
source, typeName);
|
||||
}
|
||||
} else {
|
||||
if (anyKeyword) { // C7100
|
||||
|
@ -1295,7 +1296,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
Say(source,
|
||||
"Component '%s' conflicts with another component earlier in "
|
||||
"this structure constructor"_err_en_US,
|
||||
symbol->name().ToString().c_str());
|
||||
symbol->name());
|
||||
} else if (symbol->test(Symbol::Flag::ParentComp)) {
|
||||
// Make earlier components unavailable once a whole parent appears.
|
||||
for (auto it{components.begin()}; it != componentIter; ++it) {
|
||||
|
@ -1329,8 +1330,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
"Externally visible object '%s' must not be "
|
||||
"associated with pointer component '%s' in a "
|
||||
"PURE function"_err_en_US,
|
||||
object->name().ToString().c_str(),
|
||||
pointer->name().ToString().c_str())}) {
|
||||
object->name(), pointer->name())}) {
|
||||
msg->Attach(object->name(), "Object declaration"_en_US)
|
||||
.Attach(pointer->name(), "Pointer declaration"_en_US);
|
||||
}
|
||||
|
@ -1341,13 +1341,13 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
Say(expr.source,
|
||||
"Type parameter '%s' may not appear as a component "
|
||||
"of a structure constructor"_err_en_US,
|
||||
symbol->name().ToString().c_str());
|
||||
symbol->name());
|
||||
continue;
|
||||
} else {
|
||||
Say(expr.source,
|
||||
"Component '%s' is neither a procedure pointer "
|
||||
"nor a data object"_err_en_US,
|
||||
symbol->name().ToString().c_str());
|
||||
symbol->name());
|
||||
continue;
|
||||
}
|
||||
if (IsPointer(*symbol)) {
|
||||
|
@ -1360,7 +1360,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
if (auto *msg{Say(expr.source,
|
||||
"Value in structure constructor is incompatible with "
|
||||
"component '%s'"_err_en_US,
|
||||
symbol->name().ToString().c_str())}) {
|
||||
symbol->name())}) {
|
||||
msg->Attach(symbol->name(), "Component declaration"_en_US);
|
||||
}
|
||||
}
|
||||
|
@ -1381,7 +1381,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
|
|||
if (auto *msg{Say(typeName,
|
||||
"Structure constructor lacks a value for "
|
||||
"component '%s'"_err_en_US,
|
||||
symbol->name().ToString().c_str())}) {
|
||||
symbol->name())}) {
|
||||
msg->Attach(symbol->name(), "Absent component"_en_US);
|
||||
}
|
||||
}
|
||||
|
@ -1413,7 +1413,7 @@ ExpressionAnalyzer::AnalyzeProcedureComponentRef(
|
|||
} else {
|
||||
Say(name,
|
||||
"procedure component is not in scope of derived TYPE(%s)"_err_en_US,
|
||||
dtSpec->typeSymbol().name().ToString().c_str());
|
||||
dtSpec->typeSymbol().name());
|
||||
}
|
||||
} else {
|
||||
Say(name,
|
||||
|
@ -1963,7 +1963,7 @@ bool ExpressionAnalyzer::CheckIntrinsicKind(
|
|||
return true;
|
||||
} else {
|
||||
Say("%s(KIND=%jd) is not a supported type"_err_en_US,
|
||||
parser::ToUpperCaseLetters(EnumToString(category)).c_str(), kind);
|
||||
parser::ToUpperCaseLetters(EnumToString(category)), kind);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1979,7 +1979,7 @@ bool ExpressionAnalyzer::CheckIntrinsicSize(
|
|||
return true;
|
||||
}
|
||||
Say("%s*%jd is not a supported type"_err_en_US,
|
||||
parser::ToUpperCaseLetters(EnumToString(category)).c_str(), size);
|
||||
parser::ToUpperCaseLetters(EnumToString(category)), size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2010,21 +2010,21 @@ bool ExpressionAnalyzer::EnforceTypeConstraint(parser::CharBlock at,
|
|||
if (auto type{result->GetType()}) {
|
||||
if (type->category != category) {
|
||||
Say(at, "Must have %s type, but is %s"_err_en_US,
|
||||
parser::ToUpperCaseLetters(EnumToString(category)).c_str(),
|
||||
parser::ToUpperCaseLetters(type->AsFortran()).c_str());
|
||||
parser::ToUpperCaseLetters(EnumToString(category)),
|
||||
parser::ToUpperCaseLetters(type->AsFortran()));
|
||||
return false;
|
||||
} else if (defaultKind) {
|
||||
int kind{context_.defaultKinds().GetDefaultKind(category)};
|
||||
if (type->kind != kind) {
|
||||
Say(at, "Must have default kind(%d) of %s type, but is %s"_err_en_US,
|
||||
kind, parser::ToUpperCaseLetters(EnumToString(category)).c_str(),
|
||||
parser::ToUpperCaseLetters(type->AsFortran()).c_str());
|
||||
kind, parser::ToUpperCaseLetters(EnumToString(category)),
|
||||
parser::ToUpperCaseLetters(type->AsFortran()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Say(at, "Must have %s type, but is typeless"_err_en_US,
|
||||
parser::ToUpperCaseLetters(EnumToString(category)).c_str());
|
||||
parser::ToUpperCaseLetters(EnumToString(category)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ void ModFileWriter::Write(const Symbol &symbol) {
|
|||
ModFilePath(context_.moduleDirectory(), symbol.name(), ancestorName)};
|
||||
PutSymbols(*symbol.scope());
|
||||
if (!WriteFile(path, GetAsString(symbol))) {
|
||||
context_.Say(symbol.name(), "Error writing %s: %s"_err_en_US, path.c_str(),
|
||||
context_.Say(symbol.name(), "Error writing %s: %s"_err_en_US, path,
|
||||
std::strerror(errno));
|
||||
}
|
||||
}
|
||||
|
@ -682,8 +682,7 @@ Scope *ModFileReader::Read(const SourceName &name, Scope *ancestor) {
|
|||
// to parse. Do it only reading the file once.
|
||||
if (!VerifyHeader(*path)) {
|
||||
context_.Say(name,
|
||||
"Module file for '%s' has invalid checksum: %s"_err_en_US,
|
||||
name.ToString().data(), path->data());
|
||||
"Module file for '%s' has invalid checksum: %s"_err_en_US, name, *path);
|
||||
return nullptr;
|
||||
}
|
||||
// TODO: Construct parsing with an AllSources reference to share provenance
|
||||
|
@ -695,8 +694,8 @@ Scope *ModFileReader::Read(const SourceName &name, Scope *ancestor) {
|
|||
auto &parseTree{parsing.parseTree()};
|
||||
if (!parsing.messages().empty() || !parsing.consumedWholeFile() ||
|
||||
!parseTree.has_value()) {
|
||||
context_.Say(name, "Module file for '%s' is corrupt: %s"_err_en_US,
|
||||
name.ToString().data(), path->data());
|
||||
context_.Say(
|
||||
name, "Module file for '%s' is corrupt: %s"_err_en_US, name, *path);
|
||||
return nullptr;
|
||||
}
|
||||
Scope *parentScope; // the scope this module/submodule goes into
|
||||
|
@ -727,21 +726,21 @@ std::optional<std::string> ModFileReader::FindModFile(
|
|||
std::string path{ModFilePath(dir, name, ancestor)};
|
||||
std::ifstream ifstream{path};
|
||||
if (!ifstream.good()) {
|
||||
attachments.Say(name, "%s: %s"_en_US, path.data(), std::strerror(errno));
|
||||
attachments.Say(name, "%s: %s"_en_US, path, std::strerror(errno));
|
||||
} else {
|
||||
std::string line;
|
||||
std::getline(ifstream, line);
|
||||
if (line.compare(0, strlen(magic), magic) == 0) {
|
||||
return path;
|
||||
}
|
||||
attachments.Say(name, "%s: Not a valid module file"_en_US, path.data());
|
||||
attachments.Say(name, "%s: Not a valid module file"_en_US, path);
|
||||
}
|
||||
}
|
||||
auto error{parser::Message{name,
|
||||
ancestor.empty()
|
||||
? "Cannot find module file for '%s'"_err_en_US
|
||||
: "Cannot find module file for submodule '%s' of module '%s'"_err_en_US,
|
||||
name.ToString().data(), ancestor.data()}};
|
||||
name, ancestor}};
|
||||
attachments.AttachTo(error);
|
||||
context_.Say(std::move(error));
|
||||
return std::nullopt;
|
||||
|
|
|
@ -387,12 +387,12 @@ public:
|
|||
if (optionalGenericSpec.has_value()) {
|
||||
if (const auto *otherPointer{
|
||||
std::get_if<parser::Name>(&optionalGenericSpec->u)}) {
|
||||
if (namePointer->ToString() != otherPointer->ToString()) {
|
||||
if (namePointer->source != otherPointer->source) {
|
||||
errorHandler_
|
||||
.Say(currentPosition_,
|
||||
parser::MessageFormattedText{
|
||||
"INTERFACE generic-name (%s) mismatch"_en_US,
|
||||
namePointer->ToString().c_str()})
|
||||
namePointer->source})
|
||||
.Attach(interfaceStmt.source, "mismatched INTERFACE"_en_US);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,8 +75,8 @@ private:
|
|||
// Check that name has been resolved to a symbol
|
||||
void RewriteMutator::Post(parser::Name &name) {
|
||||
if (name.symbol == nullptr && errorOnUnresolvedName_) {
|
||||
messages_.Say(name.source, "Internal: no symbol found for '%s'"_err_en_US,
|
||||
name.ToString().c_str());
|
||||
messages_.Say(
|
||||
name.source, "Internal: no symbol found for '%s'"_err_en_US, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -298,8 +298,7 @@ const DeclTypeSpec &Scope::InstantiateIntrinsicType(
|
|||
"did not resolve to a supported value"_err_en_US,
|
||||
static_cast<std::intmax_t>(*value),
|
||||
parser::ToUpperCaseLetters(
|
||||
common::EnumToString(intrinsic->category()))
|
||||
.data());
|
||||
common::EnumToString(intrinsic->category())));
|
||||
}
|
||||
}
|
||||
switch (spec.category()) {
|
||||
|
|
|
@ -92,15 +92,13 @@ public:
|
|||
bool HasError(const parser::Name &);
|
||||
void SetError(Symbol &, bool = true);
|
||||
|
||||
template<typename... A>
|
||||
common::IfNoLvalue<parser::Message &, A...> Say(
|
||||
parser::CharBlock at, A &&... args) {
|
||||
return messages_.Say(at, std::move(args)...);
|
||||
template<typename... A> parser::Message &Say(A &&... args) {
|
||||
CHECK(location_);
|
||||
return messages_.Say(*location_, std::forward<A>(args)...);
|
||||
}
|
||||
template<typename... A>
|
||||
common::IfNoLvalue<parser::Message &, A...> Say(A &&... args) {
|
||||
CHECK(location_);
|
||||
return messages_.Say(*location_, std::move(args)...);
|
||||
parser::Message &Say(parser::CharBlock at, A &&... args) {
|
||||
return messages_.Say(at, std::forward<A>(args)...);
|
||||
}
|
||||
parser::Message &Say(parser::Message &&msg) {
|
||||
return messages_.Say(std::move(msg));
|
||||
|
|
|
@ -105,7 +105,7 @@ void DerivedTypeSpec::Instantiate(
|
|||
if (auto *msg{foldingContext.messages().Say(
|
||||
"Value of kind type parameter '%s' (%s) is not "
|
||||
"scalar INTEGER constant"_err_en_US,
|
||||
name.ToString().data(), fortran.str().data())}) {
|
||||
name, fortran.str())}) {
|
||||
msg->Attach(name, "declared here"_en_US);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue