@@ -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,47 @@ 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
+ },
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
+
1528
1571
SkipImplicitTyping (true );
1529
1572
return true ;
1530
1573
}
@@ -8126,7 +8169,12 @@ const parser::Name *DeclarationVisitor::ResolveDataRef(
8126
8169
// If implicit types are allowed, ensure name is in the symbol table.
8127
8170
// Otherwise, report an error if it hasn't been declared.
8128
8171
const 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
+
8130
8178
if (CheckForHostAssociatedImplicit (name)) {
8131
8179
NotePossibleBadForwardRef (name);
8132
8180
return &name;
@@ -8313,6 +8361,48 @@ const parser::Name *DeclarationVisitor::FindComponent(
8313
8361
return nullptr ;
8314
8362
}
8315
8363
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
+
8316
8406
void DeclarationVisitor::Initialization (const parser::Name &name,
8317
8407
const parser::Initialization &init, bool inComponentDecl) {
8318
8408
// Traversal of the initializer was deferred to here so that the
0 commit comments