@@ -698,7 +698,7 @@ class ScopeHandler : public ImplicitRulesVisitor {
698
698
bool CheckPossibleBadForwardRef (const Symbol &);
699
699
700
700
bool inSpecificationPart_{false };
701
- bool inDataStmtObject_ {false };
701
+ bool deferImplicitTyping_ {false };
702
702
bool inEquivalenceStmt_{false };
703
703
704
704
// Some information is collected from a specification part for deferred
@@ -1629,6 +1629,7 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
1629
1629
bool BeginScopeForNode (const ProgramTree &);
1630
1630
void EndScopeForNode (const ProgramTree &);
1631
1631
void FinishSpecificationParts (const ProgramTree &);
1632
+ void FinishExecutionParts (const ProgramTree &);
1632
1633
void FinishDerivedTypeInstantiation (Scope &);
1633
1634
void ResolveExecutionParts (const ProgramTree &);
1634
1635
void UseCUDABuiltinNames ();
@@ -2533,7 +2534,7 @@ void ScopeHandler::ApplyImplicitRules(
2533
2534
// or object, it'll be caught later.
2534
2535
return ;
2535
2536
}
2536
- if (inDataStmtObject_ ) {
2537
+ if (deferImplicitTyping_ ) {
2537
2538
return ;
2538
2539
}
2539
2540
if (!context ().HasError (symbol)) {
@@ -2709,7 +2710,7 @@ const DeclTypeSpec &ScopeHandler::MakeLogicalType(int kind) {
2709
2710
}
2710
2711
2711
2712
void ScopeHandler::NotePossibleBadForwardRef (const parser::Name &name) {
2712
- if (inSpecificationPart_ && !inDataStmtObject_ && name.symbol ) {
2713
+ if (inSpecificationPart_ && !deferImplicitTyping_ && name.symbol ) {
2713
2714
auto kind{currScope ().kind ()};
2714
2715
if ((kind == Scope::Kind::Subprogram && !currScope ().IsStmtFunction ()) ||
2715
2716
kind == Scope::Kind::BlockConstruct) {
@@ -6802,7 +6803,8 @@ bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {
6802
6803
auto flagRestorer{common::ScopedSet (inSpecificationPart_, false )};
6803
6804
common::visit (common::visitors{
6804
6805
[&](const Indirection<parser::Variable> &y) {
6805
- auto restorer{common::ScopedSet (inDataStmtObject_, true )};
6806
+ auto restorer{
6807
+ common::ScopedSet (deferImplicitTyping_, true )};
6806
6808
Walk (y.value ());
6807
6809
const parser::Name &first{
6808
6810
parser::GetFirstName (y.value ())};
@@ -7386,7 +7388,7 @@ const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
7386
7388
}
7387
7389
return &name;
7388
7390
}
7389
- if (isImplicitNoneType () && !inDataStmtObject_ ) {
7391
+ if (isImplicitNoneType () && !deferImplicitTyping_ ) {
7390
7392
Say (name, " No explicit type declared for '%s'" _err_en_US);
7391
7393
return nullptr ;
7392
7394
}
@@ -7548,7 +7550,15 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
7548
7550
common::visit (
7549
7551
common::visitors{
7550
7552
[&](const parser::ConstantExpr &expr) {
7551
- NonPointerInitialization (name, expr);
7553
+ Walk (expr);
7554
+ if (IsNamedConstant (ultimate) || inComponentDecl) {
7555
+ NonPointerInitialization (name, expr);
7556
+ } else {
7557
+ // Defer analysis so forward references to nested subprograms
7558
+ // can be properly resolved when they appear in structure
7559
+ // constructors.
7560
+ ultimate.set (Symbol::Flag::InDataStmt);
7561
+ }
7552
7562
},
7553
7563
[&](const parser::NullInit &null) { // => NULL()
7554
7564
Walk (null);
@@ -7569,10 +7579,12 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
7569
7579
}
7570
7580
}
7571
7581
},
7572
- [&](const parser::InitialDataTarget &) {
7582
+ [&](const parser::InitialDataTarget &target ) {
7573
7583
// Defer analysis to the end of the specification part
7574
7584
// so that forward references and attribute checks like SAVE
7575
7585
// work better.
7586
+ auto restorer{common::ScopedSet (deferImplicitTyping_, true )};
7587
+ Walk (target);
7576
7588
ultimate.set (Symbol::Flag::InDataStmt);
7577
7589
},
7578
7590
[&](const std::list<Indirection<parser::DataStmtValue>> &values) {
@@ -7590,12 +7602,27 @@ void DeclarationVisitor::PointerInitialization(
7590
7602
Symbol &ultimate{name.symbol ->GetUltimate ()};
7591
7603
if (!context ().HasError (ultimate)) {
7592
7604
if (IsPointer (ultimate)) {
7593
- if ( auto *details{ultimate. detailsIf <ObjectEntityDetails>()}) {
7594
- CHECK (!details-> init ());
7595
- Walk (target);
7596
- if (MaybeExpr expr{ EvaluateExpr (target )}) {
7597
- // Validation is done in declaration checking.
7605
+ Walk (target);
7606
+ if (MaybeExpr expr{ EvaluateExpr (target)}) {
7607
+ // Validation is done in declaration checking.
7608
+ if (auto *details{ultimate. detailsIf <ObjectEntityDetails>( )}) {
7609
+ CHECK (!details-> init ());
7598
7610
details->set_init (std::move (*expr));
7611
+ ultimate.set (Symbol::Flag::InDataStmt, false );
7612
+ } else if (auto *details{ultimate.detailsIf <ProcEntityDetails>()}) {
7613
+ // something like "REAL, EXTERNAL, POINTER :: p => t"
7614
+ if (evaluate::IsNullProcedurePointer (*expr)) {
7615
+ CHECK (!details->init ());
7616
+ details->set_init (nullptr );
7617
+ } else if (const Symbol *
7618
+ targetSymbol{evaluate::UnwrapWholeSymbolDataRef (*expr)}) {
7619
+ CHECK (!details->init ());
7620
+ details->set_init (*targetSymbol);
7621
+ } else {
7622
+ Say (name,
7623
+ " Procedure pointer '%s' must be initialized with a procedure name or NULL()" _err_en_US);
7624
+ context ().SetError (ultimate);
7625
+ }
7599
7626
}
7600
7627
}
7601
7628
} else {
@@ -7635,27 +7662,23 @@ void DeclarationVisitor::PointerInitialization(
7635
7662
7636
7663
void DeclarationVisitor::NonPointerInitialization (
7637
7664
const parser::Name &name, const parser::ConstantExpr &expr) {
7638
- if (name.symbol ) {
7665
+ if (! context (). HasError ( name.symbol ) ) {
7639
7666
Symbol &ultimate{name.symbol ->GetUltimate ()};
7640
- if (!context ().HasError (ultimate) && ! context (). HasError (name. symbol ) ) {
7667
+ if (!context ().HasError (ultimate)) {
7641
7668
if (IsPointer (ultimate)) {
7642
7669
Say (name,
7643
7670
" '%s' is a pointer but is not initialized like one" _err_en_US);
7644
7671
} else if (auto *details{ultimate.detailsIf <ObjectEntityDetails>()}) {
7645
- CHECK (! details->init ());
7646
- if (IsAllocatable (ultimate)) {
7672
+ if ( details->init ()) {
7673
+ } else if (IsAllocatable (ultimate)) {
7647
7674
Say (name, " Allocatable object '%s' cannot be initialized" _err_en_US);
7648
- return ;
7649
- }
7650
- Walk (expr);
7651
- if (ultimate.owner ().IsParameterizedDerivedType ()) {
7675
+ } else if (ultimate.owner ().IsParameterizedDerivedType ()) {
7652
7676
// Save the expression for per-instantiation analysis.
7653
7677
details->set_unanalyzedPDTComponentInit (&expr.thing .value ());
7654
- } else {
7655
- if (MaybeExpr folded{EvaluateNonPointerInitializer (
7656
- ultimate, expr, expr.thing .value ().source )}) {
7657
- details->set_init (std::move (*folded));
7658
- }
7678
+ } else if (MaybeExpr folded{EvaluateNonPointerInitializer (
7679
+ ultimate, expr, expr.thing .value ().source )}) {
7680
+ details->set_init (std::move (*folded));
7681
+ ultimate.set (Symbol::Flag::InDataStmt, false );
7659
7682
}
7660
7683
} else {
7661
7684
Say (name, " '%s' is not an object that can be initialized" _err_en_US);
@@ -8424,6 +8447,7 @@ bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) {
8424
8447
ResolveSpecificationParts (root);
8425
8448
FinishSpecificationParts (root);
8426
8449
ResolveExecutionParts (root);
8450
+ FinishExecutionParts (root);
8427
8451
ResolveAccParts (context (), x);
8428
8452
ResolveOmpParts (context (), x);
8429
8453
return false ;
@@ -8841,6 +8865,8 @@ class DeferredCheckVisitor {
8841
8865
}
8842
8866
}
8843
8867
8868
+ bool Pre (const parser::BlockConstruct &x) { return true ; }
8869
+
8844
8870
void Post (const parser::ProcInterface &pi) {
8845
8871
if (const auto *name{std::get_if<parser::Name>(&pi.u )}) {
8846
8872
resolver_.CheckExplicitInterface (*name);
@@ -8871,7 +8897,6 @@ class DeferredCheckVisitor {
8871
8897
resolver_.CheckBindings (tbps);
8872
8898
}
8873
8899
}
8874
- bool Pre (const parser::StmtFunctionStmt &stmtFunc) { return false ; }
8875
8900
8876
8901
private:
8877
8902
void Init (const parser::Name &name,
@@ -8880,6 +8905,9 @@ class DeferredCheckVisitor {
8880
8905
if (const auto *target{
8881
8906
std::get_if<parser::InitialDataTarget>(&init->u )}) {
8882
8907
resolver_.PointerInitialization (name, *target);
8908
+ } else if (const auto *expr{
8909
+ std::get_if<parser::ConstantExpr>(&init->u )}) {
8910
+ resolver_.NonPointerInitialization (name, *expr);
8883
8911
}
8884
8912
}
8885
8913
}
@@ -8894,15 +8922,16 @@ void ResolveNamesVisitor::FinishSpecificationParts(const ProgramTree &node) {
8894
8922
if (!node.scope ()) {
8895
8923
return ; // error occurred creating scope
8896
8924
}
8925
+ auto flagRestorer{common::ScopedSet (inSpecificationPart_, true )};
8897
8926
SetScope (*node.scope ());
8898
- // The initializers of pointers, the default initializers of pointer
8899
- // components, non-deferred type-bound procedure bindings have not
8900
- // yet been traversed.
8901
- // We do that now, when any (formerly) forward references that appear
8927
+ // The initializers of pointers and non-PARAMETER objects, the default
8928
+ // initializers of components, and non-deferred type-bound procedure
8929
+ // bindings have not yet been traversed.
8930
+ // We do that now, when any forward references that appeared
8902
8931
// in those initializers will resolve to the right symbols without
8903
- // incurring spurious errors with IMPLICIT NONE.
8932
+ // incurring spurious errors with IMPLICIT NONE or forward references
8933
+ // to nested subprograms.
8904
8934
DeferredCheckVisitor{*this }.Walk (node.spec ());
8905
- DeferredCheckVisitor{*this }.Walk (node.exec ()); // for BLOCK
8906
8935
for (Scope &childScope : currScope ().children ()) {
8907
8936
if (childScope.IsParameterizedDerivedTypeInstantiation ()) {
8908
8937
FinishDerivedTypeInstantiation (childScope);
@@ -8913,6 +8942,18 @@ void ResolveNamesVisitor::FinishSpecificationParts(const ProgramTree &node) {
8913
8942
}
8914
8943
}
8915
8944
8945
+ void ResolveNamesVisitor::FinishExecutionParts (const ProgramTree &node) {
8946
+ if (node.scope ()) {
8947
+ SetScope (*node.scope ());
8948
+ if (node.exec ()) {
8949
+ DeferredCheckVisitor{*this }.Walk (*node.exec ());
8950
+ }
8951
+ for (const auto &child : node.children ()) {
8952
+ FinishExecutionParts (child);
8953
+ }
8954
+ }
8955
+ }
8956
+
8916
8957
// Duplicate and fold component object pointer default initializer designators
8917
8958
// using the actual type parameter values of each particular instantiation.
8918
8959
// Validation is done later in declaration checking.
0 commit comments