Skip to content

Commit 0ee7112

Browse files
authored
[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.
1 parent 3ab6d12 commit 0ee7112

File tree

2 files changed

+138
-12
lines changed

2 files changed

+138
-12
lines changed

flang/lib/Semantics/check-declarations.cpp

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,20 +1887,47 @@ void CheckHelper::CheckSpecifics(
18871887
helper.Check(generic.owner());
18881888
}
18891889

1890+
static bool CUDAHostDeviceDiffer(
1891+
const Procedure &proc, const DummyDataObject &arg) {
1892+
auto procCUDA{
1893+
proc.cudaSubprogramAttrs.value_or(common::CUDASubprogramAttrs::Host)};
1894+
bool procIsHostOnly{procCUDA == common::CUDASubprogramAttrs::Host};
1895+
bool procIsDeviceOnly{
1896+
!procIsHostOnly && procCUDA != common::CUDASubprogramAttrs::HostDevice};
1897+
const auto &argCUDA{arg.cudaDataAttr};
1898+
bool argIsHostOnly{!argCUDA || *argCUDA == common::CUDADataAttr::Pinned};
1899+
bool argIsDeviceOnly{(!argCUDA && procIsDeviceOnly) ||
1900+
(argCUDA &&
1901+
(*argCUDA != common::CUDADataAttr::Managed &&
1902+
*argCUDA != common::CUDADataAttr::Pinned &&
1903+
*argCUDA != common::CUDADataAttr::Unified))};
1904+
return (procIsHostOnly && argIsDeviceOnly) ||
1905+
(procIsDeviceOnly && argIsHostOnly);
1906+
}
1907+
18901908
static bool ConflictsWithIntrinsicAssignment(const Procedure &proc) {
1891-
auto lhs{std::get<DummyDataObject>(proc.dummyArguments[0].u).type};
1892-
auto rhs{std::get<DummyDataObject>(proc.dummyArguments[1].u).type};
1893-
return Tristate::No ==
1894-
IsDefinedAssignment(lhs.type(), lhs.Rank(), rhs.type(), rhs.Rank());
1909+
const auto &lhsData{std::get<DummyDataObject>(proc.dummyArguments[0].u)};
1910+
const auto &lhsTnS{lhsData.type};
1911+
const auto &rhsData{std::get<DummyDataObject>(proc.dummyArguments[1].u)};
1912+
const auto &rhsTnS{rhsData.type};
1913+
return !CUDAHostDeviceDiffer(proc, lhsData) &&
1914+
!CUDAHostDeviceDiffer(proc, rhsData) &&
1915+
Tristate::No ==
1916+
IsDefinedAssignment(
1917+
lhsTnS.type(), lhsTnS.Rank(), rhsTnS.type(), rhsTnS.Rank());
18951918
}
18961919

18971920
static bool ConflictsWithIntrinsicOperator(
18981921
const GenericKind &kind, const Procedure &proc) {
18991922
if (!kind.IsIntrinsicOperator()) {
19001923
return false;
19011924
}
1902-
auto arg0{std::get<DummyDataObject>(proc.dummyArguments[0].u).type};
1903-
auto type0{arg0.type()};
1925+
const auto &arg0Data{std::get<DummyDataObject>(proc.dummyArguments[0].u)};
1926+
if (CUDAHostDeviceDiffer(proc, arg0Data)) {
1927+
return false;
1928+
}
1929+
const auto &arg0TnS{arg0Data.type};
1930+
auto type0{arg0TnS.type()};
19041931
if (proc.dummyArguments.size() == 1) { // unary
19051932
return common::visit(
19061933
common::visitors{
@@ -1910,10 +1937,14 @@ static bool ConflictsWithIntrinsicOperator(
19101937
},
19111938
kind.u);
19121939
} else { // binary
1913-
int rank0{arg0.Rank()};
1914-
auto arg1{std::get<DummyDataObject>(proc.dummyArguments[1].u).type};
1915-
auto type1{arg1.type()};
1916-
int rank1{arg1.Rank()};
1940+
int rank0{arg0TnS.Rank()};
1941+
const auto &arg1Data{std::get<DummyDataObject>(proc.dummyArguments[1].u)};
1942+
if (CUDAHostDeviceDiffer(proc, arg1Data)) {
1943+
return false;
1944+
}
1945+
const auto &arg1TnS{arg1Data.type};
1946+
auto type1{arg1TnS.type()};
1947+
int rank1{arg1TnS.Rank()};
19171948
return common::visit(
19181949
common::visitors{
19191950
[&](common::NumericOperator) {
@@ -2087,8 +2118,8 @@ bool CheckHelper::CheckDefinedAssignment(
20872118
if (!(ok0 && ok1)) {
20882119
return false; // error was reported
20892120
} else if (ConflictsWithIntrinsicAssignment(proc)) {
2090-
msg = "Defined assignment subroutine '%s' conflicts with"
2091-
" intrinsic assignment"_err_en_US;
2121+
msg =
2122+
"Defined assignment subroutine '%s' conflicts with intrinsic assignment"_err_en_US;
20922123
} else {
20932124
return true; // OK
20942125
}

flang/test/Semantics/cuf16.cuf

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
module m
3+
interface operator(-)
4+
!ERROR: OPERATOR(-) function 'f1' conflicts with intrinsic operator
5+
function f1(x)
6+
real, intent(in) :: x
7+
end
8+
!ERROR: OPERATOR(-) function 'f2' conflicts with intrinsic operator
9+
attributes(device) function f2(x)
10+
real, intent(in), device :: x(:)
11+
end
12+
function f3(x) ! ok
13+
real, intent(in), device :: x(:,:)
14+
end
15+
!ERROR: OPERATOR(-) function 'f4' conflicts with intrinsic operator
16+
attributes(device) function f4(x)
17+
real, intent(in) :: x(:,:,:)
18+
end
19+
!ERROR: OPERATOR(-) function 'f5' conflicts with intrinsic operator
20+
function f5(x)
21+
real, intent(in), unified :: x(:,:,:,:)
22+
end
23+
!ERROR: OPERATOR(-) function 'f6' conflicts with intrinsic operator
24+
attributes(device) function f6(x)
25+
real, intent(in), managed :: x(:,:,:,:,:)
26+
end
27+
end interface
28+
interface operator(*)
29+
!ERROR: OPERATOR(*) function 'f11' conflicts with intrinsic operator
30+
function f11(x, y)
31+
real, intent(in) :: x, y
32+
end
33+
!ERROR: OPERATOR(*) function 'f12' conflicts with intrinsic operator
34+
attributes(device) function f12(x, y)
35+
real, intent(in), device :: x, y(:)
36+
end
37+
!ERROR: OPERATOR(*) function 'f13' conflicts with intrinsic operator
38+
attributes(device) function f13(x, y)
39+
real, intent(in) :: x(:), y
40+
end
41+
function f14a(x, y) ! ok
42+
real, intent(in), device :: x(:)
43+
real, intent(in) :: y(:)
44+
end
45+
function f14b(x, y) ! ok
46+
real, intent(in) :: x
47+
real, intent(in), device :: y(:,:)
48+
end
49+
!ERROR: OPERATOR(*) function 'f15' conflicts with intrinsic operator
50+
function f15(x, y)
51+
real, intent(in) :: x(:,:)
52+
real, intent(in), unified :: y
53+
end
54+
!ERROR: OPERATOR(*) function 'f16' conflicts with intrinsic operator
55+
attributes(device) function f16(x, y)
56+
real, intent(in), device :: x(:,:)
57+
real, intent(in), managed :: y(:,:)
58+
end
59+
end interface
60+
interface assignment(=)
61+
!ERROR: Defined assignment subroutine 's1' conflicts with intrinsic assignment
62+
subroutine s1(x, y)
63+
real, intent(in out) :: x
64+
real, intent(in) :: y
65+
end
66+
!ERROR: Defined assignment subroutine 's2' conflicts with intrinsic assignment
67+
attributes(device) subroutine s2(x, y)
68+
real, intent(in out), device :: x(:)
69+
real, intent(in), device :: y
70+
end
71+
!ERROR: Defined assignment subroutine 's3' conflicts with intrinsic assignment
72+
attributes(device) subroutine s3(x, y)
73+
real, intent(in out) :: x(:)
74+
real, intent(in) :: y(:)
75+
end
76+
subroutine s4a(x, y) ! ok
77+
real, intent(in out), device :: x(:,:)
78+
real, intent(in) :: y
79+
end
80+
subroutine s4b(x, y) ! ok
81+
real, intent(in out) :: x(:,:)
82+
real, intent(in), device :: y(:,:)
83+
end
84+
!ERROR: Defined assignment subroutine 's5' conflicts with intrinsic assignment
85+
subroutine s5(x, y)
86+
real, intent(in out) :: x(:,:,:)
87+
real, intent(in), unified :: y
88+
end
89+
!ERROR: Defined assignment subroutine 's6' conflicts with intrinsic assignment
90+
attributes(device) subroutine s6(x, y)
91+
real, intent(in out), device :: x(:,:,:)
92+
real, intent(in), managed :: y(:,:,:)
93+
end
94+
end interface
95+
end

0 commit comments

Comments
 (0)