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