[flang-commits] [flang] 89d5c31 - [flang] Make per-argument intrinsic error messages more localized
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Mon Mar 7 12:31:13 PST 2022
Author: Peter Klausler
Date: 2022-03-07T12:31:03-08:00
New Revision: 89d5c31b780d28de1a9867238fe2304eef6dff37
URL: https://github.com/llvm/llvm-project/commit/89d5c31b780d28de1a9867238fe2304eef6dff37
DIFF: https://github.com/llvm/llvm-project/commit/89d5c31b780d28de1a9867238fe2304eef6dff37.diff
LOG: [flang] Make per-argument intrinsic error messages more localized
A recent patch made it possible to emit more localized error messages
pertaining to actual arguments in non-intrinsic procedure references.
Use these new powers for good and make intrinsic error messages more
precise, too.
Differential Revision: https://reviews.llvm.org/D121126
Added:
Modified:
flang/include/flang/Parser/message.h
flang/lib/Evaluate/intrinsics.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index 21aff2b82d404..50ab3118543f5 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -296,6 +296,11 @@ class ContextualMessages {
}
}
+ template <typename... A>
+ Message *Say(std::optional<CharBlock> at, A &&...args) {
+ return Say(at.value_or(at_), std::forward<A>(args)...);
+ }
+
template <typename... A> Message *Say(A &&...args) {
return Say(at_, std::forward<A>(args)...);
}
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 95f80f516eba0..1a674ede0c6ff 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -1243,7 +1243,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
if (!arg) {
++missingActualArguments;
} else if (arg->isAlternateReturn()) {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
name);
return std::nullopt;
@@ -1323,7 +1323,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
continue;
}
} else if (d.optionality == Optionality::missing) {
- messages.Say("unexpected '%s=' argument"_err_en_US, d.keyword);
+ messages.Say(arg->sourceLocation(), "unexpected '%s=' argument"_err_en_US,
+ d.keyword);
return std::nullopt;
}
if (arg->GetAssumedTypeDummy()) {
@@ -1334,8 +1335,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
d.typePattern.kindCode == KindCode::addressable)) {
continue;
} else {
- messages.Say("Assumed type TYPE(*) dummy argument not allowed "
- "for '%s=' intrinsic argument"_err_en_US,
+ messages.Say(arg->sourceLocation(),
+ "Assumed type TYPE(*) dummy argument not allowed for '%s=' intrinsic argument"_err_en_US,
d.keyword);
return std::nullopt;
}
@@ -1352,11 +1353,11 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
const IntrinsicDummyArgument *nextParam{
j + 1 < dummies ? &dummy[j + 1] : nullptr};
if (nextParam && nextParam->rank == Rank::elementalOrBOZ) {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"Typeless (BOZ) not allowed for both '%s=' & '%s=' arguments"_err_en_US, // C7109
d.keyword, nextParam->keyword);
} else {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"Typeless (BOZ) not allowed for '%s=' argument"_err_en_US,
d.keyword);
}
@@ -1370,15 +1371,16 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
} else if (d.typePattern.kindCode == KindCode::nullPointerType) {
continue;
} else {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"Actual argument for '%s=' may not be a procedure"_err_en_US,
d.keyword);
}
}
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());
+ messages.Say(arg->sourceLocation(),
+ "Actual argument for '%s=' has bad type '%s'"_err_en_US, d.keyword,
+ type->AsFortran());
return std::nullopt; // argument has invalid type category
}
bool argOk{false};
@@ -1457,7 +1459,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
CRASH_NO_CASE;
}
if (!argOk) {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"Actual argument for '%s=' has bad type or kind '%s'"_err_en_US,
d.keyword, type->AsFortran());
return std::nullopt;
@@ -1475,8 +1477,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
if (const ActualArgument * arg{actualForDummy[j]}) {
bool isAssumedRank{IsAssumedRank(*arg)};
if (isAssumedRank && d.rank != Rank::anyOrAssumedRank) {
- messages.Say("Assumed-rank array cannot be forwarded to "
- "'%s=' argument"_err_en_US,
+ messages.Say(arg->sourceLocation(),
+ "Assumed-rank array cannot be forwarded to '%s=' argument"_err_en_US,
d.keyword);
return std::nullopt;
}
@@ -1499,7 +1501,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
case Rank::shape:
CHECK(!shapeArgSize);
if (rank != 1) {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"'shape=' argument must be an array of rank 1"_err_en_US);
return std::nullopt;
} else {
@@ -1512,7 +1514,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
}
}
if (!argOk) {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"'shape=' argument must be a vector of known size"_err_en_US);
return std::nullopt;
}
@@ -1530,7 +1532,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
case Rank::coarray:
argOk = IsCoarray(*arg);
if (!argOk) {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"'coarray=' argument must have corank > 0 for intrinsic '%s'"_err_en_US,
name);
return std::nullopt;
@@ -1556,11 +1558,11 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
if (std::optional<Shape> shape{GetShape(context, *arg)}) {
if (!shape->empty() && !shape->back().has_value()) {
if (strcmp(name, "shape") == 0) {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"The '%s=' argument to the intrinsic function '%s' may not be assumed-size"_err_en_US,
d.keyword, name);
} else {
- messages.Say(
+ messages.Say(arg->sourceLocation(),
"A dim= argument is required for '%s' when the array is assumed-size"_err_en_US,
name);
}
@@ -1606,8 +1608,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
d.keyword, name);
}
if (!argOk) {
- messages.Say("'%s=' argument has unacceptable rank %d"_err_en_US,
- d.keyword, rank);
+ messages.Say(arg->sourceLocation(),
+ "'%s=' argument has unacceptable rank %d"_err_en_US, d.keyword,
+ rank);
return std::nullopt;
}
}
@@ -2020,14 +2023,15 @@ bool CheckAndRearrangeArguments(ActualArguments &arguments,
return false;
}
} else if (anyKeywords) {
- messages.Say(
+ messages.Say(arg ? arg->sourceLocation() : messages.at(),
"A positional actual argument may not appear after any keyword arguments"_err_en_US);
return false;
} else {
dummyIndex = position++;
}
if (rearranged[dummyIndex]) {
- messages.Say("Dummy argument '%s=' appears more than once"_err_en_US,
+ messages.Say(arg ? arg->sourceLocation() : messages.at(),
+ "Dummy argument '%s=' appears more than once"_err_en_US,
dummyKeywords[dummyIndex]);
return false;
}
@@ -2081,7 +2085,7 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
"mold"s, characteristics::DummyDataObject{typeAndShape});
fResult.emplace(std::move(typeAndShape));
} else {
- context.messages().Say(
+ context.messages().Say(arguments[0]->sourceLocation(),
"MOLD= argument to NULL() lacks type"_err_en_US);
}
if (goodProcPointer) {
@@ -2095,7 +2099,7 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
}
}
}
- context.messages().Say(
+ context.messages().Say(arguments[0]->sourceLocation(),
"MOLD= argument to NULL() must be a pointer or allocatable"_err_en_US);
}
characteristics::Procedure::Attrs attrs;
@@ -2121,7 +2125,7 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
CHECK(arguments.size() == 3);
if (const auto *expr{arguments[0].value().UnwrapExpr()}) {
if (expr->Rank() > 0) {
- context.messages().Say(
+ context.messages().Say(arguments[0]->sourceLocation(),
"CPTR= argument to C_F_POINTER() must be scalar"_err_en_US);
}
if (auto type{expr->GetType()}) {
@@ -2129,7 +2133,7 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
type->IsPolymorphic() ||
type->GetDerivedTypeSpec().typeSymbol().name() !=
"__builtin_c_ptr") {
- context.messages().Say(
+ context.messages().Say(arguments[0]->sourceLocation(),
"CPTR= argument to C_F_POINTER() must be a C_PTR"_err_en_US);
}
characteristics::DummyDataObject cptr{
@@ -2142,11 +2146,11 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
int fptrRank{expr->Rank()};
if (auto type{expr->GetType()}) {
if (type->HasDeferredTypeParameter()) {
- context.messages().Say(
+ context.messages().Say(arguments[1]->sourceLocation(),
"FPTR= argument to C_F_POINTER() may not have a deferred type parameter"_err_en_US);
}
if (ExtractCoarrayRef(*expr)) {
- context.messages().Say(
+ context.messages().Say(arguments[1]->sourceLocation(),
"FPTR= argument to C_F_POINTER() may not be a coindexed object"_err_en_US);
}
characteristics::DummyDataObject fptr{
@@ -2155,11 +2159,11 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
fptr.attrs.set(characteristics::DummyDataObject::Attr::Pointer);
dummies.emplace_back("fptr"s, std::move(fptr));
} else {
- context.messages().Say(
+ context.messages().Say(arguments[1]->sourceLocation(),
"FPTR= argument to C_F_POINTER() must have a type"_err_en_US);
}
if (arguments[2] && fptrRank == 0) {
- context.messages().Say(
+ context.messages().Say(arguments[2]->sourceLocation(),
"SHAPE= argument to C_F_POINTER() may not appear when FPTR= is scalar"_err_en_US);
} else if (!arguments[2] && fptrRank > 0) {
context.messages().Say(
@@ -2196,7 +2200,7 @@ static bool CheckAssociated(SpecificCall &call, FoldingContext &context) {
if (const auto *pointerExpr{pointerArg->UnwrapExpr()}) {
if (const Symbol * pointerSymbol{GetLastSymbol(*pointerExpr)}) {
if (!pointerSymbol->attrs().test(semantics::Attr::POINTER)) {
- AttachDeclaration(context.messages().Say(
+ AttachDeclaration(context.messages().Say(pointerArg->sourceLocation(),
"POINTER= argument of ASSOCIATED() must be a "
"POINTER"_err_en_US),
*pointerSymbol);
@@ -2268,6 +2272,7 @@ static bool CheckAssociated(SpecificCall &call, FoldingContext &context) {
CHECK(!symbols.empty());
if (!GetLastTarget(symbols)) {
parser::Message *msg{context.messages().Say(
+ targetArg->sourceLocation(),
"TARGET= argument '%s' must have either the POINTER or the TARGET attribute"_err_en_US,
targetExpr->AsFortran())};
for (SymbolRef ref : symbols) {
@@ -2301,7 +2306,8 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
bool ok{true};
const std::string &name{call.specificIntrinsic.name};
if (name == "allocated") {
- if (const auto &arg{call.arguments[0]}) {
+ const auto &arg{call.arguments[0]};
+ if (arg) {
if (const auto *expr{arg->UnwrapExpr()}) {
if (const Symbol * symbol{GetLastSymbol(*expr)}) {
ok = symbol->attrs().test(semantics::Attr::ALLOCATABLE);
@@ -2310,20 +2316,23 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
}
if (!ok) {
context.messages().Say(
+ arg ? arg->sourceLocation() : context.messages().at(),
"Argument of ALLOCATED() must be an ALLOCATABLE object or component"_err_en_US);
}
} else if (name == "associated") {
return CheckAssociated(call, context);
} else if (name == "loc") {
- if (const auto &arg{call.arguments[0]}) {
- ok = arg->GetAssumedTypeDummy() || GetLastSymbol(arg->UnwrapExpr());
- }
+ const auto &arg{call.arguments[0]};
+ ok =
+ arg && (arg->GetAssumedTypeDummy() || GetLastSymbol(arg->UnwrapExpr()));
if (!ok) {
context.messages().Say(
+ arg ? arg->sourceLocation() : context.messages().at(),
"Argument of LOC() must be an object or procedure"_err_en_US);
}
} else if (name == "present") {
- if (const auto &arg{call.arguments[0]}) {
+ const auto &arg{call.arguments[0]};
+ if (arg) {
if (const auto *expr{arg->UnwrapExpr()}) {
if (const Symbol * symbol{UnwrapWholeSymbolDataRef(*expr)}) {
ok = symbol->attrs().test(semantics::Attr::OPTIONAL);
@@ -2332,6 +2341,7 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
}
if (!ok) {
context.messages().Say(
+ arg ? arg->sourceLocation() : context.messages().at(),
"Argument of PRESENT() must be the name of an OPTIONAL dummy argument"_err_en_US);
}
}
More information about the flang-commits
mailing list