@@ -736,6 +736,8 @@ class ScopeHandler : public ImplicitRulesVisitor {
736
736
std::vector<const std::list<parser::EquivalenceObject> *> equivalenceSets;
737
737
// Names of all common block objects in the scope
738
738
std::set<SourceName> commonBlockObjects;
739
+ // Names of all names that show in a declare target declaration
740
+ std::set<SourceName> declareTargetNames;
739
741
// Info about SAVE statements and attributes in current scope
740
742
struct {
741
743
std::optional<SourceName> saveAll; // "SAVE" without entity list
@@ -1223,6 +1225,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
1223
1225
const parser::Name *FindComponent (const parser::Name *, const parser::Name &);
1224
1226
void Initialization (const parser::Name &, const parser::Initialization &,
1225
1227
bool inComponentDecl);
1228
+ bool FindAndMarkDeclareTargetSymbol (const parser::Name &);
1226
1229
bool PassesLocalityChecks (
1227
1230
const parser::Name &name, Symbol &symbol, Symbol::Flag flag);
1228
1231
bool CheckForHostAssociatedImplicit (const parser::Name &);
@@ -1524,7 +1527,46 @@ class OmpVisitor : public virtual DeclarationVisitor {
1524
1527
return true ;
1525
1528
}
1526
1529
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
+ ompObject.u );
1548
+ }
1549
+ };
1550
+
1551
+ if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u )}) {
1552
+ populateDeclareTargetNames (*objectList);
1553
+ } else if (const auto *clauseList{
1554
+ parser::Unwrap<parser::OmpClauseList>(spec.u )}) {
1555
+ for (const auto &clause : clauseList->v ) {
1556
+ if (const auto *toClause{
1557
+ std::get_if<parser::OmpClause::To>(&clause.u )}) {
1558
+ populateDeclareTargetNames (
1559
+ {std::get<parser::OmpObjectList>(toClause->v .t )});
1560
+ } else if (const auto *linkClause{
1561
+ std::get_if<parser::OmpClause::Link>(&clause.u )}) {
1562
+ populateDeclareTargetNames (linkClause->v );
1563
+ } else if (const auto *enterClause{
1564
+ std::get_if<parser::OmpClause::Enter>(&clause.u )}) {
1565
+ populateDeclareTargetNames (enterClause->v );
1566
+ }
1567
+ }
1568
+ }
1569
+
1528
1570
SkipImplicitTyping (true );
1529
1571
return true ;
1530
1572
}
@@ -8114,7 +8156,12 @@ const parser::Name *DeclarationVisitor::ResolveDataRef(
8114
8156
// If implicit types are allowed, ensure name is in the symbol table.
8115
8157
// Otherwise, report an error if it hasn't been declared.
8116
8158
const parser::Name *DeclarationVisitor::ResolveName (const parser::Name &name) {
8117
- FindSymbol (name);
8159
+ if (!FindSymbol (name)) {
8160
+ if (FindAndMarkDeclareTargetSymbol (name)) {
8161
+ return &name;
8162
+ }
8163
+ }
8164
+
8118
8165
if (CheckForHostAssociatedImplicit (name)) {
8119
8166
NotePossibleBadForwardRef (name);
8120
8167
return &name;
@@ -8298,6 +8345,44 @@ const parser::Name *DeclarationVisitor::FindComponent(
8298
8345
return nullptr ;
8299
8346
}
8300
8347
8348
+ bool DeclarationVisitor::FindAndMarkDeclareTargetSymbol (
8349
+ const parser::Name &name) {
8350
+ if (!specPartState_.declareTargetNames .empty ()) {
8351
+ if (specPartState_.declareTargetNames .find (name.source ) !=
8352
+ specPartState_.declareTargetNames .end ()) {
8353
+ if (!currScope ().IsTopLevel ()) {
8354
+ // Search preceding scopes until we find a matching symbol or run out
8355
+ // of scopes to search, we skip the current scope as it's already been
8356
+ // designated as implicit here.
8357
+ Symbol *symbol = nullptr ;
8358
+ for (auto *scope = &currScope ().parent ();; scope = &scope->parent ()) {
8359
+ symbol = scope->FindSymbol (name.source );
8360
+ if (symbol) {
8361
+ if (symbol->test (Symbol::Flag::Subroutine) ||
8362
+ symbol->test (Symbol::Flag::Function)) {
8363
+ const auto pair{currScope ().try_emplace (
8364
+ symbol->name (), Attrs{}, HostAssocDetails{*symbol})};
8365
+ name.symbol = &*pair.first ->second ;
8366
+ symbol->test (Symbol::Flag::Subroutine)
8367
+ ? name.symbol ->set (Symbol::Flag::Subroutine)
8368
+ : name.symbol ->set (Symbol::Flag::Function);
8369
+ return true ;
8370
+ }
8371
+ }
8372
+
8373
+ // This is our loop exit condition, as parent() has an inbuilt assert
8374
+ // if you call it on a top level scope, rather than returning a null
8375
+ // value.
8376
+ if (scope->IsTopLevel ()) {
8377
+ return false ;
8378
+ }
8379
+ }
8380
+ }
8381
+ }
8382
+ }
8383
+ return false ;
8384
+ }
8385
+
8301
8386
void DeclarationVisitor::Initialization (const parser::Name &name,
8302
8387
const parser::Initialization &init, bool inComponentDecl) {
8303
8388
// Traversal of the initializer was deferred to here so that the
0 commit comments