@@ -576,11 +576,11 @@ static std::optional<DummyArgument> CharacterizeDummyArgument(
576
576
semantics::UnorderedSymbolSet seenProcs);
577
577
static std::optional<FunctionResult> CharacterizeFunctionResult (
578
578
const semantics::Symbol &symbol, FoldingContext &context,
579
- semantics::UnorderedSymbolSet seenProcs);
579
+ semantics::UnorderedSymbolSet seenProcs, bool emitError );
580
580
581
581
static std::optional<Procedure> CharacterizeProcedure (
582
582
const semantics::Symbol &original, FoldingContext &context,
583
- semantics::UnorderedSymbolSet seenProcs) {
583
+ semantics::UnorderedSymbolSet seenProcs, bool emitError ) {
584
584
const auto &symbol{ResolveAssociations (original)};
585
585
if (seenProcs.find (symbol) != seenProcs.end ()) {
586
586
std::string procsList{GetSeenProcs (seenProcs)};
@@ -591,14 +591,22 @@ static std::optional<Procedure> CharacterizeProcedure(
591
591
return std::nullopt;
592
592
}
593
593
seenProcs.insert (symbol);
594
+ auto CheckForNested{[&](const Symbol &symbol) {
595
+ if (emitError) {
596
+ CHECK (!getenv (" PMK" ));
597
+ context.messages ().Say (
598
+ " Procedure '%s' is referenced before being sufficiently defined in a context where it must be so" _err_en_US,
599
+ symbol.name ());
600
+ }
601
+ }};
594
602
auto result{common::visit (
595
603
common::visitors{
596
604
[&](const semantics::SubprogramDetails &subp)
597
605
-> std::optional<Procedure> {
598
606
Procedure result;
599
607
if (subp.isFunction ()) {
600
608
if (auto fr{CharacterizeFunctionResult (
601
- subp.result (), context, seenProcs)}) {
609
+ subp.result (), context, seenProcs, emitError )}) {
602
610
result.functionResult = std::move (fr);
603
611
} else {
604
612
return std::nullopt;
@@ -641,8 +649,8 @@ static std::optional<Procedure> CharacterizeProcedure(
641
649
}
642
650
if (const semantics::Symbol *
643
651
interfaceSymbol{proc.procInterface ()}) {
644
- auto result{
645
- CharacterizeProcedure ( *interfaceSymbol, context, seenProcs)};
652
+ auto result{CharacterizeProcedure (
653
+ *interfaceSymbol, context, seenProcs, /* emitError= */ false )};
646
654
if (result && (IsDummy (symbol) || IsPointer (symbol))) {
647
655
// Dummy procedures and procedure pointers may not be
648
656
// ELEMENTAL, but we do accept the use of elemental intrinsic
@@ -675,8 +683,8 @@ static std::optional<Procedure> CharacterizeProcedure(
675
683
}
676
684
},
677
685
[&](const semantics::ProcBindingDetails &binding) {
678
- if (auto result{CharacterizeProcedure (
679
- binding. symbol (), context, seenProcs )}) {
686
+ if (auto result{CharacterizeProcedure (binding. symbol (), context,
687
+ seenProcs, /* emitError= */ false )}) {
680
688
if (binding.symbol ().attrs ().test (semantics::Attr::INTRINSIC)) {
681
689
result->attrs .reset (Procedure::Attr::Elemental);
682
690
}
@@ -695,33 +703,32 @@ static std::optional<Procedure> CharacterizeProcedure(
695
703
}
696
704
},
697
705
[&](const semantics::UseDetails &use) {
698
- return CharacterizeProcedure (use.symbol (), context, seenProcs);
706
+ return CharacterizeProcedure (
707
+ use.symbol (), context, seenProcs, /* emitError=*/ false );
699
708
},
700
709
[](const semantics::UseErrorDetails &) {
701
710
// Ambiguous use-association will be handled later during symbol
702
711
// checks, ignore UseErrorDetails here without actual symbol usage.
703
712
return std::optional<Procedure>{};
704
713
},
705
714
[&](const semantics::HostAssocDetails &assoc) {
706
- return CharacterizeProcedure (assoc.symbol (), context, seenProcs);
715
+ return CharacterizeProcedure (
716
+ assoc.symbol (), context, seenProcs, /* emitError=*/ false );
707
717
},
708
718
[&](const semantics::GenericDetails &generic) {
709
719
if (const semantics::Symbol * specific{generic.specific ()}) {
710
- return CharacterizeProcedure (*specific, context, seenProcs);
720
+ return CharacterizeProcedure (
721
+ *specific, context, seenProcs, emitError);
711
722
} else {
712
723
return std::optional<Procedure>{};
713
724
}
714
725
},
715
726
[&](const semantics::EntityDetails &) {
716
- context.messages ().Say (
717
- " Procedure '%s' is referenced before being sufficiently defined in a context where it must be so" _err_en_US,
718
- symbol.name ());
727
+ CheckForNested (symbol);
719
728
return std::optional<Procedure>{};
720
729
},
721
730
[&](const semantics::SubprogramNameDetails &) {
722
- context.messages ().Say (
723
- " Procedure '%s' is referenced before being sufficiently defined in a context where it must be so" _err_en_US,
724
- symbol.name ());
731
+ CheckForNested (symbol);
725
732
return std::optional<Procedure>{};
726
733
},
727
734
[&](const auto &) {
@@ -752,7 +759,8 @@ static std::optional<Procedure> CharacterizeProcedure(
752
759
static std::optional<DummyProcedure> CharacterizeDummyProcedure (
753
760
const semantics::Symbol &symbol, FoldingContext &context,
754
761
semantics::UnorderedSymbolSet seenProcs) {
755
- if (auto procedure{CharacterizeProcedure (symbol, context, seenProcs)}) {
762
+ if (auto procedure{CharacterizeProcedure (
763
+ symbol, context, seenProcs, /* emitError=*/ true )}) {
756
764
// Dummy procedures may not be elemental. Elemental dummy procedure
757
765
// interfaces are errors when the interface is not intrinsic, and that
758
766
// error is caught elsewhere. Elemental intrinsic interfaces are
@@ -854,7 +862,8 @@ std::optional<DummyArgument> DummyArgument::FromActual(std::string &&name,
854
862
std::move (name), std::move (obj));
855
863
},
856
864
[&](const ProcedureDesignator &designator) {
857
- if (auto proc{Procedure::Characterize (designator, context)}) {
865
+ if (auto proc{Procedure::Characterize (
866
+ designator, context, /* emitError=*/ true )}) {
858
867
return std::make_optional<DummyArgument>(
859
868
std::move (name), DummyProcedure{std::move (*proc)});
860
869
} else {
@@ -988,7 +997,7 @@ bool FunctionResult::operator==(const FunctionResult &that) const {
988
997
989
998
static std::optional<FunctionResult> CharacterizeFunctionResult (
990
999
const semantics::Symbol &symbol, FoldingContext &context,
991
- semantics::UnorderedSymbolSet seenProcs) {
1000
+ semantics::UnorderedSymbolSet seenProcs, bool emitError ) {
992
1001
if (const auto *object{symbol.detailsIf <semantics::ObjectEntityDetails>()}) {
993
1002
if (auto type{TypeAndShape::Characterize (
994
1003
symbol, context, /* invariantOnly=*/ false )}) {
@@ -1002,8 +1011,8 @@ static std::optional<FunctionResult> CharacterizeFunctionResult(
1002
1011
result.cudaDataAttr = object->cudaDataAttr ();
1003
1012
return result;
1004
1013
}
1005
- } else if (auto maybeProc{
1006
- CharacterizeProcedure ( symbol, context, seenProcs)}) {
1014
+ } else if (auto maybeProc{CharacterizeProcedure (
1015
+ symbol, context, seenProcs, emitError )}) {
1007
1016
FunctionResult result{std::move (*maybeProc)};
1008
1017
result.attrs .set (FunctionResult::Attr::Pointer);
1009
1018
return result;
@@ -1014,7 +1023,8 @@ static std::optional<FunctionResult> CharacterizeFunctionResult(
1014
1023
std::optional<FunctionResult> FunctionResult::Characterize (
1015
1024
const Symbol &symbol, FoldingContext &context) {
1016
1025
semantics::UnorderedSymbolSet seenProcs;
1017
- return CharacterizeFunctionResult (symbol, context, seenProcs);
1026
+ return CharacterizeFunctionResult (
1027
+ symbol, context, seenProcs, /* emitError=*/ false );
1018
1028
}
1019
1029
1020
1030
bool FunctionResult::IsAssumedLengthCharacter () const {
@@ -1360,27 +1370,26 @@ bool Procedure::CanOverride(
1360
1370
}
1361
1371
1362
1372
std::optional<Procedure> Procedure::Characterize (
1363
- const semantics::Symbol &original , FoldingContext &context) {
1373
+ const semantics::Symbol &symbol , FoldingContext &context) {
1364
1374
semantics::UnorderedSymbolSet seenProcs;
1365
- return CharacterizeProcedure (original , context, seenProcs);
1375
+ return CharacterizeProcedure (symbol , context, seenProcs, /* emitError= */ true );
1366
1376
}
1367
1377
1368
1378
std::optional<Procedure> Procedure::Characterize (
1369
- const ProcedureDesignator &proc, FoldingContext &context) {
1379
+ const ProcedureDesignator &proc, FoldingContext &context, bool emitError ) {
1370
1380
if (const auto *symbol{proc.GetSymbol ()}) {
1371
- if (auto result{
1372
- characteristics::Procedure::Characterize (*symbol, context)}) {
1373
- return result;
1374
- }
1381
+ semantics::UnorderedSymbolSet seenProcs;
1382
+ return CharacterizeProcedure (*symbol, context, seenProcs, emitError);
1375
1383
} else if (const auto *intrinsic{proc.GetSpecificIntrinsic ()}) {
1376
1384
return intrinsic->characteristics .value ();
1385
+ } else {
1386
+ return std::nullopt;
1377
1387
}
1378
- return std::nullopt;
1379
1388
}
1380
1389
1381
1390
std::optional<Procedure> Procedure::Characterize (
1382
1391
const ProcedureRef &ref, FoldingContext &context) {
1383
- if (auto callee{Characterize (ref.proc (), context)}) {
1392
+ if (auto callee{Characterize (ref.proc (), context, /* emitError= */ true )}) {
1384
1393
if (callee->functionResult ) {
1385
1394
if (const Procedure *
1386
1395
proc{callee->functionResult ->IsProcedurePointer ()}) {
@@ -1397,7 +1406,7 @@ std::optional<Procedure> Procedure::Characterize(
1397
1406
return Characterize (*procRef, context);
1398
1407
} else if (const auto *procDesignator{
1399
1408
std::get_if<ProcedureDesignator>(&expr.u )}) {
1400
- return Characterize (*procDesignator, context);
1409
+ return Characterize (*procDesignator, context, /* emitError= */ true );
1401
1410
} else if (const Symbol * symbol{UnwrapWholeSymbolOrComponentDataRef (expr)}) {
1402
1411
return Characterize (*symbol, context);
1403
1412
} else {
@@ -1409,7 +1418,7 @@ std::optional<Procedure> Procedure::Characterize(
1409
1418
1410
1419
std::optional<Procedure> Procedure::FromActuals (const ProcedureDesignator &proc,
1411
1420
const ActualArguments &args, FoldingContext &context) {
1412
- auto callee{Characterize (proc, context)};
1421
+ auto callee{Characterize (proc, context, /* emitError= */ true )};
1413
1422
if (callee) {
1414
1423
if (callee->dummyArguments .empty () &&
1415
1424
callee->attrs .test (Procedure::Attr::ImplicitInterface)) {
0 commit comments