diff --git a/flang/include/flang/Evaluate/common.h b/flang/include/flang/Evaluate/common.h --- a/flang/include/flang/Evaluate/common.h +++ b/flang/include/flang/Evaluate/common.h @@ -260,6 +260,9 @@ const semantics::DerivedTypeSpec &spec) { return common::ScopedSet(pdtInstance_, &spec); } + common::Restorer WithoutPDTInstance() { + return common::ScopedSet(pdtInstance_, nullptr); + } private: parser::ContextualMessages messages_; diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -1269,10 +1269,11 @@ } } else { // A "bare" type parameter: replace with its value, if that's now known - // in a current derived type instantiation, for KIND type parameters. + // in a current derived type instantiation. if (const auto *pdt{context.pdtInstance()}) { + auto restorer{context.WithoutPDTInstance()}; // don't loop bool isLen{false}; - if (const semantics::Scope * scope{context.pdtInstance()->scope()}) { + if (const semantics::Scope * scope{pdt->scope()}) { auto iter{scope->find(parameterName)}; if (iter != scope->end()) { const Symbol &symbol{*iter->second}; diff --git a/flang/test/Semantics/pdt01.f90 b/flang/test/Semantics/pdt01.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/pdt01.f90 @@ -0,0 +1,16 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! Catch error instead of crashing with infinite recursion +! when a LEN PDT from one type is being used to define a +! LEN PDT in another type's instantiation. +program main + type t1(lp) + integer, len :: lp + end type + type t2(lp) + integer, len :: lp + type(t1(lp)) :: c + end type + integer local + !ERROR: Invalid specification expression: reference to local entity 'local' + type(t2(local)) :: x +end