@@ -2828,6 +2828,16 @@ Scope &ScopeHandler::NonDerivedTypeScope() {
28282828 return currScope_->IsDerivedType () ? currScope_->parent () : *currScope_;
28292829}
28302830
2831+ static void SetImplicitCUDADevice (Symbol &symbol) {
2832+ if (auto *object{symbol.detailsIf <ObjectEntityDetails>()}) {
2833+ if (!object->cudaDataAttr () && !IsValue (symbol) &&
2834+ !IsFunctionResult (symbol)) {
2835+ // Implicitly set device attribute if none is set in device context.
2836+ object->set_cudaDataAttr (common::CUDADataAttr::Device);
2837+ }
2838+ }
2839+ }
2840+
28312841void ScopeHandler::PushScope (Scope::Kind kind, Symbol *symbol) {
28322842 PushScope (currScope ().MakeScope (kind, symbol));
28332843}
@@ -2867,9 +2877,35 @@ void ScopeHandler::PopScope() {
28672877 // Entities that are not yet classified as objects or procedures are now
28682878 // assumed to be objects.
28692879 // TODO: Statement functions
2880+ bool inDeviceSubprogram{false };
2881+ const Symbol *scopeSym{currScope ().GetSymbol ()};
2882+ if (currScope ().kind () == Scope::Kind::BlockConstruct) {
2883+ scopeSym = GetProgramUnitContaining (currScope ()).GetSymbol ();
2884+ }
2885+ if (scopeSym) {
2886+ if (auto *details{scopeSym->detailsIf <SubprogramDetails>()}) {
2887+ // Check the current procedure is a device procedure to apply implicit
2888+ // attribute at the end.
2889+ if (auto attrs{details->cudaSubprogramAttrs ()}) {
2890+ if (*attrs == common::CUDASubprogramAttrs::Device ||
2891+ *attrs == common::CUDASubprogramAttrs::Global ||
2892+ *attrs == common::CUDASubprogramAttrs::Grid_Global) {
2893+ inDeviceSubprogram = true ;
2894+ }
2895+ }
2896+ }
2897+ }
28702898 for (auto &pair : currScope ()) {
28712899 ConvertToObjectEntity (*pair.second );
28722900 }
2901+
2902+ // Apply CUDA device attributes if in a device subprogram
2903+ if (inDeviceSubprogram && currScope ().kind () == Scope::Kind::BlockConstruct) {
2904+ for (auto &pair : currScope ()) {
2905+ SetImplicitCUDADevice (*pair.second );
2906+ }
2907+ }
2908+
28732909 funcResultStack_.Pop ();
28742910 // If popping back into a global scope, pop back to the top scope.
28752911 Scope *hermetic{context ().currentHermeticModuleFileScope ()};
@@ -9555,40 +9591,11 @@ void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) {
95559591 info.Resolve (&MakeSymbol (symbolName, Attrs{}, std::move (genericDetails)));
95569592}
95579593
9558- static void SetImplicitCUDADevice (bool inDeviceSubprogram, Symbol &symbol) {
9559- if (inDeviceSubprogram && symbol.has <ObjectEntityDetails>()) {
9560- auto *object{symbol.detailsIf <ObjectEntityDetails>()};
9561- if (!object->cudaDataAttr () && !IsValue (symbol) &&
9562- !IsFunctionResult (symbol)) {
9563- // Implicitly set device attribute if none is set in device context.
9564- object->set_cudaDataAttr (common::CUDADataAttr::Device);
9565- }
9566- }
9567- }
9568-
95699594void ResolveNamesVisitor::FinishSpecificationPart (
95709595 const std::list<parser::DeclarationConstruct> &decls) {
95719596 misparsedStmtFuncFound_ = false ;
95729597 funcResultStack ().CompleteFunctionResultType ();
95739598 CheckImports ();
9574- bool inDeviceSubprogram{false };
9575- Symbol *scopeSym{currScope ().symbol ()};
9576- if (currScope ().kind () == Scope::Kind::BlockConstruct) {
9577- scopeSym = currScope ().parent ().symbol ();
9578- }
9579- if (scopeSym) {
9580- if (auto *details{scopeSym->detailsIf <SubprogramDetails>()}) {
9581- // Check the current procedure is a device procedure to apply implicit
9582- // attribute at the end.
9583- if (auto attrs{details->cudaSubprogramAttrs ()}) {
9584- if (*attrs == common::CUDASubprogramAttrs::Device ||
9585- *attrs == common::CUDASubprogramAttrs::Global ||
9586- *attrs == common::CUDASubprogramAttrs::Grid_Global) {
9587- inDeviceSubprogram = true ;
9588- }
9589- }
9590- }
9591- }
95929599 for (auto &pair : currScope ()) {
95939600 auto &symbol{*pair.second };
95949601 if (inInterfaceBlock ()) {
@@ -9623,11 +9630,6 @@ void ResolveNamesVisitor::FinishSpecificationPart(
96239630 SetBindNameOn (symbol);
96249631 }
96259632 }
9626- if (currScope ().kind () == Scope::Kind::BlockConstruct) {
9627- // Only look for specification in BlockConstruct. Other cases are done in
9628- // ResolveSpecificationParts.
9629- SetImplicitCUDADevice (inDeviceSubprogram, symbol);
9630- }
96319633 }
96329634 currScope ().InstantiateDerivedTypes ();
96339635 for (const auto &decl : decls) {
@@ -10187,7 +10189,9 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {
1018710189 }
1018810190 ApplyImplicitRules (symbol);
1018910191 // Apply CUDA implicit attributes if needed.
10190- SetImplicitCUDADevice (inDeviceSubprogram, symbol);
10192+ if (inDeviceSubprogram) {
10193+ SetImplicitCUDADevice (symbol);
10194+ }
1019110195 // Main program local objects usually don't have an implied SAVE attribute,
1019210196 // as one might think, but in the exceptional case of a derived type
1019310197 // local object that contains a coarray, we have to mark it as an
0 commit comments