mirror of
https://github.com/intel/llvm.git
synced 2026-01-27 06:06:34 +08:00
[flang] Parenthesize RHS arguments to defined assignments (bug #62599)
The right-hand sides of assignment statements are always expressions, never variables. When an assignment statement is converted into a call to a defined assignment subroutine, and the actual argument being associated with the second dummy argument is a variable, and the dummy argument does not have the VALUE attribute, wrap it with parentheses so that lowering will pass it by means of a temporary. Fixes https://github.com/llvm/llvm-project/issues/62599. Differential Revision: https://reviews.llvm.org/D150331
This commit is contained in:
@@ -4067,7 +4067,7 @@ bool ArgumentAnalyzer::OkLogicalIntegerAssignment(
|
||||
|
||||
std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
|
||||
const Symbol *proc{nullptr};
|
||||
int passedObjectIndex{-1};
|
||||
std::optional<int> passedObjectIndex;
|
||||
std::string oprNameString{"assignment(=)"};
|
||||
parser::CharBlock oprName{oprNameString};
|
||||
const auto &scope{context_.context().FindScope(source_)};
|
||||
@@ -4099,8 +4099,23 @@ std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
|
||||
return std::nullopt;
|
||||
}
|
||||
ActualArguments actualsCopy{actuals_};
|
||||
if (passedObjectIndex >= 0) {
|
||||
actualsCopy[passedObjectIndex]->set_isPassedObject();
|
||||
// Ensure that the RHS argument is not passed as a variable unless
|
||||
// the dummy argument has the VALUE attribute.
|
||||
if (evaluate::IsVariable(actualsCopy.at(1).value().UnwrapExpr())) {
|
||||
auto chars{evaluate::characteristics::Procedure::Characterize(
|
||||
*proc, context_.GetFoldingContext())};
|
||||
const auto *rhsDummy{chars && chars->dummyArguments.size() == 2
|
||||
? std::get_if<evaluate::characteristics::DummyDataObject>(
|
||||
&chars->dummyArguments.at(1).u)
|
||||
: nullptr};
|
||||
if (!rhsDummy ||
|
||||
!rhsDummy->attrs.test(
|
||||
evaluate::characteristics::DummyDataObject::Attr::Value)) {
|
||||
actualsCopy.at(1).value().Parenthesize();
|
||||
}
|
||||
}
|
||||
if (passedObjectIndex) {
|
||||
actualsCopy[*passedObjectIndex]->set_isPassedObject();
|
||||
}
|
||||
return ProcedureRef{ProcedureDesignator{*proc}, std::move(actualsCopy)};
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,10 @@ subroutine user_assignment(a, i)
|
||||
end subroutine
|
||||
end interface
|
||||
type(t) :: a
|
||||
! CHECK: fir.call @_QPmy_assign(%[[arg0]], %[[arg1]])
|
||||
! CHECK: %[[V_0:[0-9]+]] = fir.alloca i32
|
||||
! CHECK: %[[V_1:[0-9]+]] = fir.load %arg1 : !fir.ref<i32>
|
||||
! CHECK: %[[V_2:[0-9]+]] = fir.no_reassoc %[[V_1:[0-9]+]] : i32
|
||||
! CHECK: fir.store %[[V_2]] to %[[V_0:[0-9]+]] : !fir.ref<i32>
|
||||
! CHECK: fir.call @_QPmy_assign(%arg0, %[[V_0]]) fastmath<contract> : (!fir.ref<!fir.type<_QFuser_assignmentTt{x:f32,i:i32}>>, !fir.ref<i32>) -> ()
|
||||
a = i
|
||||
end subroutine
|
||||
|
||||
@@ -13,7 +13,7 @@ module m1
|
||||
contains
|
||||
subroutine s1(x, y)
|
||||
class(t), intent(out) :: x
|
||||
integer, intent(in) :: y
|
||||
integer, intent(in), value :: y
|
||||
end
|
||||
subroutine s2(x, y)
|
||||
real, intent(out) :: x
|
||||
@@ -22,9 +22,13 @@ contains
|
||||
subroutine test1(x)
|
||||
type(t) :: x
|
||||
real :: a
|
||||
integer :: j
|
||||
!CHECK: CALL s1(x,1_4)
|
||||
x = 1
|
||||
!CHECK: CALL s2(a,x)
|
||||
j = 1
|
||||
!CHECK: CALL s1(x,j)
|
||||
x = j ! no parentheses due to VALUE
|
||||
!CHECK: CALL s2(a,(x))
|
||||
a = x
|
||||
end
|
||||
subroutine test2(x)
|
||||
@@ -32,7 +36,7 @@ contains
|
||||
real :: a
|
||||
!CHECK: CALL x%b1(1_4)
|
||||
x = 1
|
||||
!CHECK: CALL x%b2(a)
|
||||
!CHECK: CALL (x)%b2(a)
|
||||
a = x
|
||||
end
|
||||
end
|
||||
@@ -73,6 +77,10 @@ module m3
|
||||
real, intent(out) :: x
|
||||
class(*), intent(in) :: y
|
||||
end
|
||||
subroutine s3(x, y)
|
||||
integer, intent(out) :: x
|
||||
class(*), intent(in), value :: y
|
||||
end
|
||||
end interface
|
||||
interface operator(+)
|
||||
integer function f(x, y)
|
||||
@@ -89,7 +97,9 @@ contains
|
||||
x = 2
|
||||
!CHECK: i=f(x,y)
|
||||
i = x + y
|
||||
!CHECK: CALL s2(a,z)
|
||||
!CHECK: CALL s2(a,(z))
|
||||
a = z
|
||||
!CHECK: CALL s3(i,z)
|
||||
i = z
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user