@@ -736,6 +736,8 @@ class ScopeHandler : public ImplicitRulesVisitor {
736736 std::vector<const std::list<parser::EquivalenceObject> *> equivalenceSets;
737737 // Names of all common block objects in the scope
738738 std::set<SourceName> commonBlockObjects;
739+ // Names of all names that show in a declare target declaration
740+ std::set<SourceName> declareTargetNames;
739741 // Info about SAVE statements and attributes in current scope
740742 struct {
741743 std::optional<SourceName> saveAll; // "SAVE" without entity list
@@ -1223,6 +1225,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
12231225 const parser::Name *FindComponent (const parser::Name *, const parser::Name &);
12241226 void Initialization (const parser::Name &, const parser::Initialization &,
12251227 bool inComponentDecl);
1228+ bool FindAndMarkDeclareTargetSymbol (const parser::Name &);
12261229 bool PassesLocalityChecks (
12271230 const parser::Name &name, Symbol &symbol, Symbol::Flag flag);
12281231 bool CheckForHostAssociatedImplicit (const parser::Name &);
@@ -1524,7 +1527,47 @@ class OmpVisitor : public virtual DeclarationVisitor {
15241527 return true ;
15251528 }
15261529 void Post (const parser::OpenMPThreadprivate &) { SkipImplicitTyping (false ); }
1527- bool Pre (const parser::OpenMPDeclareTargetConstruct &) {
1530+ bool Pre (const parser::OpenMPDeclareTargetConstruct &x) {
1531+ const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t )};
1532+ auto populateDeclareTargetNames{
1533+ [this ](const parser::OmpObjectList &objectList) {
1534+ for (const auto &ompObject : objectList.v ) {
1535+ common::visit (
1536+ common::visitors{
1537+ [&](const parser::Designator &designator) {
1538+ if (const auto *name{
1539+ semantics::getDesignatorNameIfDataRef (
1540+ designator)}) {
1541+ specPartState_.declareTargetNames .insert (name->source );
1542+ }
1543+ },
1544+ [&](const parser::Name &name) {
1545+ specPartState_.declareTargetNames .insert (name.source );
1546+ },
1547+ },
1548+ ompObject.u );
1549+ }
1550+ }};
1551+
1552+ if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u )}) {
1553+ populateDeclareTargetNames (*objectList);
1554+ } else if (const auto *clauseList{
1555+ parser::Unwrap<parser::OmpClauseList>(spec.u )}) {
1556+ for (const auto &clause : clauseList->v ) {
1557+ if (const auto *toClause{
1558+ std::get_if<parser::OmpClause::To>(&clause.u )}) {
1559+ populateDeclareTargetNames (
1560+ std::get<parser::OmpObjectList>(toClause->v .t ));
1561+ } else if (const auto *linkClause{
1562+ std::get_if<parser::OmpClause::Link>(&clause.u )}) {
1563+ populateDeclareTargetNames (linkClause->v );
1564+ } else if (const auto *enterClause{
1565+ std::get_if<parser::OmpClause::Enter>(&clause.u )}) {
1566+ populateDeclareTargetNames (enterClause->v );
1567+ }
1568+ }
1569+ }
1570+
15281571 SkipImplicitTyping (true );
15291572 return true ;
15301573 }
@@ -8126,7 +8169,12 @@ const parser::Name *DeclarationVisitor::ResolveDataRef(
81268169// If implicit types are allowed, ensure name is in the symbol table.
81278170// Otherwise, report an error if it hasn't been declared.
81288171const parser::Name *DeclarationVisitor::ResolveName (const parser::Name &name) {
8129- FindSymbol (name);
8172+ if (!FindSymbol (name)) {
8173+ if (FindAndMarkDeclareTargetSymbol (name)) {
8174+ return &name;
8175+ }
8176+ }
8177+
81308178 if (CheckForHostAssociatedImplicit (name)) {
81318179 NotePossibleBadForwardRef (name);
81328180 return &name;
@@ -8313,6 +8361,48 @@ const parser::Name *DeclarationVisitor::FindComponent(
83138361 return nullptr ;
83148362}
83158363
8364+ bool DeclarationVisitor::FindAndMarkDeclareTargetSymbol (
8365+ const parser::Name &name) {
8366+ if (!specPartState_.declareTargetNames .empty ()) {
8367+ if (specPartState_.declareTargetNames .count (name.source )) {
8368+ if (!currScope ().IsTopLevel ()) {
8369+ // Search preceding scopes until we find a matching symbol or run out
8370+ // of scopes to search, we skip the current scope as it's already been
8371+ // designated as implicit here.
8372+ Symbol *symbol = nullptr ;
8373+ for (auto *scope = &currScope ().parent ();; scope = &scope->parent ()) {
8374+ if (Symbol * symbol{scope->FindSymbol (name.source )}) {
8375+ if (symbol->test (Symbol::Flag::Subroutine) ||
8376+ symbol->test (Symbol::Flag::Function)) {
8377+ const auto [sym, success]{currScope ().try_emplace (
8378+ symbol->name (), Attrs{}, HostAssocDetails{*symbol})};
8379+ assert (success &&
8380+ " FindAndMarkDeclareTargetSymbol could not emplace new "
8381+ " subroutine/function symbol" );
8382+ name.symbol = &*sym->second ;
8383+ symbol->test (Symbol::Flag::Subroutine)
8384+ ? name.symbol ->set (Symbol::Flag::Subroutine)
8385+ : name.symbol ->set (Symbol::Flag::Function);
8386+ return true ;
8387+ }
8388+ // if we find a symbol that is not a function or subroutine, we
8389+ // currently escape without doing anything.
8390+ break ;
8391+ }
8392+
8393+ // This is our loop exit condition, as parent() has an inbuilt assert
8394+ // if you call it on a top level scope, rather than returning a null
8395+ // value.
8396+ if (scope->IsTopLevel ()) {
8397+ return false ;
8398+ }
8399+ }
8400+ }
8401+ }
8402+ }
8403+ return false ;
8404+ }
8405+
83168406void DeclarationVisitor::Initialization (const parser::Name &name,
83178407 const parser::Initialization &init, bool inComponentDecl) {
83188408 // Traversal of the initializer was deferred to here so that the
0 commit comments