[flang-commits] [flang] 72c801f - [flang] Handle BOZ as right-hand side of assignment (#96672)
via flang-commits
flang-commits at lists.llvm.org
Fri Jun 28 11:46:58 PDT 2024
Author: Peter Klausler
Date: 2024-06-28T11:46:54-07:00
New Revision: 72c801f843d95546d92e2b15fe832503ba3bfab6
URL: https://github.com/llvm/llvm-project/commit/72c801f843d95546d92e2b15fe832503ba3bfab6
DIFF: https://github.com/llvm/llvm-project/commit/72c801f843d95546d92e2b15fe832503ba3bfab6.diff
LOG: [flang] Handle BOZ as right-hand side of assignment (#96672)
F'2023 allows BOZ to appear in more contexts, including the common
extension of the right-hand side of an assignment to an INTEGER or REAL
variable. Implement that one case now.
Added:
Modified:
flang/lib/Semantics/expression.cpp
flang/test/Semantics/boz-literal-constants.f90
Removed:
################################################################################
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index d80b3b65f0a98..2202639a92e43 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -141,7 +141,7 @@ class ArgumentAnalyzer {
}
void Analyze(const parser::Variable &);
void Analyze(const parser::ActualArgSpec &, bool isSubroutine);
- void ConvertBOZ(std::optional<DynamicType> &thisType, std::size_t i,
+ void ConvertBOZ(std::optional<DynamicType> *thisType, std::size_t,
std::optional<DynamicType> otherType);
bool IsIntrinsicRelational(
@@ -3573,8 +3573,8 @@ MaybeExpr RelationHelper(ExpressionAnalyzer &context, RelationalOperator opr,
if (!analyzer.fatalErrors()) {
std::optional<DynamicType> leftType{analyzer.GetType(0)};
std::optional<DynamicType> rightType{analyzer.GetType(1)};
- analyzer.ConvertBOZ(leftType, 0, rightType);
- analyzer.ConvertBOZ(rightType, 1, leftType);
+ analyzer.ConvertBOZ(&leftType, 0, rightType);
+ analyzer.ConvertBOZ(&rightType, 1, leftType);
if (leftType && rightType &&
analyzer.IsIntrinsicRelational(opr, *leftType, *rightType)) {
analyzer.CheckForNullPointer("as a relational operand");
@@ -4488,9 +4488,22 @@ std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() {
// allocatable (the explicit conversion would prevent the propagation of the
// right hand side if it is a variable). Lowering will deal with the
// conversion in this case.
- if (lhsType && rhsType &&
- (!IsAllocatableDesignator(lhs) || context_.inWhereBody())) {
- AddAssignmentConversion(*lhsType, *rhsType);
+ if (lhsType) {
+ if (rhsType) {
+ if (!IsAllocatableDesignator(lhs) || context_.inWhereBody()) {
+ AddAssignmentConversion(*lhsType, *rhsType);
+ }
+ } else {
+ if (lhsType->category() == TypeCategory::Integer ||
+ lhsType->category() == TypeCategory::Real) {
+ ConvertBOZ(nullptr, 1, lhsType);
+ }
+ if (IsBOZLiteral(1)) {
+ context_.Say(
+ "Right-hand side of this assignment may not be BOZ"_err_en_US);
+ fatalErrors_ = true;
+ }
+ }
}
if (!fatalErrors_) {
CheckAssignmentConformance();
@@ -4719,7 +4732,7 @@ int ArgumentAnalyzer::GetRank(std::size_t i) const {
// otherType. If it's REAL convert to REAL, otherwise convert to INTEGER.
// Note that IBM supports comparing BOZ literals to CHARACTER operands. That
// is not currently supported.
-void ArgumentAnalyzer::ConvertBOZ(std::optional<DynamicType> &thisType,
+void ArgumentAnalyzer::ConvertBOZ(std::optional<DynamicType> *thisType,
std::size_t i, std::optional<DynamicType> otherType) {
if (IsBOZLiteral(i)) {
Expr<SomeType> &&argExpr{MoveExpr(i)};
@@ -4729,13 +4742,17 @@ void ArgumentAnalyzer::ConvertBOZ(std::optional<DynamicType> &thisType,
MaybeExpr realExpr{
ConvertToKind<TypeCategory::Real>(kind, std::move(*boz))};
actuals_[i] = std::move(*realExpr);
- thisType.emplace(TypeCategory::Real, kind);
+ if (thisType) {
+ thisType->emplace(TypeCategory::Real, kind);
+ }
} else {
int kind{context_.context().GetDefaultKind(TypeCategory::Integer)};
MaybeExpr intExpr{
ConvertToKind<TypeCategory::Integer>(kind, std::move(*boz))};
actuals_[i] = std::move(*intExpr);
- thisType.emplace(TypeCategory::Integer, kind);
+ if (thisType) {
+ thisType->emplace(TypeCategory::Integer, kind);
+ }
}
}
}
diff --git a/flang/test/Semantics/boz-literal-constants.f90 b/flang/test/Semantics/boz-literal-constants.f90
index e6392f6f030e5..ee6919cb9ecd5 100644
--- a/flang/test/Semantics/boz-literal-constants.f90
+++ b/flang/test/Semantics/boz-literal-constants.f90
@@ -7,7 +7,12 @@ subroutine bozchecks
integer :: f, realpart = B"0101", img = B"1111", resint
logical :: resbit
complex :: rescmplx
+ character :: reschar
real :: dbl, e
+ type :: dt
+ integer :: n
+ end type
+ type(dt) :: resdt
interface
subroutine explicit(n, x, c)
integer :: n
@@ -98,6 +103,17 @@ subroutine explicit(n, x, c)
res = REAL(B"1101")
+ resint = z'ff' ! ok
+ res = z'3f800000' ! ok
+ !ERROR: Right-hand side of this assignment may not be BOZ
+ rescmplx = z'123'
+ !ERROR: Right-hand side of this assignment may not be BOZ
+ resbit = z'123'
+ !ERROR: Right-hand side of this assignment may not be BOZ
+ reschar = z'123'
+ !ERROR: Right-hand side of this assignment may not be BOZ
+ resdt = z'123'
+
!Ok
call explicit(z'deadbeef', o'666', 'a')
More information about the flang-commits
mailing list