[flang] Add traits to several AST nodes (#175065)

There are quite a few AST nodes that don't have any of the standard
traits (Wrapper/Tuple/etc). Because of that they require special
handling in the parse tree visitor.

Convert a subset of these nodes to the typical format, and remove the
special cases from the parse tree visitor.
This commit is contained in:
Krzysztof Parzyszek 2026-01-08 18:26:48 -06:00 committed by GitHub
parent 7a22bea512
commit 568b8e4873
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 95 additions and 258 deletions

View File

@ -64,6 +64,7 @@ public:
NODE(std, uint64_t)
NODE_ENUM(common, CUDADataAttr)
NODE_ENUM(common, CUDASubprogramAttrs)
NODE_ENUM(common, ImportKind)
NODE_ENUM(common, OmpDependenceKind)
NODE_ENUM(common, OmpMemoryOrderType)
NODE_ENUM(common, OpenACCDeviceType)

View File

@ -296,20 +296,6 @@ struct ParseTreeVisitorLookupScope {
}
}
template <typename V> static void Walk(const AcSpec &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.type, visitor);
Walk(x.values, visitor);
visitor.Post(x);
}
}
template <typename M> static void Walk(AcSpec &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.type, mutator);
Walk(x.values, mutator);
mutator.Post(x);
}
}
template <typename V> static void Walk(const ArrayElement &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.base, visitor);
@ -325,37 +311,6 @@ struct ParseTreeVisitorLookupScope {
}
}
template <typename V>
static void Walk(const CharSelector::LengthAndKind &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.length, visitor);
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template <typename M>
static void Walk(CharSelector::LengthAndKind &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.length, mutator);
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template <typename V>
static void Walk(const CaseValueRange::Range &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.lower, visitor);
Walk(x.upper, visitor);
visitor.Post(x);
}
}
template <typename M> static void Walk(CaseValueRange::Range &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.lower, mutator);
Walk(x.upper, mutator);
mutator.Post(x);
}
}
template <typename V>
static void Walk(const CoindexedNamedObject &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.base, visitor);
@ -370,102 +325,6 @@ struct ParseTreeVisitorLookupScope {
mutator.Post(x);
}
}
template <typename V>
static void Walk(const DeclarationTypeSpec::Class &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.derived, visitor);
visitor.Post(x);
}
}
template <typename M>
static void Walk(DeclarationTypeSpec::Class &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.derived, mutator);
mutator.Post(x);
}
}
template <typename V>
static void Walk(const DeclarationTypeSpec::Type &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.derived, visitor);
visitor.Post(x);
}
}
template <typename M>
static void Walk(DeclarationTypeSpec::Type &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.derived, mutator);
mutator.Post(x);
}
}
template <typename V> static void Walk(const ImportStmt &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.names, visitor);
visitor.Post(x);
}
}
template <typename M> static void Walk(ImportStmt &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.names, mutator);
mutator.Post(x);
}
}
template <typename V>
static void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.selector, visitor);
visitor.Post(x);
}
}
template <typename M>
static void Walk(IntrinsicTypeSpec::Character &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.selector, mutator);
mutator.Post(x);
}
}
template <typename V>
static void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template <typename M>
static void Walk(IntrinsicTypeSpec::Complex &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template <typename V>
static void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template <typename M>
static void Walk(IntrinsicTypeSpec::Logical &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template <typename V>
static void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template <typename M>
static void Walk(IntrinsicTypeSpec::Real &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template <typename A, typename B, typename V>
static void Walk(const LoopBounds<A, B> &x, V &visitor) {
if (visitor.Pre(x)) {
@ -486,18 +345,6 @@ struct ParseTreeVisitorLookupScope {
mutator.Post(x);
}
}
template <typename V> static void Walk(const CommonStmt &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.blocks, visitor);
visitor.Post(x);
}
}
template <typename M> static void Walk(CommonStmt &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.blocks, mutator);
mutator.Post(x);
}
}
// Expr traversal uses iteration rather than recursion to avoid
// blowing out the stack on very deep expression parse trees.

View File

@ -623,12 +623,12 @@ using ObjectName = Name;
// IMPORT [[::] import-name-list] |
// IMPORT , ONLY : import-name-list | IMPORT , NONE | IMPORT , ALL
struct ImportStmt {
BOILERPLATE(ImportStmt);
ImportStmt(common::ImportKind &&k) : kind{k} {}
ImportStmt(std::list<Name> &&n) : names(std::move(n)) {}
TUPLE_CLASS_BOILERPLATE(ImportStmt);
ImportStmt(common::ImportKind &&k) : t(k, std::list<Name>{}) {}
ImportStmt(std::list<Name> &&n)
: t(common::ImportKind::Default, std::move(n)) {}
ImportStmt(common::ImportKind &&, std::list<Name> &&);
common::ImportKind kind{common::ImportKind::Default};
std::list<Name> names;
std::tuple<common::ImportKind, std::list<Name>> t;
};
// R868 namelist-stmt ->
@ -686,11 +686,8 @@ struct LengthSelector {
struct CharSelector {
UNION_CLASS_BOILERPLATE(CharSelector);
struct LengthAndKind {
BOILERPLATE(LengthAndKind);
LengthAndKind(std::optional<TypeParamValue> &&l, ScalarIntConstantExpr &&k)
: length(std::move(l)), kind(std::move(k)) {}
std::optional<TypeParamValue> length;
ScalarIntConstantExpr kind;
TUPLE_CLASS_BOILERPLATE(LengthAndKind);
std::tuple<std::optional<TypeParamValue>, ScalarIntConstantExpr> t;
};
CharSelector(TypeParamValue &&l, ScalarIntConstantExpr &&k)
: u{LengthAndKind{std::make_optional(std::move(l)), std::move(k)}} {}
@ -707,25 +704,17 @@ struct CharSelector {
struct IntrinsicTypeSpec {
UNION_CLASS_BOILERPLATE(IntrinsicTypeSpec);
struct Real {
BOILERPLATE(Real);
Real(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
std::optional<KindSelector> kind;
WRAPPER_CLASS_BOILERPLATE(Real, std::optional<KindSelector>);
};
EMPTY_CLASS(DoublePrecision);
struct Complex {
BOILERPLATE(Complex);
Complex(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
std::optional<KindSelector> kind;
WRAPPER_CLASS_BOILERPLATE(Complex, std::optional<KindSelector>);
};
struct Character {
BOILERPLATE(Character);
Character(std::optional<CharSelector> &&s) : selector{std::move(s)} {}
std::optional<CharSelector> selector;
WRAPPER_CLASS_BOILERPLATE(Character, std::optional<CharSelector>);
};
struct Logical {
BOILERPLATE(Logical);
Logical(std::optional<KindSelector> &&k) : kind{std::move(k)} {}
std::optional<KindSelector> kind;
WRAPPER_CLASS_BOILERPLATE(Logical, std::optional<KindSelector>);
};
EMPTY_CLASS(DoubleComplex);
std::variant<IntegerTypeSpec, UnsignedTypeSpec, Real, DoublePrecision,
@ -774,16 +763,8 @@ struct TypeSpec {
// Legacy extension: RECORD /struct/
struct DeclarationTypeSpec {
UNION_CLASS_BOILERPLATE(DeclarationTypeSpec);
struct Type {
BOILERPLATE(Type);
Type(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
DerivedTypeSpec derived;
};
struct Class {
BOILERPLATE(Class);
Class(DerivedTypeSpec &&dt) : derived(std::move(dt)) {}
DerivedTypeSpec derived;
};
WRAPPER_CLASS(Type, DerivedTypeSpec);
WRAPPER_CLASS(Class, DerivedTypeSpec);
EMPTY_CLASS(ClassStar);
EMPTY_CLASS(TypeStar);
WRAPPER_CLASS(Record, Name);
@ -1274,12 +1255,9 @@ struct AcValue {
// R770 ac-spec -> type-spec :: | [type-spec ::] ac-value-list
struct AcSpec {
BOILERPLATE(AcSpec);
AcSpec(std::optional<TypeSpec> &&ts, std::list<AcValue> &&xs)
: type(std::move(ts)), values(std::move(xs)) {}
explicit AcSpec(TypeSpec &&ts) : type{std::move(ts)} {}
std::optional<TypeSpec> type;
std::list<AcValue> values;
TUPLE_CLASS_BOILERPLATE(AcSpec);
explicit AcSpec(TypeSpec &&ts) : t(std::move(ts), std::list<AcValue>()) {}
std::tuple<std::optional<TypeSpec>, std::list<AcValue>> t;
};
// R769 array-constructor -> (/ ac-spec /) | lbracket ac-spec rbracket
@ -1646,11 +1624,10 @@ struct CommonStmt {
TUPLE_CLASS_BOILERPLATE(Block);
std::tuple<std::optional<Name>, std::list<CommonBlockObject>> t;
};
BOILERPLATE(CommonStmt);
WRAPPER_CLASS_BOILERPLATE(CommonStmt, std::list<Block>);
CommonStmt(std::optional<Name> &&, std::list<CommonBlockObject> &&,
std::list<Block> &&);
CharBlock source;
std::list<Block> blocks;
};
// R872 equivalence-object -> variable-name | array-element | substring
@ -2416,10 +2393,9 @@ using CaseValue = Scalar<ConstantExpr>;
struct CaseValueRange {
UNION_CLASS_BOILERPLATE(CaseValueRange);
struct Range {
BOILERPLATE(Range);
Range(std::optional<CaseValue> &&l, std::optional<CaseValue> &&u)
: lower{std::move(l)}, upper{std::move(u)} {}
std::optional<CaseValue> lower, upper; // not both missing
TUPLE_CLASS_BOILERPLATE(Range);
std::tuple<std::optional<CaseValue>, std::optional<CaseValue>>
t; // not both missing
};
std::variant<CaseValue, Range> u;
};

View File

@ -4011,16 +4011,17 @@ private:
}
const auto &caseRange =
std::get<Fortran::parser::CaseValueRange::Range>(caseValueRange.u);
if (caseRange.lower && caseRange.upper) {
const auto &[lower, upper]{caseRange.t};
if (lower && upper) {
attrList.push_back(fir::ClosedIntervalAttr::get(context));
addValue(*caseRange.lower);
addValue(*caseRange.upper);
} else if (caseRange.lower) {
addValue(*lower);
addValue(*upper);
} else if (lower) {
attrList.push_back(fir::LowerBoundAttr::get(context));
addValue(*caseRange.lower);
addValue(*lower);
} else {
attrList.push_back(fir::UpperBoundAttr::get(context));
addValue(*caseRange.upper);
addValue(*upper);
}
}
}

View File

@ -22,7 +22,8 @@ namespace Fortran::parser {
// R867
ImportStmt::ImportStmt(common::ImportKind &&k, std::list<Name> &&n)
: kind{k}, names(std::move(n)) {
: t(k, std::move(n)) {
const auto &[kind, names]{t};
CHECK(kind == common::ImportKind::Default ||
kind == common::ImportKind::Only || names.empty());
}
@ -30,8 +31,8 @@ ImportStmt::ImportStmt(common::ImportKind &&k, std::list<Name> &&n)
// R873
CommonStmt::CommonStmt(std::optional<Name> &&name,
std::list<CommonBlockObject> &&objects, std::list<Block> &&others) {
blocks.emplace_front(std::move(name), std::move(objects));
blocks.splice(blocks.end(), std::move(others));
v.emplace_front(std::move(name), std::move(objects));
v.splice(v.end(), std::move(others));
}
// R901 designator

View File

@ -142,10 +142,10 @@ public:
void Post(const Star &) { Put('*'); } // R701 &c.
void Post(const TypeParamValue::Deferred &) { Put(':'); } // R701
void Unparse(const DeclarationTypeSpec::Type &x) { // R703
Word("TYPE("), Walk(x.derived), Put(')');
Word("TYPE("), Walk(x.v), Put(')');
}
void Unparse(const DeclarationTypeSpec::Class &x) {
Word("CLASS("), Walk(x.derived), Put(')');
Word("CLASS("), Walk(x.v), Put(')');
}
void Post(const DeclarationTypeSpec::ClassStar &) { Word("CLASS(*)"); }
void Post(const DeclarationTypeSpec::TypeStar &) { Word("TYPE(*)"); }
@ -204,8 +204,11 @@ public:
Put('('), Walk(x.t, ","), Put(')');
}
void Unparse(const CharSelector::LengthAndKind &x) { // R721
Put('('), Word("KIND="), Walk(x.kind);
Walk(", LEN=", x.length), Put(')');
Put('(');
Word("KIND=");
Walk(std::get<ScalarIntConstantExpr>(x.t));
Walk(", LEN=", std::get<std::optional<TypeParamValue>>(x.t));
Put(')');
}
void Unparse(const LengthSelector &x) { // R722
common::visit(common::visitors{
@ -430,7 +433,8 @@ public:
Put('['), Walk(x.v), Put(']');
}
void Unparse(const AcSpec &x) { // R770
Walk(x.type, "::"), Walk(x.values, ", ");
Walk(std::get<std::optional<TypeSpec>>(x.t), "::");
Walk(std::get<std::list<AcValue>>(x.t), ", ");
}
template <typename A, typename B> void Unparse(const LoopBounds<A, B> &x) {
Walk(x.name), Put('='), Walk(x.lower), Put(','), Walk(x.upper);
@ -723,14 +727,15 @@ public:
}
}
void Unparse(const ImportStmt &x) { // R867
const auto &[kind, names]{x.t};
Word("IMPORT");
switch (x.kind) {
switch (kind) {
case common::ImportKind::Default:
Walk(" :: ", x.names, ", ");
Walk(" :: ", names, ", ");
break;
case common::ImportKind::Only:
Put(", "), Word("ONLY: ");
Walk(x.names, ", ");
Walk(names, ", ");
break;
case common::ImportKind::None:
Word(", NONE");
@ -757,7 +762,7 @@ public:
}
void Unparse(const CommonStmt &x) { // R873
Word("COMMON ");
Walk(x.blocks);
Walk(x.v);
}
void Unparse(const CommonBlockObject &x) { // R874
Walk(std::get<Name>(x.t));
@ -1103,7 +1108,8 @@ public:
x.u);
}
void Unparse(const CaseValueRange::Range &x) { // R1146
Walk(x.lower), Put(':'), Walk(x.upper);
const auto &[lower, upper]{x.t};
Walk(lower), Put(':'), Walk(upper);
}
void Unparse(const SelectRankStmt &x) { // R1149
Walk(std::get<0>(x.t), ": ");

View File

@ -117,26 +117,27 @@ private:
using PairOfValues = std::pair<std::optional<Value>, std::optional<Value>>;
PairOfValues ComputeBounds(const parser::CaseValueRange &range) {
return common::visit(
common::visitors{
[&](const parser::CaseValue &x) {
auto value{GetValue(x)};
return PairOfValues{value, value};
},
[&](const parser::CaseValueRange::Range &x) {
std::optional<Value> lo, hi;
if (x.lower) {
lo = GetValue(*x.lower);
}
if (x.upper) {
hi = GetValue(*x.upper);
}
if ((x.lower && !lo) || (x.upper && !hi)) {
return PairOfValues{}; // error case
}
return PairOfValues{std::move(lo), std::move(hi)};
},
},
return common::visit(common::visitors{
[&](const parser::CaseValue &x) {
auto value{GetValue(x)};
return PairOfValues{value, value};
},
[&](const parser::CaseValueRange::Range &x) {
const auto &[lower, upper]{x.t};
std::optional<Value> lo, hi;
if (lower) {
lo = GetValue(*lower);
}
if (upper) {
hi = GetValue(*upper);
}
if ((lower && !lo) || (upper && !hi)) {
return PairOfValues{}; // error case
}
return PairOfValues{
std::move(lo), std::move(hi)};
},
},
range.u);
}

View File

@ -2076,10 +2076,11 @@ MaybeExpr ArrayConstructorContext::ToExpr() {
MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
const parser::AcSpec &acSpec{array.v};
const auto &[type, values]{acSpec.t};
bool hadAnyFatalError{context_.AnyFatalError()};
ArrayConstructorContext acContext{
*this, AnalyzeTypeSpec(acSpec.type, GetFoldingContext())};
for (const parser::AcValue &value : acSpec.values) {
*this, AnalyzeTypeSpec(type, GetFoldingContext())};
for (const parser::AcValue &value : values) {
acContext.Add(value);
}
if (!hadAnyFatalError && context_.AnyFatalError()) {

View File

@ -6138,14 +6138,14 @@ void DeclarationVisitor::Post(const parser::UnsignedTypeSpec &x) {
}
void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Real &x) {
if (!isVectorType_) {
SetDeclTypeSpec(MakeNumericType(TypeCategory::Real, x.kind));
SetDeclTypeSpec(MakeNumericType(TypeCategory::Real, x.v));
}
}
void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Complex &x) {
SetDeclTypeSpec(MakeNumericType(TypeCategory::Complex, x.kind));
SetDeclTypeSpec(MakeNumericType(TypeCategory::Complex, x.v));
}
void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Logical &x) {
SetDeclTypeSpec(MakeLogicalType(x.kind));
SetDeclTypeSpec(MakeLogicalType(x.v));
}
void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Character &) {
if (!charInfo_.length) {
@ -6160,7 +6160,8 @@ void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Character &) {
charInfo_ = {};
}
void DeclarationVisitor::Post(const parser::CharSelector::LengthAndKind &x) {
charInfo_.kind = EvaluateSubscriptIntExpr(x.kind);
const auto &[length, kind]{x.t};
charInfo_.kind = EvaluateSubscriptIntExpr(kind);
std::optional<std::int64_t> intKind{ToInt64(charInfo_.kind)};
if (intKind &&
!context().targetCharacteristics().IsTypeEnabled(
@ -6169,8 +6170,8 @@ void DeclarationVisitor::Post(const parser::CharSelector::LengthAndKind &x) {
"KIND value (%jd) not valid for CHARACTER"_err_en_US, *intKind);
charInfo_.kind = std::nullopt; // prevent further errors
}
if (x.length) {
charInfo_.length = GetParamValue(*x.length, common::TypeParamAttr::Len);
if (length) {
charInfo_.length = GetParamValue(*length, common::TypeParamAttr::Len);
}
}
void DeclarationVisitor::Post(const parser::CharLength &x) {
@ -6245,7 +6246,7 @@ void DeclarationVisitor::Post(const parser::VectorTypeSpec &x) {
},
[&](const parser::IntrinsicTypeSpec::Real &z) {
vecElemKind = GetVectorElementKind(
TypeCategory::Real, std::move(z.kind));
TypeCategory::Real, std::move(z.v));
typeParams.push_back(
ParamValue(static_cast<common::ConstantSubscript>(
common::VectorElementCategory::Real),
@ -6321,7 +6322,7 @@ bool DeclarationVisitor::Pre(const parser::DeclarationTypeSpec::Type &) {
}
void DeclarationVisitor::Post(const parser::DeclarationTypeSpec::Type &type) {
const parser::Name &derivedName{std::get<parser::Name>(type.derived.t)};
const parser::Name &derivedName{std::get<parser::Name>(type.v.t)};
if (const Symbol * derivedSymbol{derivedName.symbol}) {
CheckForAbstractType(*derivedSymbol); // C706
}
@ -6334,7 +6335,7 @@ bool DeclarationVisitor::Pre(const parser::DeclarationTypeSpec::Class &) {
void DeclarationVisitor::Post(
const parser::DeclarationTypeSpec::Class &parsedClass) {
const auto &typeName{std::get<parser::Name>(parsedClass.derived.t)};
const auto &typeName{std::get<parser::Name>(parsedClass.v.t)};
if (auto spec{ResolveDerivedType(typeName)};
spec && !IsExtensibleType(&*spec)) { // C705
SayWithDecl(typeName, *typeName.symbol,
@ -7893,8 +7894,9 @@ bool ConstructVisitor::Pre(const parser::LocalitySpec::Shared &x) {
}
bool ConstructVisitor::Pre(const parser::AcSpec &x) {
ProcessTypeSpec(x.type);
Walk(x.values);
const auto &[type, values]{x.t};
ProcessTypeSpec(type);
Walk(values);
return false;
}
@ -8492,12 +8494,12 @@ public:
return true;
}
void Post(const parser::ImportStmt &x) {
if (x.kind == common::ImportKind::None ||
x.kind == common::ImportKind::Only) {
const auto &[kind, names]{x.t};
if (kind == common::ImportKind::None || kind == common::ImportKind::Only) {
if (!nestedScopes_.front().importOnly.has_value()) {
nestedScopes_.front().importOnly.emplace();
}
for (const auto &name : x.names) {
for (const auto &name : names) {
nestedScopes_.front().importOnly->emplace(name.source);
}
} else {
@ -8709,6 +8711,7 @@ bool ResolveNamesVisitor::Pre(const parser::CallStmt &x) {
}
bool ResolveNamesVisitor::Pre(const parser::ImportStmt &x) {
const auto &[kind, names]{x.t};
auto &scope{currScope()};
// Check C896 and C899: where IMPORT statements are allowed
switch (scope.kind()) {
@ -8716,7 +8719,7 @@ bool ResolveNamesVisitor::Pre(const parser::ImportStmt &x) {
if (scope.IsModule()) {
Say("IMPORT is not allowed in a module scoping unit"_err_en_US);
return false;
} else if (x.kind == common::ImportKind::None) {
} else if (kind == common::ImportKind::None) {
Say("IMPORT,NONE is not allowed in a submodule scoping unit"_err_en_US);
return false;
}
@ -8735,10 +8738,10 @@ bool ResolveNamesVisitor::Pre(const parser::ImportStmt &x) {
return false;
default:;
}
if (auto error{scope.SetImportKind(x.kind)}) {
if (auto error{scope.SetImportKind(kind)}) {
Say(std::move(*error));
}
for (auto &name : x.names) {
for (auto &name : names) {
if (Symbol * outer{FindSymbol(scope.parent(), name)}) {
scope.add_importName(name.source);
if (Symbol * symbol{FindInScope(name)}) {
@ -9613,10 +9616,10 @@ void ResolveNamesVisitor::HandleDerivedTypesInImplicitStmts(
if (const auto *dtSpec{common::visit(
common::visitors{
[](const parser::DeclarationTypeSpec::Type &x) {
return &x.derived;
return &x.v;
},
[](const parser::DeclarationTypeSpec::Class &x) {
return &x.derived;
return &x.v;
},
[](const auto &) -> const parser::DerivedTypeSpec * {
return nullptr;
@ -9783,7 +9786,7 @@ void ResolveNamesVisitor::EarlyDummyTypeDeclaration(
void ResolveNamesVisitor::CreateCommonBlockSymbols(
const parser::CommonStmt &commonStmt) {
for (const parser::CommonStmt::Block &block : commonStmt.blocks) {
for (const parser::CommonStmt::Block &block : commonStmt.v) {
const auto &[name, objects] = block.t;
Symbol &commonBlock{MakeCommonBlockSymbol(name, commonStmt.source)};
for (const auto &object : objects) {