@@ -42,6 +42,7 @@ class AssignmentContext {
4242 void Analyze (const parser::AssignmentStmt &);
4343 void Analyze (const parser::PointerAssignmentStmt &);
4444 void Analyze (const parser::ConcurrentControl &);
45+ int deviceConstructDepth_{0 };
4546
4647private:
4748 bool CheckForPureContext (const SomeExpr &rhs, parser::CharBlock rhsSource);
@@ -94,7 +95,7 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
9495 common::LanguageFeature::CUDA)) {
9596 const auto &scope{context_.FindScope (lhsLoc)};
9697 const Scope &progUnit{GetProgramUnitContaining (scope)};
97- if (!IsCUDADeviceContext (&progUnit)) {
98+ if (!IsCUDADeviceContext (&progUnit) && deviceConstructDepth_ == 0 ) {
9899 if (Fortran::evaluate::HasCUDADeviceAttrs (lhs) &&
99100 Fortran::evaluate::HasCUDAImplicitTransfer (rhs)) {
100101 context_.Say (lhsLoc, " Unsupported CUDA data transfer" _err_en_US);
@@ -228,6 +229,46 @@ void AssignmentChecker::Enter(const parser::MaskedElsewhereStmt &x) {
228229void AssignmentChecker::Leave (const parser::MaskedElsewhereStmt &) {
229230 context_.value ().PopWhereContext ();
230231}
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+ }
231272
232273} // namespace Fortran::semantics
233274template class Fortran ::common::Indirection<
0 commit comments