diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index ce24321e2961..177082d6af08 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -70,6 +70,7 @@ static bool FileContentsMatch( const std::string &, const std::string &, const std::string &); static ModuleCheckSumType ComputeCheckSum(const std::string_view &); static std::string CheckSumString(ModuleCheckSumType); +static bool ScopeHasCUDAModuleVariables(const Scope &); // Collect symbols needed for a subprogram interface class SubprogramSymbolCollector { @@ -1820,6 +1821,14 @@ Scope *ModFileReader::Read(SourceName name, std::optional isIntrinsic, if (isIntrinsic.value_or(false)) { moduleSymbol->attrs().set(Attr::INTRINSIC); } + if (context_.languageFeatures().IsEnabled( + common::LanguageFeature::OpenACC) && + !context_.languageFeatures().IsEnabled(common::LanguageFeature::CUDA) && + ScopeHasCUDAModuleVariables(*moduleSymbol->scope())) { + Say("use", name, ancestorName, + "CUDA is not enabled, but '%s' defines CUDA symbols"_err_en_US, + sourceFile->path()); + } return moduleSymbol->scope(); } else { return nullptr; @@ -1855,6 +1864,25 @@ static std::optional GetSubmoduleParent( } } +static bool ScopeHasCUDAModuleVariables(const Scope &scope) { + for (const auto &[_, symbolRef] : scope) { + const Symbol &symbol{*symbolRef}; + if (const auto *object{symbol.detailsIf()}) { + if (object->cudaDataAttr()) { + return true; + } + const DeclTypeSpec *type{object->type()}; + const DerivedTypeSpec *derived{type ? type->AsDerived() : nullptr}; + if (derived && + FindUltimateComponent(*derived, + [](const Symbol &component) { return HasCUDAAttr(component); })) { + return true; + } + } + } + return false; +} + void SubprogramSymbolCollector::Collect() { const auto &details{symbol_.get()}; isInterface_ = details.isInterface(); diff --git a/flang/test/Semantics/modfile84.f90 b/flang/test/Semantics/modfile84.f90 new file mode 100644 index 000000000000..ca09ed2e509e --- /dev/null +++ b/flang/test/Semantics/modfile84.f90 @@ -0,0 +1,46 @@ +! RUN: split-file %s %t +! RUN: %flang_fc1 -fsyntax-only -x cuda -module-dir %t %t/m.cuf +! RUN: not %flang_fc1 -fsyntax-only -fopenacc -module-dir %t %t/use.f90 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fsyntax-only -x cuda -module-dir %t %t/m2.cuf +! RUN: %flang_fc1 -fsyntax-only -fopenacc -module-dir %t %t/use2.f90 +! RUN: %flang_fc1 -fsyntax-only -x cuda -module-dir %t %t/m3.cuf +! RUN: not %flang_fc1 -fsyntax-only -fopenacc -module-dir %t %t/use3.f90 2>&1 | FileCheck --check-prefix=CHECK-M3 %s + +!--- m.cuf +module modfile84m + real, device :: d +contains + attributes(device) subroutine s() + end subroutine +end module + +!--- m2.cuf +module modfile84m2 +contains + attributes(device) subroutine s() + end subroutine +end module + +!--- m3.cuf +module modfile84m3 + type dt + real, device, pointer :: dp + end type + + type(dt) :: d ! Should trigger the error +end module + +!--- use.f90 +use modfile84m +end + +!--- use2.f90 +use modfile84m2 +end + +!--- use3.f90 +use modfile84m3 +end + +! CHECK: error: Cannot use module file for module 'modfile84m': CUDA is not enabled, but '{{.*modfile84m.mod}}' defines CUDA symbols +! CHECK-M3: error: Cannot use module file for module 'modfile84m3': CUDA is not enabled, but '{{.*modfile84m3.mod}}' defines CUDA symbols