[flang-commits] [flang] 571673c - [flang] Disallow BOZ literal constants as output list items
Peter Steinfeld via flang-commits
flang-commits at lists.llvm.org
Tue Jul 27 13:13:04 PDT 2021
Author: Peter Steinfeld
Date: 2021-07-27T13:01:26-07:00
New Revision: 571673ce390a2f4973946c06801dfb2037115750
URL: https://github.com/llvm/llvm-project/commit/571673ce390a2f4973946c06801dfb2037115750
DIFF: https://github.com/llvm/llvm-project/commit/571673ce390a2f4973946c06801dfb2037115750.diff
LOG: [flang] Disallow BOZ literal constants as output list items
According to C7109, "A boz-literal-constant shall appear only as a
data-stmt-constant in a DATA statement, or where explicitly allowed in
16.9 as an actual argument of an intrinsic procedure." This change
enforces that constraint for output list items.
I also added a general interface to determine if an expression is a BOZ
literal constant and changed all of the places I could find where it
could be used.
I also added a test.
This change stemmed from the following issue --
https://gitlab-master.nvidia.com/fortran/f18-stage/issues/108
Differential Revision: https://reviews.llvm.org/D106893
Added:
Modified:
flang/include/flang/Evaluate/tools.h
flang/lib/Evaluate/intrinsics.cpp
flang/lib/Semantics/check-call.cpp
flang/lib/Semantics/check-io.cpp
flang/lib/Semantics/data-to-inits.cpp
flang/lib/Semantics/expression.cpp
flang/test/Semantics/boz-literal-constants.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index 257fb054a3acb..90c7cc03bcc94 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -460,6 +460,10 @@ template <typename TO> Expr<TO> ConvertToType(BOZLiteralConstant &&x) {
}
}
+template <typename T> bool IsBOZLiteral(const Expr<T> &expr) {
+ return std::holds_alternative<BOZLiteralConstant>(expr.u);
+}
+
// Conversions to dynamic types
std::optional<Expr<SomeType>> ConvertToType(
const DynamicType &, Expr<SomeType> &&);
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 5e305055b6913..8340e809f85ef 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -1247,7 +1247,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
if (!type) {
CHECK(arg->Rank() == 0);
const Expr<SomeType> &expr{DEREF(arg->UnwrapExpr())};
- if (std::holds_alternative<BOZLiteralConstant>(expr.u)) {
+ if (IsBOZLiteral(expr)) {
if (d.typePattern.kindCode == KindCode::typeless ||
d.rank == Rank::elementalOrBOZ) {
continue;
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 77fc25b44f6e4..ee0a4bfc59168 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -46,7 +46,7 @@ static void CheckImplicitInterfaceArg(
}
}
if (const auto *expr{arg.UnwrapExpr()}) {
- if (std::holds_alternative<evaluate::BOZLiteralConstant>(expr->u)) {
+ if (IsBOZLiteral(*expr)) {
messages.Say("BOZ argument requires an explicit interface"_err_en_US);
}
if (auto named{evaluate::ExtractNamedEntity(*expr)}) {
@@ -632,8 +632,7 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
CheckExplicitDataArg(object, dummyName, *expr, *type,
isElemental, context, scope, intrinsic);
} else if (object.type.type().IsTypelessIntrinsicArgument() &&
- std::holds_alternative<evaluate::BOZLiteralConstant>(
- expr->u)) {
+ IsBOZLiteral(*expr)) {
// ok
} else if (object.type.type().IsTypelessIntrinsicArgument() &&
evaluate::IsNullPointer(*expr)) {
diff --git a/flang/lib/Semantics/check-io.cpp b/flang/lib/Semantics/check-io.cpp
index 9ce7f82936147..fcca5f7b12915 100644
--- a/flang/lib/Semantics/check-io.cpp
+++ b/flang/lib/Semantics/check-io.cpp
@@ -8,6 +8,7 @@
#include "check-io.h"
#include "flang/Common/format.h"
+#include "flang/Evaluate/tools.h"
#include "flang/Parser/tools.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/tools.h"
@@ -550,6 +551,10 @@ void IoChecker::Enter(const parser::OutputItem &item) {
flags_.set(Flag::DataList);
if (const auto *x{std::get_if<parser::Expr>(&item.u)}) {
if (const auto *expr{GetExpr(*x)}) {
+ if (evaluate::IsBOZLiteral(*expr)) {
+ context_.Say(parser::FindSourceLocation(*x), // C7109
+ "Output item must not be a BOZ literal constant"_err_en_US);
+ }
const Symbol *last{GetLastSymbol(*expr)};
if (last && IsProcedurePointer(*last)) {
context_.Say(parser::FindSourceLocation(*x),
diff --git a/flang/lib/Semantics/data-to-inits.cpp b/flang/lib/Semantics/data-to-inits.cpp
index e72216c8233f4..168dfb8e45586 100644
--- a/flang/lib/Semantics/data-to-inits.cpp
+++ b/flang/lib/Semantics/data-to-inits.cpp
@@ -17,6 +17,7 @@
#include "data-to-inits.h"
#include "pointer-assignment.h"
#include "flang/Evaluate/fold-designator.h"
+#include "flang/Evaluate/tools.h"
#include "flang/Semantics/tools.h"
namespace Fortran::semantics {
@@ -338,7 +339,7 @@ bool DataInitializationCompiler::InitElement(
DescribeElement());
} else if (auto converted{ConvertElement(*expr, *designatorType)}) {
// value non-pointer initialization
- if (std::holds_alternative<evaluate::BOZLiteralConstant>(expr->u) &&
+ if (IsBOZLiteral(*expr) &&
designatorType->category() != TypeCategory::Integer) { // 8.6.7(11)
exprAnalyzer_.Say(
"BOZ literal should appear in a DATA statement only as a value for an integer object, but '%s' is '%s'"_en_US,
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index f6e55263820de..e4ce88b1284ca 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -157,7 +157,7 @@ class ArgumentAnalyzer {
bool OkLogicalIntegerAssignment(TypeCategory lhs, TypeCategory rhs);
int GetRank(std::size_t) const;
bool IsBOZLiteral(std::size_t i) const {
- return std::holds_alternative<BOZLiteralConstant>(GetExpr(i).u);
+ return evaluate::IsBOZLiteral(GetExpr(i));
}
void SayNoMatch(const std::string &, bool isAssignment = false);
std::string TypeAsFortran(std::size_t);
diff --git a/flang/test/Semantics/boz-literal-constants.f90 b/flang/test/Semantics/boz-literal-constants.f90
index 8636a31e705f1..e7dae868499d5 100644
--- a/flang/test/Semantics/boz-literal-constants.f90
+++ b/flang/test/Semantics/boz-literal-constants.f90
@@ -80,4 +80,7 @@ subroutine bozchecks
!ERROR: BOZ argument requires an explicit interface
call implictSub(Z'12345')
+
+ !ERROR: Output item must not be a BOZ literal constant
+ print "(Z18)", Z"76543210"
end subroutine
More information about the flang-commits
mailing list