diff --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp --- a/flang/lib/Semantics/type.cpp +++ b/flang/lib/Semantics/type.cpp @@ -399,7 +399,7 @@ } else if (auto *procDetails{newSymbol.detailsIf()}) { // We have a procedure pointer. Instantiate its return type if (const DeclTypeSpec * returnType{InstantiateType(newSymbol)}) { - ProcInterface &interface{procDetails->interface()}; + ProcInterface &interface { procDetails->interface() }; if (!interface.symbol()) { // Don't change the type for interfaces based on symbols interface.set_type(*returnType); @@ -425,11 +425,28 @@ } } +/// Fold explicit length parameters of character components when the explicit +/// expression is a constant expression (if it only depends on KIND parameters). +/// Do not fold `character(len=pdt_length)`, even if the length parameter is +/// constant in the pdt instantiation, in order to avoid losing the information +/// that the character component is automatic (and must be a descriptor). +static ParamValue FoldCharaterLength(evaluate::FoldingContext &foldingContext, + const CharacterTypeSpec &characterSpec) { + if (const auto &len{characterSpec.length().GetExplicit()}) { + if (evaluate::IsConstantExpr(*len)) { + return ParamValue{evaluate::Fold(foldingContext, common::Clone(*len)), + common::TypeParamAttr::Len}; + } + } + return characterSpec.length(); +} + // Apply type parameter values to an intrinsic type spec. const DeclTypeSpec &InstantiateHelper::InstantiateIntrinsicType( SourceName symbolName, const DeclTypeSpec &spec) { const IntrinsicTypeSpec &intrinsic{DEREF(spec.AsIntrinsic())}; - if (evaluate::ToInt64(intrinsic.kind())) { + if (spec.category() != DeclTypeSpec::Character && + evaluate::ToInt64(intrinsic.kind())) { return spec; // KIND is already a known constant } // The expression was not originally constant, but now it must be so @@ -454,7 +471,8 @@ return scope_.MakeLogicalType(KindExpr{kind}); case DeclTypeSpec::Character: return scope_.MakeCharacterType( - ParamValue{spec.characterTypeSpec().length()}, KindExpr{kind}); + FoldCharaterLength(foldingContext(), spec.characterTypeSpec()), + KindExpr{kind}); default: CRASH_NO_CASE; } diff --git a/flang/test/Lower/derived-types-kind-params.f90 b/flang/test/Lower/derived-types-kind-params.f90 --- a/flang/test/Lower/derived-types-kind-params.f90 +++ b/flang/test/Lower/derived-types-kind-params.f90 @@ -31,13 +31,13 @@ ! ----------------------------------------------------------------------------- ! CHECK-LABEL: func @_QMmPfoo - ! CHECK-SAME: !fir.ref> + ! CHECK-SAME: !fir.ref> subroutine foo(at) type(t(k2=12)) :: at end subroutine ! CHECK-LABEL: func @_QMmPfoo2 - ! CHECK-SAME: !fir.ref>}>}>> + ! CHECK-SAME: !fir.ref>}>}>> subroutine foo2(at2) type(t2(12, 13)) :: at2 end subroutine diff --git a/flang/test/Semantics/offsets02.f90 b/flang/test/Semantics/offsets02.f90 --- a/flang/test/Semantics/offsets02.f90 +++ b/flang/test/Semantics/offsets02.f90 @@ -52,3 +52,13 @@ !CHECK: d3 size=24 offset=40: type(t(4, 20)) :: x4 end + +subroutine s4 + type t(k) + integer, kind :: k + character(len=k) :: c + end type + type(t(7)) :: x4 + !CHECK: DerivedType scope: size=7 alignment=1 instantiation of t(k=7_4) + !CHECK: c size=7 offset=0: ObjectEntity type: CHARACTER(7_4,1) +end subroutine