[flang-commits] [flang] [flang] Handle forward reference to shadowing derived type from IMPLICIT (PR #87280)
via flang-commits
flang-commits at lists.llvm.org
Mon Apr 1 13:05:39 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
A derived type name in an IMPLICIT statement might be a host association or it might be a forward reference to a local derived type, which may be shadowing a host-associated name. Add a scan over the specification part in search of derived type definitions to determine the right interpretation.
Fixes https://github.com/llvm/llvm-project/issues/87215.
---
Full diff: https://github.com/llvm/llvm-project/pull/87280.diff
2 Files Affected:
- (modified) flang/lib/Semantics/resolve-names.cpp (+65)
- (modified) flang/test/Semantics/resolve29.f90 (+12)
``````````diff
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 2e88a2daff2c08..dfffb908cde2f8 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1635,6 +1635,8 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
void FinishDerivedTypeInstantiation(Scope &);
void ResolveExecutionParts(const ProgramTree &);
void UseCUDABuiltinNames();
+ void HandleDerivedTypesInImplicitStmts(const parser::ImplicitPart &,
+ const std::list<parser::DeclarationConstruct> &);
};
// ImplicitRules implementation
@@ -2035,6 +2037,7 @@ bool ImplicitRulesVisitor::Pre(const parser::ImplicitSpec &) {
}
void ImplicitRulesVisitor::Post(const parser::ImplicitSpec &) {
+ set_allowForwardReferenceToDerivedType(false);
EndDeclTypeSpec();
}
@@ -8329,6 +8332,67 @@ static bool NeedsExplicitType(const Symbol &symbol) {
}
}
+void ResolveNamesVisitor::HandleDerivedTypesInImplicitStmts(
+ const parser::ImplicitPart &implicitPart,
+ const std::list<parser::DeclarationConstruct> &decls) {
+ // Detect derived type definitions and create symbols for them now if
+ // they appear in IMPLICIT statements so that these forward-looking
+ // references will not be ambiguous with host associations.
+ std::set<SourceName> implicitDerivedTypes;
+ for (const auto &ipStmt : implicitPart.v) {
+ if (const auto *impl{std::get_if<
+ parser::Statement<common::Indirection<parser::ImplicitStmt>>>(
+ &ipStmt.u)}) {
+ if (const auto *specs{std::get_if<std::list<parser::ImplicitSpec>>(
+ &impl->statement.value().u)}) {
+ for (const auto &spec : *specs) {
+ const auto &declTypeSpec{
+ std::get<parser::DeclarationTypeSpec>(spec.t)};
+ if (const auto *dtSpec{common::visit(
+ common::visitors{
+ [](const parser::DeclarationTypeSpec::Type &x) {
+ return &x.derived;
+ },
+ [](const parser::DeclarationTypeSpec::Class &x) {
+ return &x.derived;
+ },
+ [](const auto &) -> const parser::DerivedTypeSpec * {
+ return nullptr;
+ }},
+ declTypeSpec.u)}) {
+ implicitDerivedTypes.emplace(
+ std::get<parser::Name>(dtSpec->t).source);
+ }
+ }
+ }
+ }
+ }
+ if (!implicitDerivedTypes.empty()) {
+ for (const auto &decl : decls) {
+ if (const auto *spec{
+ std::get_if<parser::SpecificationConstruct>(&decl.u)}) {
+ if (const auto *dtDef{
+ std::get_if<common::Indirection<parser::DerivedTypeDef>>(
+ &spec->u)}) {
+ const parser::DerivedTypeStmt &dtStmt{
+ std::get<parser::Statement<parser::DerivedTypeStmt>>(
+ dtDef->value().t)
+ .statement};
+ const parser::Name &name{std::get<parser::Name>(dtStmt.t)};
+ if (implicitDerivedTypes.find(name.source) !=
+ implicitDerivedTypes.end() &&
+ !FindInScope(name)) {
+ DerivedTypeDetails details;
+ details.set_isForwardReferenced(true);
+ Resolve(name, MakeSymbol(name, std::move(details)));
+ implicitDerivedTypes.erase(name.source);
+ }
+ }
+ }
+ }
+ }
+}
+
bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
const auto &[accDecls, ompDecls, compilerDirectives, useStmts, importStmts,
implicitPart, decls] = x.t;
@@ -8347,6 +8411,7 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
ClearUseOnly();
ClearModuleUses();
Walk(importStmts);
+ HandleDerivedTypesInImplicitStmts(implicitPart, decls);
Walk(implicitPart);
for (const auto &decl : decls) {
if (const auto *spec{
diff --git a/flang/test/Semantics/resolve29.f90 b/flang/test/Semantics/resolve29.f90
index 3e6a8a0ba69763..c6a9b036c5828d 100644
--- a/flang/test/Semantics/resolve29.f90
+++ b/flang/test/Semantics/resolve29.f90
@@ -3,6 +3,7 @@ module m1
type t1
end type
type t3
+ integer t3c
end type
interface
subroutine s1(x)
@@ -64,6 +65,17 @@ subroutine s9()
end type
type(t2) x
end
+ subroutine s10()
+ !Forward shadowing derived type in IMPLICIT
+ !(supported by all other compilers)
+ implicit type(t1) (c) ! forward shadow
+ implicit type(t3) (d) ! host associated
+ type t1
+ integer a
+ end type
+ c%a = 1
+ d%t3c = 2
+ end
end module
module m2
integer, parameter :: ck = kind('a')
``````````
</details>
https://github.com/llvm/llvm-project/pull/87280
More information about the flang-commits
mailing list