[flang-commits] [flang] [flang] Add traits to several AST nodes (PR #175065)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Thu Jan 8 13:09:18 PST 2026
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/175065
>From 539ae71c5e92a885aa3869f87d7d16489eb76f4e Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 7 Jan 2026 14:08:03 -0600
Subject: [PATCH 1/3] [flang] Add traits to several AST nodes, NFC
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.
---
flang/include/flang/Parser/dump-parse-tree.h | 1 +
.../include/flang/Parser/parse-tree-visitor.h | 153 ------------------
flang/include/flang/Parser/parse-tree.h | 64 +++-----
flang/lib/Lower/Bridge.cpp | 13 +-
flang/lib/Parser/parse-tree.cpp | 7 +-
flang/lib/Parser/unparse.cpp | 26 +--
flang/lib/Semantics/check-case.cpp | 11 +-
flang/lib/Semantics/expression.cpp | 5 +-
flang/lib/Semantics/resolve-names.cpp | 44 ++---
9 files changed, 81 insertions(+), 243 deletions(-)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 466cec9003038..f6e4cce241ad3 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -64,6 +64,7 @@ class ParseTreeDumper {
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)
diff --git a/flang/include/flang/Parser/parse-tree-visitor.h b/flang/include/flang/Parser/parse-tree-visitor.h
index 7ebce671c5fd1..67f5481144c52 100644
--- a/flang/include/flang/Parser/parse-tree-visitor.h
+++ b/flang/include/flang/Parser/parse-tree-visitor.h
@@ -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.
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 2ab640ed351d8..37c0f699361eb 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -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;
};
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 6c3631438a596..5570e07501ee9 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -4011,16 +4011,17 @@ class FirConverter : public Fortran::lower::AbstractConverter {
}
const auto &caseRange =
std::get<Fortran::parser::CaseValueRange::Range>(caseValueRange.u);
- if (caseRange.lower && caseRange.upper) {
+ 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);
}
}
}
diff --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp
index 53d4e4e680caa..4783a4e3b635e 100644
--- a/flang/lib/Parser/parse-tree.cpp
+++ b/flang/lib/Parser/parse-tree.cpp
@@ -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)) {
+ 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
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 0a6b0cdf88efa..812ed9ac58e6f 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -142,10 +142,10 @@ class UnparseVisitor {
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 @@ class UnparseVisitor {
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 @@ class UnparseVisitor {
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 @@ class UnparseVisitor {
}
}
void Unparse(const ImportStmt &x) { // R867
+ 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 @@ class UnparseVisitor {
}
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 @@ class UnparseVisitor {
x.u);
}
void Unparse(const CaseValueRange::Range &x) { // R1146
- Walk(x.lower), Put(':'), Walk(x.upper);
+ auto &[lower, upper]{x.t};
+ Walk(lower), Put(':'), Walk(upper);
}
void Unparse(const SelectRankStmt &x) { // R1149
Walk(std::get<0>(x.t), ": ");
diff --git a/flang/lib/Semantics/check-case.cpp b/flang/lib/Semantics/check-case.cpp
index 7593154b84c4c..1b00db91b83f2 100644
--- a/flang/lib/Semantics/check-case.cpp
+++ b/flang/lib/Semantics/check-case.cpp
@@ -124,14 +124,15 @@ template <typename T> class CaseValues {
return PairOfValues{value, value};
},
[&](const parser::CaseValueRange::Range &x) {
+ auto &[lower, upper]{x.t};
std::optional<Value> lo, hi;
- if (x.lower) {
- lo = GetValue(*x.lower);
+ if (lower) {
+ lo = GetValue(*lower);
}
- if (x.upper) {
- hi = GetValue(*x.upper);
+ if (upper) {
+ hi = GetValue(*upper);
}
- if ((x.lower && !lo) || (x.upper && !hi)) {
+ if ((lower && !lo) || (upper && !hi)) {
return PairOfValues{}; // error case
}
return PairOfValues{std::move(lo), std::move(hi)};
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 6e301e6ba752a..1a6b3956dacd6 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -2076,10 +2076,11 @@ MaybeExpr ArrayConstructorContext::ToExpr() {
MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
const parser::AcSpec &acSpec{array.v};
+ 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()) {
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index ae251476ed591..6d1f87f2eb0cc 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -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);
+ 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);
+ auto &[type, values]{x.t};
+ ProcessTypeSpec(type);
+ Walk(values);
return false;
}
@@ -8492,12 +8494,13 @@ class ExecutionPartSkimmerBase {
return true;
}
void Post(const parser::ImportStmt &x) {
- if (x.kind == common::ImportKind::None ||
- x.kind == common::ImportKind::Only) {
+ 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 +8712,7 @@ bool ResolveNamesVisitor::Pre(const parser::CallStmt &x) {
}
bool ResolveNamesVisitor::Pre(const parser::ImportStmt &x) {
+ auto &[kind, names]{x.t};
auto &scope{currScope()};
// Check C896 and C899: where IMPORT statements are allowed
switch (scope.kind()) {
@@ -8716,7 +8720,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 +8739,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 +9617,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 +9787,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) {
>From 2a5bdc63ac479fb7f39e5472186ee7cab1d4e7d5 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 8 Jan 2026 14:46:16 -0600
Subject: [PATCH 2/3] format
---
flang/lib/Semantics/check-case.cpp | 42 +++++++++++++--------------
flang/lib/Semantics/resolve-names.cpp | 3 +-
2 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/flang/lib/Semantics/check-case.cpp b/flang/lib/Semantics/check-case.cpp
index 1b00db91b83f2..e102257e83211 100644
--- a/flang/lib/Semantics/check-case.cpp
+++ b/flang/lib/Semantics/check-case.cpp
@@ -117,27 +117,27 @@ template <typename T> class CaseValues {
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) {
- 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)};
- },
- },
+ return common::visit(common::visitors{
+ [&](const parser::CaseValue &x) {
+ auto value{GetValue(x)};
+ return PairOfValues{value, value};
+ },
+ [&](const parser::CaseValueRange::Range &x) {
+ 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);
}
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 6d1f87f2eb0cc..e7f1eb1f41891 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -8495,8 +8495,7 @@ class ExecutionPartSkimmerBase {
}
void Post(const parser::ImportStmt &x) {
auto &[kind, names]{x.t};
- if (kind == common::ImportKind::None ||
- kind == common::ImportKind::Only) {
+ if (kind == common::ImportKind::None || kind == common::ImportKind::Only) {
if (!nestedScopes_.front().importOnly.has_value()) {
nestedScopes_.front().importOnly.emplace();
}
>From 36824e29df9415373b122e08c8cc70ba82aceab0 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 8 Jan 2026 15:07:54 -0600
Subject: [PATCH 3/3] Use "const auto &"
---
flang/lib/Lower/Bridge.cpp | 2 +-
flang/lib/Parser/parse-tree.cpp | 2 +-
flang/lib/Parser/unparse.cpp | 4 ++--
flang/lib/Semantics/check-case.cpp | 2 +-
flang/lib/Semantics/expression.cpp | 2 +-
flang/lib/Semantics/resolve-names.cpp | 8 ++++----
6 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 5570e07501ee9..9224bc2be1028 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -4011,7 +4011,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
}
const auto &caseRange =
std::get<Fortran::parser::CaseValueRange::Range>(caseValueRange.u);
- auto &[lower, upper]{caseRange.t};
+ const auto &[lower, upper]{caseRange.t};
if (lower && upper) {
attrList.push_back(fir::ClosedIntervalAttr::get(context));
addValue(*lower);
diff --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp
index 4783a4e3b635e..dae1912afa99e 100644
--- a/flang/lib/Parser/parse-tree.cpp
+++ b/flang/lib/Parser/parse-tree.cpp
@@ -23,7 +23,7 @@ namespace Fortran::parser {
// R867
ImportStmt::ImportStmt(common::ImportKind &&k, std::list<Name> &&n)
: t(k, std::move(n)) {
- auto &[kind, names]{t};
+ const auto &[kind, names]{t};
CHECK(kind == common::ImportKind::Default ||
kind == common::ImportKind::Only || names.empty());
}
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 812ed9ac58e6f..9b31454537df5 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -727,7 +727,7 @@ class UnparseVisitor {
}
}
void Unparse(const ImportStmt &x) { // R867
- auto &[kind, names]{x.t};
+ const auto &[kind, names]{x.t};
Word("IMPORT");
switch (kind) {
case common::ImportKind::Default:
@@ -1108,7 +1108,7 @@ class UnparseVisitor {
x.u);
}
void Unparse(const CaseValueRange::Range &x) { // R1146
- auto &[lower, upper]{x.t};
+ const auto &[lower, upper]{x.t};
Walk(lower), Put(':'), Walk(upper);
}
void Unparse(const SelectRankStmt &x) { // R1149
diff --git a/flang/lib/Semantics/check-case.cpp b/flang/lib/Semantics/check-case.cpp
index e102257e83211..9004d8b3a28f9 100644
--- a/flang/lib/Semantics/check-case.cpp
+++ b/flang/lib/Semantics/check-case.cpp
@@ -123,7 +123,7 @@ template <typename T> class CaseValues {
return PairOfValues{value, value};
},
[&](const parser::CaseValueRange::Range &x) {
- auto &[lower, upper]{x.t};
+ const auto &[lower, upper]{x.t};
std::optional<Value> lo, hi;
if (lower) {
lo = GetValue(*lower);
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 1a6b3956dacd6..b3643e0d35d5f 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -2076,7 +2076,7 @@ MaybeExpr ArrayConstructorContext::ToExpr() {
MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
const parser::AcSpec &acSpec{array.v};
- auto &[type, values]{acSpec.t};
+ const auto &[type, values]{acSpec.t};
bool hadAnyFatalError{context_.AnyFatalError()};
ArrayConstructorContext acContext{
*this, AnalyzeTypeSpec(type, GetFoldingContext())};
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index e7f1eb1f41891..8086e43b90f20 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -6160,7 +6160,7 @@ void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Character &) {
charInfo_ = {};
}
void DeclarationVisitor::Post(const parser::CharSelector::LengthAndKind &x) {
- auto &[length, kind]{x.t};
+ const auto &[length, kind]{x.t};
charInfo_.kind = EvaluateSubscriptIntExpr(kind);
std::optional<std::int64_t> intKind{ToInt64(charInfo_.kind)};
if (intKind &&
@@ -7894,7 +7894,7 @@ bool ConstructVisitor::Pre(const parser::LocalitySpec::Shared &x) {
}
bool ConstructVisitor::Pre(const parser::AcSpec &x) {
- auto &[type, values]{x.t};
+ const auto &[type, values]{x.t};
ProcessTypeSpec(type);
Walk(values);
return false;
@@ -8494,7 +8494,7 @@ class ExecutionPartSkimmerBase {
return true;
}
void Post(const parser::ImportStmt &x) {
- auto &[kind, names]{x.t};
+ 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();
@@ -8711,7 +8711,7 @@ bool ResolveNamesVisitor::Pre(const parser::CallStmt &x) {
}
bool ResolveNamesVisitor::Pre(const parser::ImportStmt &x) {
- auto &[kind, names]{x.t};
+ const auto &[kind, names]{x.t};
auto &scope{currScope()};
// Check C896 and C899: where IMPORT statements are allowed
switch (scope.kind()) {
More information about the flang-commits
mailing list