[flang] Refine checks for intrinsic operator conflicts with CUDA defi… (#94389)
…ned operators The checks for conflicts between defined operators/assignments and the intrinsic operators/assignment need to take CUDA procedure and data attributes into account to avoid false positive error messages.
This commit is contained in:
parent
3ab6d12625
commit
0ee71124f4
@ -1887,11 +1887,34 @@ void CheckHelper::CheckSpecifics(
|
||||
helper.Check(generic.owner());
|
||||
}
|
||||
|
||||
static bool CUDAHostDeviceDiffer(
|
||||
const Procedure &proc, const DummyDataObject &arg) {
|
||||
auto procCUDA{
|
||||
proc.cudaSubprogramAttrs.value_or(common::CUDASubprogramAttrs::Host)};
|
||||
bool procIsHostOnly{procCUDA == common::CUDASubprogramAttrs::Host};
|
||||
bool procIsDeviceOnly{
|
||||
!procIsHostOnly && procCUDA != common::CUDASubprogramAttrs::HostDevice};
|
||||
const auto &argCUDA{arg.cudaDataAttr};
|
||||
bool argIsHostOnly{!argCUDA || *argCUDA == common::CUDADataAttr::Pinned};
|
||||
bool argIsDeviceOnly{(!argCUDA && procIsDeviceOnly) ||
|
||||
(argCUDA &&
|
||||
(*argCUDA != common::CUDADataAttr::Managed &&
|
||||
*argCUDA != common::CUDADataAttr::Pinned &&
|
||||
*argCUDA != common::CUDADataAttr::Unified))};
|
||||
return (procIsHostOnly && argIsDeviceOnly) ||
|
||||
(procIsDeviceOnly && argIsHostOnly);
|
||||
}
|
||||
|
||||
static bool ConflictsWithIntrinsicAssignment(const Procedure &proc) {
|
||||
auto lhs{std::get<DummyDataObject>(proc.dummyArguments[0].u).type};
|
||||
auto rhs{std::get<DummyDataObject>(proc.dummyArguments[1].u).type};
|
||||
return Tristate::No ==
|
||||
IsDefinedAssignment(lhs.type(), lhs.Rank(), rhs.type(), rhs.Rank());
|
||||
const auto &lhsData{std::get<DummyDataObject>(proc.dummyArguments[0].u)};
|
||||
const auto &lhsTnS{lhsData.type};
|
||||
const auto &rhsData{std::get<DummyDataObject>(proc.dummyArguments[1].u)};
|
||||
const auto &rhsTnS{rhsData.type};
|
||||
return !CUDAHostDeviceDiffer(proc, lhsData) &&
|
||||
!CUDAHostDeviceDiffer(proc, rhsData) &&
|
||||
Tristate::No ==
|
||||
IsDefinedAssignment(
|
||||
lhsTnS.type(), lhsTnS.Rank(), rhsTnS.type(), rhsTnS.Rank());
|
||||
}
|
||||
|
||||
static bool ConflictsWithIntrinsicOperator(
|
||||
@ -1899,8 +1922,12 @@ static bool ConflictsWithIntrinsicOperator(
|
||||
if (!kind.IsIntrinsicOperator()) {
|
||||
return false;
|
||||
}
|
||||
auto arg0{std::get<DummyDataObject>(proc.dummyArguments[0].u).type};
|
||||
auto type0{arg0.type()};
|
||||
const auto &arg0Data{std::get<DummyDataObject>(proc.dummyArguments[0].u)};
|
||||
if (CUDAHostDeviceDiffer(proc, arg0Data)) {
|
||||
return false;
|
||||
}
|
||||
const auto &arg0TnS{arg0Data.type};
|
||||
auto type0{arg0TnS.type()};
|
||||
if (proc.dummyArguments.size() == 1) { // unary
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
@ -1910,10 +1937,14 @@ static bool ConflictsWithIntrinsicOperator(
|
||||
},
|
||||
kind.u);
|
||||
} else { // binary
|
||||
int rank0{arg0.Rank()};
|
||||
auto arg1{std::get<DummyDataObject>(proc.dummyArguments[1].u).type};
|
||||
auto type1{arg1.type()};
|
||||
int rank1{arg1.Rank()};
|
||||
int rank0{arg0TnS.Rank()};
|
||||
const auto &arg1Data{std::get<DummyDataObject>(proc.dummyArguments[1].u)};
|
||||
if (CUDAHostDeviceDiffer(proc, arg1Data)) {
|
||||
return false;
|
||||
}
|
||||
const auto &arg1TnS{arg1Data.type};
|
||||
auto type1{arg1TnS.type()};
|
||||
int rank1{arg1TnS.Rank()};
|
||||
return common::visit(
|
||||
common::visitors{
|
||||
[&](common::NumericOperator) {
|
||||
@ -2087,8 +2118,8 @@ bool CheckHelper::CheckDefinedAssignment(
|
||||
if (!(ok0 && ok1)) {
|
||||
return false; // error was reported
|
||||
} else if (ConflictsWithIntrinsicAssignment(proc)) {
|
||||
msg = "Defined assignment subroutine '%s' conflicts with"
|
||||
" intrinsic assignment"_err_en_US;
|
||||
msg =
|
||||
"Defined assignment subroutine '%s' conflicts with intrinsic assignment"_err_en_US;
|
||||
} else {
|
||||
return true; // OK
|
||||
}
|
||||
|
||||
95
flang/test/Semantics/cuf16.cuf
Normal file
95
flang/test/Semantics/cuf16.cuf
Normal file
@ -0,0 +1,95 @@
|
||||
! RUN: %python %S/test_errors.py %s %flang_fc1
|
||||
module m
|
||||
interface operator(-)
|
||||
!ERROR: OPERATOR(-) function 'f1' conflicts with intrinsic operator
|
||||
function f1(x)
|
||||
real, intent(in) :: x
|
||||
end
|
||||
!ERROR: OPERATOR(-) function 'f2' conflicts with intrinsic operator
|
||||
attributes(device) function f2(x)
|
||||
real, intent(in), device :: x(:)
|
||||
end
|
||||
function f3(x) ! ok
|
||||
real, intent(in), device :: x(:,:)
|
||||
end
|
||||
!ERROR: OPERATOR(-) function 'f4' conflicts with intrinsic operator
|
||||
attributes(device) function f4(x)
|
||||
real, intent(in) :: x(:,:,:)
|
||||
end
|
||||
!ERROR: OPERATOR(-) function 'f5' conflicts with intrinsic operator
|
||||
function f5(x)
|
||||
real, intent(in), unified :: x(:,:,:,:)
|
||||
end
|
||||
!ERROR: OPERATOR(-) function 'f6' conflicts with intrinsic operator
|
||||
attributes(device) function f6(x)
|
||||
real, intent(in), managed :: x(:,:,:,:,:)
|
||||
end
|
||||
end interface
|
||||
interface operator(*)
|
||||
!ERROR: OPERATOR(*) function 'f11' conflicts with intrinsic operator
|
||||
function f11(x, y)
|
||||
real, intent(in) :: x, y
|
||||
end
|
||||
!ERROR: OPERATOR(*) function 'f12' conflicts with intrinsic operator
|
||||
attributes(device) function f12(x, y)
|
||||
real, intent(in), device :: x, y(:)
|
||||
end
|
||||
!ERROR: OPERATOR(*) function 'f13' conflicts with intrinsic operator
|
||||
attributes(device) function f13(x, y)
|
||||
real, intent(in) :: x(:), y
|
||||
end
|
||||
function f14a(x, y) ! ok
|
||||
real, intent(in), device :: x(:)
|
||||
real, intent(in) :: y(:)
|
||||
end
|
||||
function f14b(x, y) ! ok
|
||||
real, intent(in) :: x
|
||||
real, intent(in), device :: y(:,:)
|
||||
end
|
||||
!ERROR: OPERATOR(*) function 'f15' conflicts with intrinsic operator
|
||||
function f15(x, y)
|
||||
real, intent(in) :: x(:,:)
|
||||
real, intent(in), unified :: y
|
||||
end
|
||||
!ERROR: OPERATOR(*) function 'f16' conflicts with intrinsic operator
|
||||
attributes(device) function f16(x, y)
|
||||
real, intent(in), device :: x(:,:)
|
||||
real, intent(in), managed :: y(:,:)
|
||||
end
|
||||
end interface
|
||||
interface assignment(=)
|
||||
!ERROR: Defined assignment subroutine 's1' conflicts with intrinsic assignment
|
||||
subroutine s1(x, y)
|
||||
real, intent(in out) :: x
|
||||
real, intent(in) :: y
|
||||
end
|
||||
!ERROR: Defined assignment subroutine 's2' conflicts with intrinsic assignment
|
||||
attributes(device) subroutine s2(x, y)
|
||||
real, intent(in out), device :: x(:)
|
||||
real, intent(in), device :: y
|
||||
end
|
||||
!ERROR: Defined assignment subroutine 's3' conflicts with intrinsic assignment
|
||||
attributes(device) subroutine s3(x, y)
|
||||
real, intent(in out) :: x(:)
|
||||
real, intent(in) :: y(:)
|
||||
end
|
||||
subroutine s4a(x, y) ! ok
|
||||
real, intent(in out), device :: x(:,:)
|
||||
real, intent(in) :: y
|
||||
end
|
||||
subroutine s4b(x, y) ! ok
|
||||
real, intent(in out) :: x(:,:)
|
||||
real, intent(in), device :: y(:,:)
|
||||
end
|
||||
!ERROR: Defined assignment subroutine 's5' conflicts with intrinsic assignment
|
||||
subroutine s5(x, y)
|
||||
real, intent(in out) :: x(:,:,:)
|
||||
real, intent(in), unified :: y
|
||||
end
|
||||
!ERROR: Defined assignment subroutine 's6' conflicts with intrinsic assignment
|
||||
attributes(device) subroutine s6(x, y)
|
||||
real, intent(in out), device :: x(:,:,:)
|
||||
real, intent(in), managed :: y(:,:,:)
|
||||
end
|
||||
end interface
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user