forked from OSchip/llvm-project
[flang] Catch procedure pointer interface error
A procedure pointer is allowed to name a specific intrinsic function from F'2018 table 16.2 as its interface, but not other intrinsic procedures. Catch this error, and thereby also fix a crash resulting from a failure later in compilation from failed characteristics; while here, also catch the similar error with initializers. Differential Revision: https://reviews.llvm.org/D103570
This commit is contained in:
parent
da3ed58b97
commit
f8f7002828
|
@ -367,7 +367,7 @@ static std::optional<Procedure> CharacterizeProcedure(
|
||||||
const semantics::Symbol &original, FoldingContext &context,
|
const semantics::Symbol &original, FoldingContext &context,
|
||||||
semantics::UnorderedSymbolSet &seenProcs) {
|
semantics::UnorderedSymbolSet &seenProcs) {
|
||||||
Procedure result;
|
Procedure result;
|
||||||
const auto &symbol{original.GetUltimate()};
|
const auto &symbol{ResolveAssociations(original)};
|
||||||
if (seenProcs.find(symbol) != seenProcs.end()) {
|
if (seenProcs.find(symbol) != seenProcs.end()) {
|
||||||
std::string procsList{GetSeenProcs(seenProcs)};
|
std::string procsList{GetSeenProcs(seenProcs)};
|
||||||
context.messages().Say(symbol.name(),
|
context.messages().Say(symbol.name(),
|
||||||
|
@ -417,6 +417,11 @@ static std::optional<Procedure> CharacterizeProcedure(
|
||||||
[&](const semantics::ProcEntityDetails &proc)
|
[&](const semantics::ProcEntityDetails &proc)
|
||||||
-> std::optional<Procedure> {
|
-> std::optional<Procedure> {
|
||||||
if (symbol.attrs().test(semantics::Attr::INTRINSIC)) {
|
if (symbol.attrs().test(semantics::Attr::INTRINSIC)) {
|
||||||
|
// Fails when the intrinsic is not a specific intrinsic function
|
||||||
|
// from F'2018 table 16.2. In order to handle forward references,
|
||||||
|
// attempts to use impermissible intrinsic procedures as the
|
||||||
|
// interfaces of procedure pointers are caught and flagged in
|
||||||
|
// declaration checking in Semantics.
|
||||||
return context.intrinsics().IsSpecificIntrinsicFunction(
|
return context.intrinsics().IsSpecificIntrinsicFunction(
|
||||||
symbol.name().ToString());
|
symbol.name().ToString());
|
||||||
}
|
}
|
||||||
|
@ -786,7 +791,7 @@ std::optional<Procedure> Procedure::Characterize(
|
||||||
const ProcedureDesignator &proc, FoldingContext &context) {
|
const ProcedureDesignator &proc, FoldingContext &context) {
|
||||||
if (const auto *symbol{proc.GetSymbol()}) {
|
if (const auto *symbol{proc.GetSymbol()}) {
|
||||||
if (auto result{characteristics::Procedure::Characterize(
|
if (auto result{characteristics::Procedure::Characterize(
|
||||||
symbol->GetUltimate(), context)}) {
|
ResolveAssociations(*symbol), context)}) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} else if (const auto *intrinsic{proc.GetSpecificIntrinsic()}) {
|
} else if (const auto *intrinsic{proc.GetSpecificIntrinsic()}) {
|
||||||
|
|
|
@ -575,6 +575,12 @@ void CheckHelper::CheckPointerInitialization(const Symbol &symbol) {
|
||||||
// or an unrestricted specific intrinsic function.
|
// or an unrestricted specific intrinsic function.
|
||||||
const Symbol &ultimate{(*proc->init())->GetUltimate()};
|
const Symbol &ultimate{(*proc->init())->GetUltimate()};
|
||||||
if (ultimate.attrs().test(Attr::INTRINSIC)) {
|
if (ultimate.attrs().test(Attr::INTRINSIC)) {
|
||||||
|
if (!context_.intrinsics().IsSpecificIntrinsicFunction(
|
||||||
|
ultimate.name().ToString())) { // C1030
|
||||||
|
context_.Say(
|
||||||
|
"Intrinsic procedure '%s' is not a specific intrinsic permitted for use as the initializer for procedure pointer '%s'"_err_en_US,
|
||||||
|
ultimate.name(), symbol.name());
|
||||||
|
}
|
||||||
} else if (!ultimate.attrs().test(Attr::EXTERNAL) &&
|
} else if (!ultimate.attrs().test(Attr::EXTERNAL) &&
|
||||||
ultimate.owner().kind() != Scope::Kind::Module) {
|
ultimate.owner().kind() != Scope::Kind::Module) {
|
||||||
context_.Say("Procedure pointer '%s' initializer '%s' is neither "
|
context_.Say("Procedure pointer '%s' initializer '%s' is neither "
|
||||||
|
@ -715,8 +721,14 @@ void CheckHelper::CheckProcEntity(
|
||||||
if (symbol.attrs().test(Attr::POINTER)) {
|
if (symbol.attrs().test(Attr::POINTER)) {
|
||||||
CheckPointerInitialization(symbol);
|
CheckPointerInitialization(symbol);
|
||||||
if (const Symbol * interface{details.interface().symbol()}) {
|
if (const Symbol * interface{details.interface().symbol()}) {
|
||||||
if (interface->attrs().test(Attr::ELEMENTAL) &&
|
if (interface->attrs().test(Attr::INTRINSIC)) {
|
||||||
!interface->attrs().test(Attr::INTRINSIC)) {
|
if (!context_.intrinsics().IsSpecificIntrinsicFunction(
|
||||||
|
interface->name().ToString())) { // C1515
|
||||||
|
messages_.Say(
|
||||||
|
"Intrinsic procedure '%s' is not a specific intrinsic permitted for use as the definition of the interface to procedure pointer '%s'"_err_en_US,
|
||||||
|
interface->name(), symbol.name());
|
||||||
|
}
|
||||||
|
} else if (interface->attrs().test(Attr::ELEMENTAL)) {
|
||||||
messages_.Say("Procedure pointer '%s' may not be ELEMENTAL"_err_en_US,
|
messages_.Say("Procedure pointer '%s' may not be ELEMENTAL"_err_en_US,
|
||||||
symbol.name()); // C1517
|
symbol.name()); // C1517
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue