Skip to content

Commit 72c801f

Browse files
authored
[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.
1 parent 084d943 commit 72c801f

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

flang/lib/Semantics/expression.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class ArgumentAnalyzer {
141141
}
142142
void Analyze(const parser::Variable &);
143143
void Analyze(const parser::ActualArgSpec &, bool isSubroutine);
144-
void ConvertBOZ(std::optional<DynamicType> &thisType, std::size_t i,
144+
void ConvertBOZ(std::optional<DynamicType> *thisType, std::size_t,
145145
std::optional<DynamicType> otherType);
146146

147147
bool IsIntrinsicRelational(
@@ -3573,8 +3573,8 @@ MaybeExpr RelationHelper(ExpressionAnalyzer &context, RelationalOperator opr,
35733573
if (!analyzer.fatalErrors()) {
35743574
std::optional<DynamicType> leftType{analyzer.GetType(0)};
35753575
std::optional<DynamicType> rightType{analyzer.GetType(1)};
3576-
analyzer.ConvertBOZ(leftType, 0, rightType);
3577-
analyzer.ConvertBOZ(rightType, 1, leftType);
3576+
analyzer.ConvertBOZ(&leftType, 0, rightType);
3577+
analyzer.ConvertBOZ(&rightType, 1, leftType);
35783578
if (leftType && rightType &&
35793579
analyzer.IsIntrinsicRelational(opr, *leftType, *rightType)) {
35803580
analyzer.CheckForNullPointer("as a relational operand");
@@ -4488,9 +4488,22 @@ std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() {
44884488
// allocatable (the explicit conversion would prevent the propagation of the
44894489
// right hand side if it is a variable). Lowering will deal with the
44904490
// conversion in this case.
4491-
if (lhsType && rhsType &&
4492-
(!IsAllocatableDesignator(lhs) || context_.inWhereBody())) {
4493-
AddAssignmentConversion(*lhsType, *rhsType);
4491+
if (lhsType) {
4492+
if (rhsType) {
4493+
if (!IsAllocatableDesignator(lhs) || context_.inWhereBody()) {
4494+
AddAssignmentConversion(*lhsType, *rhsType);
4495+
}
4496+
} else {
4497+
if (lhsType->category() == TypeCategory::Integer ||
4498+
lhsType->category() == TypeCategory::Real) {
4499+
ConvertBOZ(nullptr, 1, lhsType);
4500+
}
4501+
if (IsBOZLiteral(1)) {
4502+
context_.Say(
4503+
"Right-hand side of this assignment may not be BOZ"_err_en_US);
4504+
fatalErrors_ = true;
4505+
}
4506+
}
44944507
}
44954508
if (!fatalErrors_) {
44964509
CheckAssignmentConformance();
@@ -4719,7 +4732,7 @@ int ArgumentAnalyzer::GetRank(std::size_t i) const {
47194732
// otherType. If it's REAL convert to REAL, otherwise convert to INTEGER.
47204733
// Note that IBM supports comparing BOZ literals to CHARACTER operands. That
47214734
// is not currently supported.
4722-
void ArgumentAnalyzer::ConvertBOZ(std::optional<DynamicType> &thisType,
4735+
void ArgumentAnalyzer::ConvertBOZ(std::optional<DynamicType> *thisType,
47234736
std::size_t i, std::optional<DynamicType> otherType) {
47244737
if (IsBOZLiteral(i)) {
47254738
Expr<SomeType> &&argExpr{MoveExpr(i)};
@@ -4729,13 +4742,17 @@ void ArgumentAnalyzer::ConvertBOZ(std::optional<DynamicType> &thisType,
47294742
MaybeExpr realExpr{
47304743
ConvertToKind<TypeCategory::Real>(kind, std::move(*boz))};
47314744
actuals_[i] = std::move(*realExpr);
4732-
thisType.emplace(TypeCategory::Real, kind);
4745+
if (thisType) {
4746+
thisType->emplace(TypeCategory::Real, kind);
4747+
}
47334748
} else {
47344749
int kind{context_.context().GetDefaultKind(TypeCategory::Integer)};
47354750
MaybeExpr intExpr{
47364751
ConvertToKind<TypeCategory::Integer>(kind, std::move(*boz))};
47374752
actuals_[i] = std::move(*intExpr);
4738-
thisType.emplace(TypeCategory::Integer, kind);
4753+
if (thisType) {
4754+
thisType->emplace(TypeCategory::Integer, kind);
4755+
}
47394756
}
47404757
}
47414758
}

flang/test/Semantics/boz-literal-constants.f90

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ subroutine bozchecks
77
integer :: f, realpart = B"0101", img = B"1111", resint
88
logical :: resbit
99
complex :: rescmplx
10+
character :: reschar
1011
real :: dbl, e
12+
type :: dt
13+
integer :: n
14+
end type
15+
type(dt) :: resdt
1116
interface
1217
subroutine explicit(n, x, c)
1318
integer :: n
@@ -98,6 +103,17 @@ subroutine explicit(n, x, c)
98103

99104
res = REAL(B"1101")
100105

106+
resint = z'ff' ! ok
107+
res = z'3f800000' ! ok
108+
!ERROR: Right-hand side of this assignment may not be BOZ
109+
rescmplx = z'123'
110+
!ERROR: Right-hand side of this assignment may not be BOZ
111+
resbit = z'123'
112+
!ERROR: Right-hand side of this assignment may not be BOZ
113+
reschar = z'123'
114+
!ERROR: Right-hand side of this assignment may not be BOZ
115+
resdt = z'123'
116+
101117
!Ok
102118
call explicit(z'deadbeef', o'666', 'a')
103119

0 commit comments

Comments
 (0)