@@ -843,11 +843,13 @@ class InterfaceVisitor : public virtual ScopeHandler {
843
843
844
844
using ProcedureKind = parser::ProcedureStmt::Kind;
845
845
// mapping of generic to its specific proc names and kinds
846
- std::multimap<Symbol *, std::pair<const parser::Name *, ProcedureKind>>
847
- specificProcs_;
846
+ using SpecificProcMapType =
847
+ std::multimap<Symbol *, std::pair<const parser::Name *, ProcedureKind>>;
848
+ SpecificProcMapType specificProcs_;
848
849
849
850
void AddSpecificProcs (const std::list<parser::Name> &, ProcedureKind);
850
- void ResolveSpecificsInGeneric (Symbol &generic);
851
+ void ResolveSpecificsInGeneric (Symbol &, bool isEndOfSpecificationPart);
852
+ void ResolveNewSpecifics ();
851
853
};
852
854
853
855
class SubprogramVisitor : public virtual ScopeHandler, public InterfaceVisitor {
@@ -3258,6 +3260,7 @@ bool InterfaceVisitor::Pre(const parser::InterfaceStmt &x) {
3258
3260
void InterfaceVisitor::Post (const parser::InterfaceStmt &) { EndAttrs (); }
3259
3261
3260
3262
void InterfaceVisitor::Post (const parser::EndInterfaceStmt &) {
3263
+ ResolveNewSpecifics ();
3261
3264
genericInfo_.pop ();
3262
3265
}
3263
3266
@@ -3277,11 +3280,11 @@ bool InterfaceVisitor::Pre(const parser::GenericSpec &x) {
3277
3280
bool InterfaceVisitor::Pre (const parser::ProcedureStmt &x) {
3278
3281
if (!isGeneric ()) {
3279
3282
Say (" A PROCEDURE statement is only allowed in a generic interface block" _err_en_US);
3280
- return false ;
3283
+ } else {
3284
+ auto kind{std::get<parser::ProcedureStmt::Kind>(x.t )};
3285
+ const auto &names{std::get<std::list<parser::Name>>(x.t )};
3286
+ AddSpecificProcs (names, kind);
3281
3287
}
3282
- auto kind{std::get<parser::ProcedureStmt::Kind>(x.t )};
3283
- const auto &names{std::get<std::list<parser::Name>>(x.t )};
3284
- AddSpecificProcs (names, kind);
3285
3288
return false ;
3286
3289
}
3287
3290
@@ -3295,6 +3298,7 @@ void InterfaceVisitor::Post(const parser::GenericStmt &x) {
3295
3298
}
3296
3299
const auto &names{std::get<std::list<parser::Name>>(x.t )};
3297
3300
AddSpecificProcs (names, ProcedureKind::Procedure);
3301
+ ResolveNewSpecifics ();
3298
3302
genericInfo_.pop ();
3299
3303
}
3300
3304
@@ -3318,36 +3322,48 @@ void InterfaceVisitor::AddSpecificProcs(
3318
3322
3319
3323
// By now we should have seen all specific procedures referenced by name in
3320
3324
// this generic interface. Resolve those names to symbols.
3321
- void InterfaceVisitor::ResolveSpecificsInGeneric (Symbol &generic) {
3325
+ void InterfaceVisitor::ResolveSpecificsInGeneric (
3326
+ Symbol &generic, bool isEndOfSpecificationPart) {
3322
3327
auto &details{generic.get <GenericDetails>()};
3323
3328
UnorderedSymbolSet symbolsSeen;
3324
3329
for (const Symbol &symbol : details.specificProcs ()) {
3325
3330
symbolsSeen.insert (symbol.GetUltimate ());
3326
3331
}
3327
3332
auto range{specificProcs_.equal_range (&generic)};
3333
+ SpecificProcMapType retain;
3328
3334
for (auto it{range.first }; it != range.second ; ++it) {
3329
3335
const parser::Name *name{it->second .first };
3330
3336
auto kind{it->second .second };
3331
- const auto *symbol{FindSymbol (*name)};
3332
- if (!symbol) {
3333
- Say (*name, " Procedure '%s' not found" _err_en_US);
3337
+ const Symbol *symbol{FindSymbol (*name)};
3338
+ if (!isEndOfSpecificationPart && symbol &&
3339
+ &symbol->owner () != &generic.owner ()) {
3340
+ // Don't mistakenly use a name from the enclosing scope while there's
3341
+ // still a chance that it could be overridden by a later declaration in
3342
+ // this scope.
3343
+ retain.emplace (&generic, std::make_pair (name, kind));
3334
3344
continue ;
3335
3345
}
3336
- // Subtlety: when *symbol is a use- or host-association, the specific
3337
- // procedure that is recorded in the GenericDetails below must be *symbol,
3338
- // not the specific procedure shadowed by a generic, because that specific
3339
- // procedure may be a symbol from another module and its name unavailable to
3340
- // emit to a module file.
3341
- const Symbol &bypassed{BypassGeneric (*symbol)};
3342
- const Symbol &specific{
3343
- symbol == &symbol->GetUltimate () ? bypassed : *symbol};
3344
- const Symbol &ultimate{bypassed.GetUltimate ()};
3345
- ProcedureDefinitionClass defClass{ClassifyProcedure (ultimate)};
3346
+ ProcedureDefinitionClass defClass{ProcedureDefinitionClass::None};
3347
+ const Symbol *specific{symbol};
3348
+ const Symbol *ultimate{nullptr };
3349
+ if (symbol) {
3350
+ // Subtlety: when *symbol is a use- or host-association, the specific
3351
+ // procedure that is recorded in the GenericDetails below must be *symbol,
3352
+ // not the specific procedure shadowed by a generic, because that specific
3353
+ // procedure may be a symbol from another module and its name unavailable
3354
+ // to emit to a module file.
3355
+ const Symbol &bypassed{BypassGeneric (*symbol)};
3356
+ if (symbol == &symbol->GetUltimate ()) {
3357
+ specific = &bypassed;
3358
+ }
3359
+ ultimate = &bypassed.GetUltimate ();
3360
+ defClass = ClassifyProcedure (*ultimate);
3361
+ }
3362
+ std::optional<MessageFixedText> error;
3346
3363
if (defClass == ProcedureDefinitionClass::Module) {
3347
3364
// ok
3348
3365
} else if (kind == ProcedureKind::ModuleProcedure) {
3349
- Say (*name, " '%s' is not a module procedure" _err_en_US);
3350
- continue ;
3366
+ error = " '%s' is not a module procedure" _err_en_US;
3351
3367
} else {
3352
3368
switch (defClass) {
3353
3369
case ProcedureDefinitionClass::Intrinsic:
@@ -3357,47 +3373,58 @@ void InterfaceVisitor::ResolveSpecificsInGeneric(Symbol &generic) {
3357
3373
case ProcedureDefinitionClass::Pointer:
3358
3374
break ;
3359
3375
case ProcedureDefinitionClass::None:
3360
- Say (*name, " '%s' is not a procedure" _err_en_US) ;
3361
- continue ;
3376
+ error = " '%s' is not a procedure" _err_en_US;
3377
+ break ;
3362
3378
default :
3363
- Say (*name,
3364
- " '%s' is not a procedure that can appear in a generic interface" _err_en_US) ;
3365
- continue ;
3379
+ error =
3380
+ " '%s' is not a procedure that can appear in a generic interface" _err_en_US;
3381
+ break ;
3366
3382
}
3367
3383
}
3368
- if (symbolsSeen.insert (ultimate).second /* true if added*/ ) {
3384
+ if (error) {
3385
+ if (isEndOfSpecificationPart) {
3386
+ Say (*name, std::move (*error));
3387
+ } else {
3388
+ // possible forward reference, catch it later
3389
+ retain.emplace (&generic, std::make_pair (name, kind));
3390
+ }
3391
+ } else if (!ultimate) {
3392
+ } else if (symbolsSeen.insert (*ultimate).second /* true if added*/ ) {
3369
3393
// When a specific procedure is a USE association, that association
3370
3394
// is saved in the generic's specifics, not its ultimate symbol,
3371
3395
// so that module file output of interfaces can distinguish them.
3372
- details.AddSpecificProc (specific, name->source );
3373
- } else if (& specific == & ultimate) {
3396
+ details.AddSpecificProc (* specific, name->source );
3397
+ } else if (specific == ultimate) {
3374
3398
Say (name->source ,
3375
3399
" Procedure '%s' is already specified in generic '%s'" _err_en_US,
3376
3400
name->source , MakeOpName (generic.name ()));
3377
3401
} else {
3378
3402
Say (name->source ,
3379
3403
" Procedure '%s' from module '%s' is already specified in generic '%s'" _err_en_US,
3380
- ultimate. name (), ultimate. owner ().GetName ().value (),
3404
+ ultimate-> name (), ultimate-> owner ().GetName ().value (),
3381
3405
MakeOpName (generic.name ()));
3382
3406
}
3383
3407
}
3384
3408
specificProcs_.erase (range.first , range.second );
3409
+ specificProcs_.merge (std::move (retain));
3410
+ }
3411
+
3412
+ void InterfaceVisitor::ResolveNewSpecifics () {
3413
+ if (Symbol * generic{genericInfo_.top ().symbol };
3414
+ generic && generic->has <GenericDetails>()) {
3415
+ ResolveSpecificsInGeneric (*generic, false );
3416
+ }
3385
3417
}
3386
3418
3387
3419
// Mixed interfaces are allowed by the standard.
3388
3420
// If there is a derived type with the same name, they must all be functions.
3389
3421
void InterfaceVisitor::CheckGenericProcedures (Symbol &generic) {
3390
- ResolveSpecificsInGeneric (generic);
3422
+ ResolveSpecificsInGeneric (generic, true );
3391
3423
auto &details{generic.get <GenericDetails>()};
3392
3424
if (auto *proc{details.CheckSpecific ()}) {
3393
- auto msg{
3394
- " '%s' should not be the name of both a generic interface and a"
3395
- " procedure unless it is a specific procedure of the generic" _warn_en_US};
3396
- if (proc->name ().begin () > generic.name ().begin ()) {
3397
- Say (proc->name (), std::move (msg));
3398
- } else {
3399
- Say (generic.name (), std::move (msg));
3400
- }
3425
+ Say (proc->name ().begin () > generic.name ().begin () ? proc->name ()
3426
+ : generic.name (),
3427
+ " '%s' should not be the name of both a generic interface and a procedure unless it is a specific procedure of the generic" _warn_en_US);
3401
3428
}
3402
3429
auto &specifics{details.specificProcs ()};
3403
3430
if (specifics.empty ()) {
0 commit comments