@@ -42,6 +42,7 @@ class AssignmentContext {
42
42
void Analyze (const parser::AssignmentStmt &);
43
43
void Analyze (const parser::PointerAssignmentStmt &);
44
44
void Analyze (const parser::ConcurrentControl &);
45
+ int deviceConstructDepth_{0 };
45
46
46
47
private:
47
48
bool CheckForPureContext (const SomeExpr &rhs, parser::CharBlock rhsSource);
@@ -94,7 +95,7 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
94
95
common::LanguageFeature::CUDA)) {
95
96
const auto &scope{context_.FindScope (lhsLoc)};
96
97
const Scope &progUnit{GetProgramUnitContaining (scope)};
97
- if (!IsCUDADeviceContext (&progUnit)) {
98
+ if (!IsCUDADeviceContext (&progUnit) && deviceConstructDepth_ == 0 ) {
98
99
if (Fortran::evaluate::HasCUDADeviceAttrs (lhs) &&
99
100
Fortran::evaluate::HasCUDAImplicitTransfer (rhs)) {
100
101
context_.Say (lhsLoc, " Unsupported CUDA data transfer" _err_en_US);
@@ -228,6 +229,46 @@ void AssignmentChecker::Enter(const parser::MaskedElsewhereStmt &x) {
228
229
void AssignmentChecker::Leave (const parser::MaskedElsewhereStmt &) {
229
230
context_.value ().PopWhereContext ();
230
231
}
232
+ void AssignmentChecker::Enter (const parser::CUFKernelDoConstruct &x) {
233
+ ++context_.value ().deviceConstructDepth_ ;
234
+ }
235
+ void AssignmentChecker::Leave (const parser::CUFKernelDoConstruct &) {
236
+ --context_.value ().deviceConstructDepth_ ;
237
+ }
238
+ static bool IsOpenACCComputeConstruct (const parser::OpenACCBlockConstruct &x) {
239
+ const auto &beginBlockDirective =
240
+ std::get<Fortran::parser::AccBeginBlockDirective>(x.t );
241
+ const auto &blockDirective =
242
+ std::get<Fortran::parser::AccBlockDirective>(beginBlockDirective.t );
243
+ if (blockDirective.v == llvm::acc::ACCD_parallel ||
244
+ blockDirective.v == llvm::acc::ACCD_serial ||
245
+ blockDirective.v == llvm::acc::ACCD_kernels) {
246
+ return true ;
247
+ }
248
+ return false ;
249
+ }
250
+ void AssignmentChecker::Enter (const parser::OpenACCBlockConstruct &x) {
251
+ if (IsOpenACCComputeConstruct (x)) {
252
+ ++context_.value ().deviceConstructDepth_ ;
253
+ }
254
+ }
255
+ void AssignmentChecker::Leave (const parser::OpenACCBlockConstruct &x) {
256
+ if (IsOpenACCComputeConstruct (x)) {
257
+ --context_.value ().deviceConstructDepth_ ;
258
+ }
259
+ }
260
+ void AssignmentChecker::Enter (const parser::OpenACCCombinedConstruct &) {
261
+ ++context_.value ().deviceConstructDepth_ ;
262
+ }
263
+ void AssignmentChecker::Leave (const parser::OpenACCCombinedConstruct &) {
264
+ --context_.value ().deviceConstructDepth_ ;
265
+ }
266
+ void AssignmentChecker::Enter (const parser::OpenACCLoopConstruct &) {
267
+ ++context_.value ().deviceConstructDepth_ ;
268
+ }
269
+ void AssignmentChecker::Leave (const parser::OpenACCLoopConstruct &) {
270
+ --context_.value ().deviceConstructDepth_ ;
271
+ }
231
272
232
273
} // namespace Fortran::semantics
233
274
template class Fortran ::common::Indirection<
0 commit comments