Skip to content

Commit 53e9dc6

Browse files
committed
[flang] Rework component KIND= values in PDT instantiations
When processing the KIND= values of type specifications in parameterized derived type component declarations, it turns out to be necessary to analyze their expressions' parse trees rather than to just fold their typed expression representations. The types of the subexpressions may depend on the values of KIND parameters. Further, when checking the values of KIND= actual arguments to type conversion intrinsic functions (e.g., INT(..., KIND=)) that appear in KIND specifiers for PDT component declarations, don't emit an error for the derived type definition, but instead emit them for derived type instantiations. Fixes #161961.
1 parent 2e67f5c commit 53e9dc6

File tree

10 files changed

+154
-39
lines changed

10 files changed

+154
-39
lines changed

flang/include/flang/Evaluate/common.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,20 @@ class FoldingContext {
231231
: messages_{that.messages_}, defaults_{that.defaults_},
232232
intrinsics_{that.intrinsics_},
233233
targetCharacteristics_{that.targetCharacteristics_},
234-
pdtInstance_{that.pdtInstance_}, impliedDos_{that.impliedDos_},
234+
pdtInstance_{that.pdtInstance_},
235+
analyzingPDTComponentKindSelector_{
236+
that.analyzingPDTComponentKindSelector_},
237+
impliedDos_{that.impliedDos_},
235238
languageFeatures_{that.languageFeatures_}, tempNames_{that.tempNames_} {
236239
}
237240
FoldingContext(
238241
const FoldingContext &that, const parser::ContextualMessages &m)
239242
: messages_{m}, defaults_{that.defaults_}, intrinsics_{that.intrinsics_},
240243
targetCharacteristics_{that.targetCharacteristics_},
241-
pdtInstance_{that.pdtInstance_}, impliedDos_{that.impliedDos_},
244+
pdtInstance_{that.pdtInstance_},
245+
analyzingPDTComponentKindSelector_{
246+
that.analyzingPDTComponentKindSelector_},
247+
impliedDos_{that.impliedDos_},
242248
languageFeatures_{that.languageFeatures_}, tempNames_{that.tempNames_} {
243249
}
244250

@@ -248,6 +254,9 @@ class FoldingContext {
248254
return defaults_;
249255
}
250256
const semantics::DerivedTypeSpec *pdtInstance() const { return pdtInstance_; }
257+
bool analyzingPDTComponentKindSelector() const {
258+
return analyzingPDTComponentKindSelector_;
259+
}
251260
const IntrinsicProcTable &intrinsics() const { return intrinsics_; }
252261
const TargetCharacteristics &targetCharacteristics() const {
253262
return targetCharacteristics_;
@@ -290,6 +299,10 @@ class FoldingContext {
290299
return common::ScopedSet(pdtInstance_, nullptr);
291300
}
292301

302+
common::Restorer<bool> AnalyzingPDTComponentKindSelector() {
303+
return common::ScopedSet(analyzingPDTComponentKindSelector_, true);
304+
}
305+
293306
parser::CharBlock SaveTempName(std::string &&name) {
294307
return {*tempNames_.emplace(std::move(name)).first};
295308
}
@@ -300,6 +313,7 @@ class FoldingContext {
300313
const IntrinsicProcTable &intrinsics_;
301314
const TargetCharacteristics &targetCharacteristics_;
302315
const semantics::DerivedTypeSpec *pdtInstance_{nullptr};
316+
bool analyzingPDTComponentKindSelector_{false};
303317
std::optional<parser::CharBlock> moduleFileName_;
304318
std::map<parser::CharBlock, ConstantSubscript> impliedDos_;
305319
const common::LanguageFeatureControl &languageFeatures_;

flang/include/flang/Semantics/symbol.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,11 @@ class DerivedTypeDetails {
510510
const std::list<SourceName> &componentNames() const {
511511
return componentNames_;
512512
}
513+
const std::map<SourceName, const parser::Expr *> &
514+
originalKindParameterMap() const {
515+
return originalKindParameterMap_;
516+
}
517+
void add_originalKindParameter(SourceName, const parser::Expr *);
513518

514519
// If this derived type extends another, locate the parent component's symbol.
515520
const Symbol *GetParentComponent(const Scope &) const;
@@ -538,6 +543,8 @@ class DerivedTypeDetails {
538543
bool sequence_{false};
539544
bool isDECStructure_{false};
540545
bool isForwardReferenced_{false};
546+
std::map<SourceName, const parser::Expr *> originalKindParameterMap_;
547+
541548
friend llvm::raw_ostream &operator<<(
542549
llvm::raw_ostream &, const DerivedTypeDetails &);
543550
};

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,7 +2515,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
25152515
CHECK(kindDummyArg);
25162516
CHECK(result.categorySet == CategorySet{*category});
25172517
if (kindArg) {
2518-
if (auto *expr{kindArg->UnwrapExpr()}) {
2518+
auto *expr{kindArg->UnwrapExpr()};
2519+
if (expr) {
25192520
CHECK(expr->Rank() == 0);
25202521
if (auto code{ToInt64(Fold(context, common::Clone(*expr)))}) {
25212522
if (context.targetCharacteristics().IsTypeEnabled(
@@ -2529,8 +2530,16 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
25292530
}
25302531
}
25312532
}
2532-
messages.Say(
2533-
"'kind=' argument must be a constant scalar integer whose value is a supported kind for the intrinsic result type"_err_en_US);
2533+
if (context.analyzingPDTComponentKindSelector() && expr &&
2534+
IsConstantExpr(*expr)) {
2535+
// Don't emit an error about a KIND= actual argument value when
2536+
// processing a kind selector in a PDT component declaration before
2537+
// it is instantianted, so long as it's a constant expression.
2538+
// It will be renanalyzed later during instantiation.
2539+
} else {
2540+
messages.Say(
2541+
"'kind=' argument must be a constant scalar integer whose value is a supported kind for the intrinsic result type"_err_en_US);
2542+
}
25342543
// use default kind below for error recovery
25352544
} else if (kindDummyArg->flags.test(ArgFlag::defaultsToSameKind)) {
25362545
CHECK(sameArg);

flang/lib/Semantics/resolve-names.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ class DeclTypeSpecVisitor : public AttrsVisitor {
357357
DeclTypeSpec::Category category{DeclTypeSpec::TypeDerived};
358358
} derived;
359359
bool allowForwardReferenceToDerivedType{false};
360+
const parser::Expr *originalKindParameter{nullptr};
360361
};
361362

362363
bool allowForwardReferenceToDerivedType() const {
@@ -365,8 +366,10 @@ class DeclTypeSpecVisitor : public AttrsVisitor {
365366
void set_allowForwardReferenceToDerivedType(bool yes) {
366367
state_.allowForwardReferenceToDerivedType = yes;
367368
}
369+
void set_inPDTDefinition(bool yes) { inPDTDefinition_ = yes; }
368370

369-
const DeclTypeSpec *GetDeclTypeSpec();
371+
const DeclTypeSpec *GetDeclTypeSpec() const;
372+
const parser::Expr *GetOriginalKindParameter() const;
370373
void BeginDeclTypeSpec();
371374
void EndDeclTypeSpec();
372375
void SetDeclTypeSpec(const DeclTypeSpec &);
@@ -380,6 +383,7 @@ class DeclTypeSpecVisitor : public AttrsVisitor {
380383

381384
private:
382385
State state_;
386+
bool inPDTDefinition_{false};
383387

384388
void MakeNumericType(TypeCategory, int kind);
385389
};
@@ -2454,9 +2458,12 @@ bool AttrsVisitor::Pre(const common::CUDADataAttr x) {
24542458

24552459
// DeclTypeSpecVisitor implementation
24562460

2457-
const DeclTypeSpec *DeclTypeSpecVisitor::GetDeclTypeSpec() {
2461+
const DeclTypeSpec *DeclTypeSpecVisitor::GetDeclTypeSpec() const {
24582462
return state_.declTypeSpec;
24592463
}
2464+
const parser::Expr *DeclTypeSpecVisitor::GetOriginalKindParameter() const {
2465+
return state_.originalKindParameter;
2466+
}
24602467

24612468
void DeclTypeSpecVisitor::BeginDeclTypeSpec() {
24622469
CHECK(!state_.expectDeclTypeSpec);
@@ -2541,6 +2548,21 @@ void DeclTypeSpecVisitor::SetDeclTypeSpec(const DeclTypeSpec &declTypeSpec) {
25412548

25422549
KindExpr DeclTypeSpecVisitor::GetKindParamExpr(
25432550
TypeCategory category, const std::optional<parser::KindSelector> &kind) {
2551+
if (inPDTDefinition_) {
2552+
if (category != TypeCategory::Derived && kind) {
2553+
if (const auto *expr{
2554+
std::get_if<parser::ScalarIntConstantExpr>(&kind->u)}) {
2555+
CHECK(!state_.originalKindParameter);
2556+
// Save a pointer to the KIND= expression in the parse tree
2557+
// in case we need to reanalyze it during PDT instantiation.
2558+
state_.originalKindParameter = &expr->thing.thing.thing.value();
2559+
}
2560+
}
2561+
// Inhibit some errors now that will be caught later during instantiations.
2562+
auto restorer{
2563+
context().foldingContext().AnalyzingPDTComponentKindSelector()};
2564+
return AnalyzeKindSelector(context(), category, kind);
2565+
}
25442566
return AnalyzeKindSelector(context(), category, kind);
25452567
}
25462568

@@ -6410,6 +6432,7 @@ bool DeclarationVisitor::Pre(const parser::DerivedTypeDef &x) {
64106432
details.set_isForwardReferenced(false);
64116433
derivedTypeInfo_ = {};
64126434
PopScope();
6435+
set_inPDTDefinition(false);
64136436
return false;
64146437
}
64156438

@@ -6437,6 +6460,10 @@ void DeclarationVisitor::Post(const parser::DerivedTypeStmt &x) {
64376460
// component without producing spurious errors about already
64386461
// existing.
64396462
const Symbol &extendsSymbol{extendsType->typeSymbol()};
6463+
if (extendsSymbol.scope() &&
6464+
extendsSymbol.scope()->IsParameterizedDerivedType()) {
6465+
set_inPDTDefinition(true);
6466+
}
64406467
auto restorer{common::ScopedSet(extendsName->symbol, nullptr)};
64416468
if (OkToAddComponent(*extendsName, &extendsSymbol)) {
64426469
auto &comp{DeclareEntity<ObjectEntityDetails>(*extendsName, Attrs{})};
@@ -6455,8 +6482,12 @@ void DeclarationVisitor::Post(const parser::DerivedTypeStmt &x) {
64556482
}
64566483
// Create symbols now for type parameters so that they shadow names
64576484
// from the enclosing specification part.
6485+
const auto &paramNames{std::get<std::list<parser::Name>>(x.t)};
6486+
if (!paramNames.empty()) {
6487+
set_inPDTDefinition(true);
6488+
}
64586489
if (auto *details{symbol.detailsIf<DerivedTypeDetails>()}) {
6459-
for (const auto &name : std::get<std::list<parser::Name>>(x.t)) {
6490+
for (const auto &name : paramNames) {
64606491
if (Symbol * symbol{MakeTypeSymbol(name, TypeParamDetails{})}) {
64616492
details->add_paramNameOrder(*symbol);
64626493
}
@@ -6544,8 +6575,7 @@ void DeclarationVisitor::Post(const parser::ComponentDecl &x) {
65446575
if (const auto *derived{declType->AsDerived()}) {
65456576
if (!attrs.HasAny({Attr::POINTER, Attr::ALLOCATABLE})) {
65466577
if (derivedTypeInfo_.type == &derived->typeSymbol()) { // C744
6547-
Say("Recursive use of the derived type requires "
6548-
"POINTER or ALLOCATABLE"_err_en_US);
6578+
Say("Recursive use of the derived type requires POINTER or ALLOCATABLE"_err_en_US);
65496579
}
65506580
}
65516581
}
@@ -6558,7 +6588,11 @@ void DeclarationVisitor::Post(const parser::ComponentDecl &x) {
65586588
Initialization(name, *init, /*inComponentDecl=*/true);
65596589
}
65606590
}
6561-
currScope().symbol()->get<DerivedTypeDetails>().add_component(symbol);
6591+
auto &details{currScope().symbol()->get<DerivedTypeDetails>()};
6592+
details.add_component(symbol);
6593+
if (const parser::Expr *kindExpr{GetOriginalKindParameter()}) {
6594+
details.add_originalKindParameter(name.source, kindExpr);
6595+
}
65626596
}
65636597
ClearArraySpec();
65646598
ClearCoarraySpec();

flang/lib/Semantics/symbol.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,11 @@ void DerivedTypeDetails::add_component(const Symbol &symbol) {
769769
componentNames_.push_back(symbol.name());
770770
}
771771

772+
void DerivedTypeDetails::add_originalKindParameter(
773+
SourceName name, const parser::Expr *expr) {
774+
originalKindParameterMap_.emplace(name, expr);
775+
}
776+
772777
const Symbol *DerivedTypeDetails::GetParentComponent(const Scope &scope) const {
773778
if (auto extends{GetParentComponentName()}) {
774779
if (auto iter{scope.find(*extends)}; iter != scope.cend()) {

flang/lib/Semantics/type.cpp

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -443,9 +443,9 @@ void InstantiateHelper::InstantiateComponents(const Scope &fromScope) {
443443
// Walks a parsed expression to prepare it for (re)analysis;
444444
// clears out the typedExpr analysis results and re-resolves
445445
// symbol table pointers of type parameters.
446-
class ComponentInitResetHelper {
446+
class ResetHelper {
447447
public:
448-
explicit ComponentInitResetHelper(Scope &scope) : scope_{scope} {}
448+
explicit ResetHelper(Scope &scope) : scope_{scope} {}
449449

450450
template <typename A> bool Pre(const A &) { return true; }
451451

@@ -498,7 +498,7 @@ void InstantiateHelper::InstantiateComponent(const Symbol &oldSymbol) {
498498
}
499499
if (const auto *parsedExpr{details->unanalyzedPDTComponentInit()}) {
500500
// Analyze the parsed expression in this PDT instantiation context.
501-
ComponentInitResetHelper resetter{scope_};
501+
ResetHelper resetter{scope_};
502502
parser::Walk(*parsedExpr, resetter);
503503
auto restorer{foldingContext().messages().SetLocation(newSymbol.name())};
504504
details->set_init(evaluate::Fold(
@@ -564,16 +564,42 @@ static ParamValue FoldCharacterLength(evaluate::FoldingContext &foldingContext,
564564
// Apply type parameter values to an intrinsic type spec.
565565
const DeclTypeSpec &InstantiateHelper::InstantiateIntrinsicType(
566566
SourceName symbolName, const DeclTypeSpec &spec) {
567+
const parser::Expr *originalKindExpr{nullptr};
568+
if (const DerivedTypeSpec *derived{scope_.derivedTypeSpec()}) {
569+
if (const auto *details{
570+
derived->originalTypeSymbol().detailsIf<DerivedTypeDetails>()}) {
571+
const auto &originalKindMap{details->originalKindParameterMap()};
572+
if (auto iter{originalKindMap.find(symbolName)};
573+
iter != originalKindMap.end()) {
574+
originalKindExpr = iter->second;
575+
}
576+
}
577+
}
567578
const IntrinsicTypeSpec &intrinsic{DEREF(spec.AsIntrinsic())};
568-
if (spec.category() != DeclTypeSpec::Character &&
579+
if (spec.category() != DeclTypeSpec::Character && !originalKindExpr &&
569580
evaluate::IsActuallyConstant(intrinsic.kind())) {
570581
return spec; // KIND is already a known constant
571582
}
572583
// The expression was not originally constant, but now it must be so
573584
// in the context of a parameterized derived type instantiation.
574-
KindExpr copy{Fold(common::Clone(intrinsic.kind()))};
585+
std::optional<KindExpr> kindExpr;
586+
if (originalKindExpr) {
587+
ResetHelper resetter{scope_};
588+
parser::Walk(*originalKindExpr, resetter);
589+
if (MaybeExpr analyzed{AnalyzeExpr(scope_.context(), *originalKindExpr)}) {
590+
if (auto *intExpr{evaluate::UnwrapExpr<SomeIntExpr>(*analyzed)}) {
591+
kindExpr = evaluate::ConvertToType<evaluate::SubscriptInteger>(
592+
std::move(*intExpr));
593+
}
594+
}
595+
}
596+
if (!kindExpr) {
597+
kindExpr = KindExpr{intrinsic.kind()};
598+
CHECK(kindExpr.has_value());
599+
}
600+
KindExpr folded{Fold(std::move(*kindExpr))};
575601
int kind{context().GetDefaultKind(intrinsic.category())};
576-
if (auto value{evaluate::ToInt64(copy)}) {
602+
if (auto value{evaluate::ToInt64(folded)}) {
577603
if (foldingContext().targetCharacteristics().IsTypeEnabled(
578604
intrinsic.category(), *value)) {
579605
kind = *value;
@@ -586,7 +612,7 @@ const DeclTypeSpec &InstantiateHelper::InstantiateIntrinsicType(
586612
} else {
587613
std::string exprString;
588614
llvm::raw_string_ostream sstream(exprString);
589-
copy.AsFortran(sstream);
615+
folded.AsFortran(sstream);
590616
foldingContext().messages().Say(symbolName,
591617
"KIND parameter expression (%s) of intrinsic type %s did not resolve to a constant value"_err_en_US,
592618
exprString,

flang/test/Semantics/kinds03.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
type :: ipdt(k)
66
!REF: /MainProgram1/ipdt/k
77
integer, kind :: k
8-
!REF: /MainProgram1/ipdt/k
8+
!DEF: /MainProgram1/DerivedType9/k TypeParam INTEGER(4)
99
!DEF: /MainProgram1/ipdt/x ObjectEntity INTEGER(int(int(k,kind=4),kind=8))
1010
integer(kind=k) :: x
1111
end type ipdt
@@ -14,7 +14,7 @@
1414
type :: rpdt(k)
1515
!REF: /MainProgram1/rpdt/k
1616
integer, kind :: k
17-
!REF: /MainProgram1/rpdt/k
17+
!DEF: /MainProgram1/DerivedType13/k TypeParam INTEGER(4)
1818
!DEF: /MainProgram1/rpdt/x ObjectEntity REAL(int(int(k,kind=4),kind=8))
1919
real(kind=k) :: x
2020
end type rpdt
@@ -23,7 +23,7 @@
2323
type :: zpdt(k)
2424
!REF: /MainProgram1/zpdt/k
2525
integer, kind :: k
26-
!REF: /MainProgram1/zpdt/k
26+
!DEF: /MainProgram1/DerivedType17/k TypeParam INTEGER(4)
2727
!DEF: /MainProgram1/zpdt/x ObjectEntity COMPLEX(int(int(k,kind=4),kind=8))
2828
complex(kind=k) :: x
2929
end type zpdt
@@ -32,7 +32,7 @@
3232
type :: lpdt(k)
3333
!REF: /MainProgram1/lpdt/k
3434
integer, kind :: k
35-
!REF: /MainProgram1/lpdt/k
35+
!DEF: /MainProgram1/DerivedType21/k TypeParam INTEGER(4)
3636
!DEF: /MainProgram1/lpdt/x ObjectEntity LOGICAL(int(int(k,kind=4),kind=8))
3737
logical(kind=k) :: x
3838
end type lpdt

flang/test/Semantics/pdt05.f90

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
!RUN: %flang_fc1 -fdebug-unparse %s | FileCheck %s
2+
3+
type base(k1,k2)
4+
integer(1),kind :: k1
5+
integer(k1),kind :: k2
6+
integer(kind(int(k1,1)+int(k2,k1))) j
7+
integer(kind(int(k1,1)+int(k2,kind(k2)))) k
8+
end type
9+
type(base(2,7)) x27
10+
type(base(8,7)) x87
11+
print *, 'x27%j', kind(x27%j)
12+
print *, 'x27%k', kind(x27%k)
13+
print *, 'x87%j', kind(x87%j)
14+
print *, 'x87%k', kind(x87%k)
15+
end
16+
17+
!CHECK: PRINT *, "x27%j", 2_4
18+
!CHECK: PRINT *, "x27%k", 2_4
19+
!CHECK: PRINT *, "x87%j", 8_4
20+
!CHECK: PRINT *, "x87%k", 8_4

flang/test/Semantics/real10-x86-01.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
type :: rpdt(k)
77
!REF: /MainProgram1/rpdt/k
88
integer, kind :: k
9-
!REF: /MainProgram1/rpdt/k
9+
!DEF: /MainProgram1/DerivedType3/k TypeParam INTEGER(4)
1010
!DEF: /MainProgram1/rpdt/x ObjectEntity REAL(int(int(k,kind=4),kind=8))
1111
real(kind=k) :: x
1212
end type rpdt
@@ -15,7 +15,7 @@
1515
type :: zpdt(k)
1616
!REF: /MainProgram1/zpdt/k
1717
integer, kind :: k
18-
!REF: /MainProgram1/zpdt/k
18+
!DEF: /MainProgram1/DerivedType4/k TypeParam INTEGER(4)
1919
!DEF: /MainProgram1/zpdt/x ObjectEntity COMPLEX(int(int(k,kind=4),kind=8))
2020
complex(kind=k) :: x
2121
end type zpdt

0 commit comments

Comments
 (0)