diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -123,6 +123,7 @@ } void Analyze(const parser::Variable &); void Analyze(const parser::ActualArgSpec &, bool isSubroutine); + void ConvertBOZToInt(std::size_t i); bool IsIntrinsicRelational(RelationalOperator) const; bool IsIntrinsicLogical() const; @@ -2337,12 +2338,16 @@ analyzer.Analyze(std::get<1>(x.t)); if (analyzer.fatalErrors()) { return std::nullopt; - } else if (analyzer.IsIntrinsicRelational(opr)) { - return AsMaybeExpr(Relate(context.GetContextualMessages(), opr, - analyzer.MoveExpr(0), analyzer.MoveExpr(1))); } else { - return analyzer.TryDefinedOp(opr, - "Operands of %s must have comparable types; have %s and %s"_err_en_US); + analyzer.ConvertBOZToInt(0); + analyzer.ConvertBOZToInt(1); + if (analyzer.IsIntrinsicRelational(opr)) { + return AsMaybeExpr(Relate(context.GetContextualMessages(), opr, + analyzer.MoveExpr(0), analyzer.MoveExpr(1))); + } else { + return analyzer.TryDefinedOp(opr, + "Operands of %s must have comparable types; have %s and %s"_err_en_US); + } } } @@ -3014,6 +3019,18 @@ return i < actuals_.size() ? actuals_[i].value().Rank() : 0; } +// If the argument at index i is a BOZ liter, convert its type to an INTEGER +void ArgumentAnalyzer::ConvertBOZToInt(std::size_t i) { + if (IsBOZLiteral(i)) { + Expr &&argExpr{MoveExpr(i)}; + auto *boz{std::get_if(&argExpr.u)}; + MaybeExpr intExpr{ConvertToKind( + context_.context().GetDefaultKind(TypeCategory::Integer), + std::move(*boz))}; + actuals_[i] = std::move(*intExpr); + } +} + // Report error resolving opr when there is a user-defined one available void ArgumentAnalyzer::SayNoMatch(const std::string &opr, bool isAssignment) { std::string type0{TypeAsFortran(0)}; diff --git a/flang/test/Semantics/resolve63.f90 b/flang/test/Semantics/resolve63.f90 --- a/flang/test/Semantics/resolve63.f90 +++ b/flang/test/Semantics/resolve63.f90 @@ -44,10 +44,28 @@ type(t) :: x, y real :: r logical :: l + integer :: iVar + complex :: cvar + character :: charVar contains subroutine test_relational() l = x == y !OK l = x .eq. y !OK + l = x .eq. y !OK + l = iVar == z'fe' !OK + l = z'fe' == iVar !OK + l = r == z'fe' !OK + l = z'fe' == r !OK + l = cVar == z'fe' !OK + l = z'fe' == cVar !OK + !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types CHARACTER(KIND=1) and INTEGER(4) + l = charVar == z'fe' + !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types INTEGER(4) and CHARACTER(KIND=1) + l = z'fe' == charVar + !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types LOGICAL(4) and INTEGER(4) + l = l == z'fe' !OK + !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types INTEGER(4) and LOGICAL(4) + l = z'fe' == l !OK !ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types TYPE(t) and REAL(4) l = x == r end