xref: /llvm-project/flang/lib/Semantics/type.cpp (revision 7cbb36590384b8b71076a91f8958df556d773238)
1 //===-- lib/Semantics/type.cpp --------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "flang/Semantics/type.h"
10 #include "check-declarations.h"
11 #include "compute-offsets.h"
12 #include "flang/Evaluate/fold.h"
13 #include "flang/Evaluate/tools.h"
14 #include "flang/Evaluate/type.h"
15 #include "flang/Parser/characters.h"
16 #include "flang/Parser/parse-tree-visitor.h"
17 #include "flang/Semantics/scope.h"
18 #include "flang/Semantics/symbol.h"
19 #include "flang/Semantics/tools.h"
20 #include "llvm/Support/raw_ostream.h"
21 
22 namespace Fortran::semantics {
23 
24 DerivedTypeSpec::DerivedTypeSpec(SourceName name, const Symbol &typeSymbol)
25     : name_{name}, originalTypeSymbol_{typeSymbol},
26       typeSymbol_{typeSymbol.GetUltimate()} {
27   CHECK(typeSymbol_.has<DerivedTypeDetails>());
28 }
29 DerivedTypeSpec::DerivedTypeSpec(const DerivedTypeSpec &that) = default;
30 DerivedTypeSpec::DerivedTypeSpec(DerivedTypeSpec &&that) = default;
31 
32 void DerivedTypeSpec::set_scope(const Scope &scope) {
33   CHECK(!scope_);
34   ReplaceScope(scope);
35 }
36 void DerivedTypeSpec::ReplaceScope(const Scope &scope) {
37   CHECK(scope.IsDerivedType());
38   scope_ = &scope;
39 }
40 
41 const Scope *DerivedTypeSpec::GetScope() const {
42   return scope_ ? scope_ : typeSymbol_.scope();
43 }
44 
45 void DerivedTypeSpec::AddRawParamValue(
46     const parser::Keyword *keyword, ParamValue &&value) {
47   CHECK(parameters_.empty());
48   rawParameters_.emplace_back(keyword, std::move(value));
49 }
50 
51 void DerivedTypeSpec::CookParameters(evaluate::FoldingContext &foldingContext) {
52   if (cooked_) {
53     return;
54   }
55   cooked_ = true;
56   auto &messages{foldingContext.messages()};
57   if (IsForwardReferenced()) {
58     messages.Say(typeSymbol_.name(),
59         "Derived type '%s' was used but never defined"_err_en_US,
60         typeSymbol_.name());
61     return;
62   }
63 
64   // Parameters of the most deeply nested "base class" come first when the
65   // derived type is an extension.
66   auto parameterNames{OrderParameterNames(typeSymbol_)};
67   auto nextNameIter{parameterNames.begin()};
68   RawParameters raw{std::move(rawParameters_)};
69   for (auto &[maybeKeyword, value] : raw) {
70     SourceName name;
71     common::TypeParamAttr attr{common::TypeParamAttr::Kind};
72     if (maybeKeyword) {
73       name = maybeKeyword->v.source;
74       auto it{std::find_if(parameterNames.begin(), parameterNames.end(),
75           [&](const Symbol &symbol) { return symbol.name() == name; })};
76       if (it == parameterNames.end()) {
77         messages.Say(name,
78             "'%s' is not the name of a parameter for derived type '%s'"_err_en_US,
79             name, typeSymbol_.name());
80       } else {
81         // Resolve the keyword's symbol
82         maybeKeyword->v.symbol = const_cast<Symbol *>(&it->get());
83         if (const auto *tpd{it->get().detailsIf<TypeParamDetails>()}) {
84           attr = tpd->attr().value_or(attr);
85         }
86       }
87     } else if (nextNameIter != parameterNames.end()) {
88       name = nextNameIter->get().name();
89       if (const auto *tpd{nextNameIter->get().detailsIf<TypeParamDetails>()}) {
90         attr = tpd->attr().value_or(attr);
91       }
92       ++nextNameIter;
93     } else {
94       messages.Say(name_,
95           "Too many type parameters given for derived type '%s'"_err_en_US,
96           typeSymbol_.name());
97       break;
98     }
99     if (FindParameter(name)) {
100       messages.Say(name_,
101           "Multiple values given for type parameter '%s'"_err_en_US, name);
102     } else {
103       value.set_attr(attr);
104       AddParamValue(name, std::move(value));
105     }
106   }
107 }
108 
109 void DerivedTypeSpec::EvaluateParameters(SemanticsContext &context) {
110   evaluate::FoldingContext &foldingContext{context.foldingContext()};
111   CookParameters(foldingContext);
112   if (evaluated_) {
113     return;
114   }
115   evaluated_ = true;
116   auto &messages{foldingContext.messages()};
117   for (const Symbol &symbol : OrderParameterDeclarations(typeSymbol_)) {
118     SourceName name{symbol.name()};
119     int parameterKind{evaluate::TypeParamInquiry::Result::kind};
120     // Compute the integer kind value of the type parameter,
121     // which may depend on the values of earlier ones.
122     if (const auto *typeSpec{symbol.GetType()}) {
123       if (const IntrinsicTypeSpec * intrinType{typeSpec->AsIntrinsic()};
124           intrinType && intrinType->category() == TypeCategory::Integer) {
125         auto restorer{foldingContext.WithPDTInstance(*this)};
126         auto folded{Fold(foldingContext, KindExpr{intrinType->kind()})};
127         if (auto k{evaluate::ToInt64(folded)}; k &&
128             evaluate::IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) {
129           parameterKind = static_cast<int>(*k);
130         } else {
131           messages.Say(
132               "Type of type parameter '%s' (%s) is not a valid kind of INTEGER"_err_en_US,
133               name, intrinType->kind().AsFortran());
134         }
135       }
136     }
137     bool ok{
138         symbol.get<TypeParamDetails>().attr() == common::TypeParamAttr::Len};
139     if (ParamValue * paramValue{FindParameter(name)}) {
140       // Explicit type parameter value expressions are not folded within
141       // the scope of the derived type being instantiated, as the expressions
142       // themselves are not in that scope and cannot reference its type
143       // parameters.
144       if (const MaybeIntExpr & expr{paramValue->GetExplicit()}) {
145         evaluate::DynamicType dyType{TypeCategory::Integer, parameterKind};
146         if (auto converted{evaluate::ConvertToType(dyType, SomeExpr{*expr})}) {
147           SomeExpr folded{
148               evaluate::Fold(foldingContext, std::move(*converted))};
149           if (auto *intExpr{std::get_if<SomeIntExpr>(&folded.u)}) {
150             ok = ok || evaluate::IsActuallyConstant(*intExpr);
151             paramValue->SetExplicit(std::move(*intExpr));
152           }
153         } else if (!context.HasError(symbol)) {
154           evaluate::SayWithDeclaration(messages, symbol,
155               "Value of type parameter '%s' (%s) is not convertible to its type (%s)"_err_en_US,
156               name, expr->AsFortran(), dyType.AsFortran());
157         }
158       }
159     } else {
160       // Default type parameter value expressions are folded within
161       // the scope of the derived type being instantiated.
162       const TypeParamDetails &details{symbol.get<TypeParamDetails>()};
163       if (details.init() && details.attr()) {
164         evaluate::DynamicType dyType{TypeCategory::Integer, parameterKind};
165         if (auto converted{
166                 evaluate::ConvertToType(dyType, SomeExpr{*details.init()})}) {
167           auto restorer{foldingContext.WithPDTInstance(*this)};
168           SomeExpr folded{
169               evaluate::Fold(foldingContext, std::move(*converted))};
170           ok = ok || evaluate::IsActuallyConstant(folded);
171           AddParamValue(name,
172               ParamValue{std::move(std::get<SomeIntExpr>(folded.u)),
173                   details.attr().value()});
174         } else {
175           if (!context.HasError(symbol)) {
176             evaluate::SayWithDeclaration(messages, symbol,
177                 "Default value of type parameter '%s' (%s) is not convertible to its type (%s)"_err_en_US,
178                 name, details.init()->AsFortran(), dyType.AsFortran());
179           }
180         }
181       } else if (!context.HasError(symbol)) {
182         messages.Say(name_,
183             "Type parameter '%s' lacks a value and has no default"_err_en_US,
184             name);
185       }
186     }
187     if (!ok && !context.HasError(symbol)) {
188       messages.Say(
189           "Value of KIND type parameter '%s' must be constant"_err_en_US, name);
190     }
191   }
192 }
193 
194 void DerivedTypeSpec::AddParamValue(SourceName name, ParamValue &&value) {
195   CHECK(cooked_);
196   auto pair{parameters_.insert(std::make_pair(name, std::move(value)))};
197   CHECK(pair.second); // name was not already present
198 }
199 
200 bool DerivedTypeSpec::MightBeParameterized() const {
201   return !cooked_ || !parameters_.empty();
202 }
203 
204 bool DerivedTypeSpec::IsForwardReferenced() const {
205   return typeSymbol_.get<DerivedTypeDetails>().isForwardReferenced();
206 }
207 
208 bool DerivedTypeSpec::HasDefaultInitialization(
209     bool ignoreAllocatable, bool ignorePointer) const {
210   DirectComponentIterator components{*this};
211   return bool{std::find_if(
212       components.begin(), components.end(), [&](const Symbol &component) {
213         return IsInitialized(component, /*ignoreDataStatements=*/true,
214             ignoreAllocatable, ignorePointer);
215       })};
216 }
217 
218 bool DerivedTypeSpec::HasDestruction() const {
219   if (!FinalsForDerivedTypeInstantiation(*this).empty()) {
220     return true;
221   }
222   DirectComponentIterator components{*this};
223   return bool{std::find_if(
224       components.begin(), components.end(), [&](const Symbol &component) {
225         return IsDestructible(component, &typeSymbol());
226       })};
227 }
228 
229 ParamValue *DerivedTypeSpec::FindParameter(SourceName target) {
230   return const_cast<ParamValue *>(
231       const_cast<const DerivedTypeSpec *>(this)->FindParameter(target));
232 }
233 
234 static bool MatchKindParams(const Symbol &typeSymbol,
235     const DerivedTypeSpec &thisSpec, const DerivedTypeSpec &thatSpec) {
236   for (auto ref : typeSymbol.get<DerivedTypeDetails>().paramNameOrder()) {
237     if (ref->get<TypeParamDetails>().attr() == common::TypeParamAttr::Kind) {
238       const auto *thisValue{thisSpec.FindParameter(ref->name())};
239       const auto *thatValue{thatSpec.FindParameter(ref->name())};
240       if (!thisValue || !thatValue || *thisValue != *thatValue) {
241         return false;
242       }
243     }
244   }
245   if (const DerivedTypeSpec *
246       parent{typeSymbol.GetParentTypeSpec(typeSymbol.scope())}) {
247     return MatchKindParams(parent->typeSymbol(), thisSpec, thatSpec);
248   } else {
249     return true;
250   }
251 }
252 
253 bool DerivedTypeSpec::MatchesOrExtends(const DerivedTypeSpec &that) const {
254   const Symbol *typeSymbol{&typeSymbol_};
255   while (typeSymbol != &that.typeSymbol_) {
256     if (const DerivedTypeSpec *
257         parent{typeSymbol->GetParentTypeSpec(typeSymbol->scope())}) {
258       typeSymbol = &parent->typeSymbol_;
259     } else {
260       return false;
261     }
262   }
263   return MatchKindParams(*typeSymbol, *this, that);
264 }
265 
266 class InstantiateHelper {
267 public:
268   InstantiateHelper(Scope &scope) : scope_{scope} {}
269   // Instantiate components from fromScope into scope_
270   void InstantiateComponents(const Scope &);
271 
272 private:
273   SemanticsContext &context() const { return scope_.context(); }
274   evaluate::FoldingContext &foldingContext() {
275     return context().foldingContext();
276   }
277   template <typename A> A Fold(A &&expr) {
278     return evaluate::Fold(foldingContext(), std::move(expr));
279   }
280   void InstantiateComponent(const Symbol &);
281   const DeclTypeSpec *InstantiateType(const Symbol &);
282   const DeclTypeSpec &InstantiateIntrinsicType(
283       SourceName, const DeclTypeSpec &);
284   DerivedTypeSpec CreateDerivedTypeSpec(const DerivedTypeSpec &, bool);
285 
286   Scope &scope_;
287 };
288 
289 static int PlumbPDTInstantiationDepth(const Scope *scope) {
290   int depth{0};
291   while (scope->IsParameterizedDerivedTypeInstantiation()) {
292     ++depth;
293     scope = &scope->parent();
294   }
295   return depth;
296 }
297 
298 // Completes component derived type instantiation and initializer folding
299 // for a non-parameterized derived type Scope.
300 static void InstantiateNonPDTScope(Scope &typeScope, Scope &containingScope) {
301   auto &context{containingScope.context()};
302   auto &foldingContext{context.foldingContext()};
303   for (auto &pair : typeScope) {
304     Symbol &symbol{*pair.second};
305     if (DeclTypeSpec * type{symbol.GetType()}) {
306       if (DerivedTypeSpec * derived{type->AsDerived()}) {
307         if (!(derived->IsForwardReferenced() &&
308                 IsAllocatableOrPointer(symbol))) {
309           derived->Instantiate(containingScope);
310         }
311       }
312     }
313     if (!IsPointer(symbol)) {
314       if (auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {
315         if (MaybeExpr & init{object->init()}) {
316           auto restorer{foldingContext.messages().SetLocation(symbol.name())};
317           init = evaluate::NonPointerInitializationExpr(
318               symbol, std::move(*init), foldingContext);
319         }
320       }
321     }
322   }
323   ComputeOffsets(context, typeScope);
324 }
325 
326 void DerivedTypeSpec::Instantiate(Scope &containingScope) {
327   if (instantiated_) {
328     return;
329   }
330   instantiated_ = true;
331   auto &context{containingScope.context()};
332   auto &foldingContext{context.foldingContext()};
333   if (IsForwardReferenced()) {
334     foldingContext.messages().Say(typeSymbol_.name(),
335         "The derived type '%s' was forward-referenced but not defined"_err_en_US,
336         typeSymbol_.name());
337     context.SetError(typeSymbol_);
338     return;
339   }
340   EvaluateParameters(context);
341   const Scope &typeScope{DEREF(typeSymbol_.scope())};
342   if (!MightBeParameterized()) {
343     scope_ = &typeScope;
344     if (!typeScope.derivedTypeSpec() || *this != *typeScope.derivedTypeSpec()) {
345       Scope &mutableTypeScope{const_cast<Scope &>(typeScope)};
346       mutableTypeScope.set_derivedTypeSpec(*this);
347       InstantiateNonPDTScope(mutableTypeScope, containingScope);
348     }
349     return;
350   }
351   // New PDT instantiation.  Create a new scope and populate it
352   // with components that have been specialized for this set of
353   // parameters.
354   Scope &newScope{containingScope.MakeScope(Scope::Kind::DerivedType)};
355   newScope.set_derivedTypeSpec(*this);
356   ReplaceScope(newScope);
357   auto restorer{foldingContext.WithPDTInstance(*this)};
358   std::string desc{typeSymbol_.name().ToString()};
359   char sep{'('};
360   for (const Symbol &symbol : OrderParameterDeclarations(typeSymbol_)) {
361     const SourceName &name{symbol.name()};
362     if (typeScope.find(symbol.name()) != typeScope.end()) {
363       // This type parameter belongs to the derived type itself, not to
364       // one of its ancestors.  Put the type parameter expression value,
365       // when there is one, into the new scope as the initialization value
366       // for the parameter.  And when there is no explicit value, add an
367       // uninitialized type parameter to forestall use of any default.
368       if (ParamValue * paramValue{FindParameter(name)}) {
369         const TypeParamDetails &details{symbol.get<TypeParamDetails>()};
370         TypeParamDetails instanceDetails{};
371         if (details.attr()) {
372           paramValue->set_attr(*details.attr());
373           instanceDetails.set_attr(*details.attr());
374         }
375         desc += sep;
376         desc += name.ToString();
377         desc += '=';
378         sep = ',';
379         if (MaybeIntExpr expr{paramValue->GetExplicit()}) {
380           desc += expr->AsFortran();
381           instanceDetails.set_init(
382               std::move(DEREF(evaluate::UnwrapExpr<SomeIntExpr>(*expr))));
383           if (auto dyType{expr->GetType()}) {
384             instanceDetails.set_type(newScope.MakeNumericType(
385                 TypeCategory::Integer, KindExpr{dyType->kind()}));
386           }
387         }
388         if (!instanceDetails.type()) {
389           if (const DeclTypeSpec * type{details.type()}) {
390             instanceDetails.set_type(*type);
391           }
392         }
393         if (!instanceDetails.init()) {
394           desc += '*';
395         }
396         newScope.try_emplace(name, std::move(instanceDetails));
397       }
398     }
399   }
400   parser::Message *contextMessage{nullptr};
401   if (sep != '(') {
402     desc += ')';
403     contextMessage = new parser::Message{foldingContext.messages().at(),
404         "instantiation of parameterized derived type '%s'"_en_US, desc};
405     if (auto outer{containingScope.instantiationContext()}) {
406       contextMessage->SetContext(outer.get());
407     }
408     newScope.set_instantiationContext(contextMessage);
409   }
410   // Instantiate nearly every non-parameter symbol from the original derived
411   // type's scope into the new instance.
412   auto restorer2{foldingContext.messages().SetContext(contextMessage)};
413   if (PlumbPDTInstantiationDepth(&containingScope) > 100) {
414     foldingContext.messages().Say(
415         "Too many recursive parameterized derived type instantiations"_err_en_US);
416   } else {
417     InstantiateHelper{newScope}.InstantiateComponents(typeScope);
418   }
419 }
420 
421 void InstantiateHelper::InstantiateComponents(const Scope &fromScope) {
422   // Instantiate symbols in declaration order; this ensures that
423   // parent components and type parameters of ancestor types exist
424   // by the time that they're needed.
425   for (SymbolRef ref : fromScope.GetSymbols()) {
426     InstantiateComponent(*ref);
427   }
428   ComputeOffsets(context(), scope_);
429 }
430 
431 // Walks a parsed expression to prepare it for (re)analysis;
432 // clears out the typedExpr analysis results and re-resolves
433 // symbol table pointers of type parameters.
434 class ComponentInitResetHelper {
435 public:
436   explicit ComponentInitResetHelper(Scope &scope) : scope_{scope} {}
437 
438   template <typename A> bool Pre(const A &) { return true; }
439 
440   template <typename A> void Post(const A &x) {
441     if constexpr (parser::HasTypedExpr<A>()) {
442       x.typedExpr.Reset();
443     }
444   }
445 
446   void Post(const parser::Name &name) {
447     if (name.symbol && name.symbol->has<TypeParamDetails>()) {
448       name.symbol = scope_.FindComponent(name.source);
449     }
450   }
451 
452 private:
453   Scope &scope_;
454 };
455 
456 void InstantiateHelper::InstantiateComponent(const Symbol &oldSymbol) {
457   auto pair{scope_.try_emplace(
458       oldSymbol.name(), oldSymbol.attrs(), common::Clone(oldSymbol.details()))};
459   Symbol &newSymbol{*pair.first->second};
460   if (!pair.second) {
461     // Symbol was already present in the scope, which can only happen
462     // in the case of type parameters.
463     CHECK(oldSymbol.has<TypeParamDetails>());
464     return;
465   }
466   newSymbol.flags() = oldSymbol.flags();
467   if (auto *details{newSymbol.detailsIf<ObjectEntityDetails>()}) {
468     if (const DeclTypeSpec * newType{InstantiateType(newSymbol)}) {
469       details->ReplaceType(*newType);
470     }
471     for (ShapeSpec &dim : details->shape()) {
472       if (dim.lbound().isExplicit()) {
473         dim.lbound().SetExplicit(Fold(std::move(dim.lbound().GetExplicit())));
474       }
475       if (dim.ubound().isExplicit()) {
476         dim.ubound().SetExplicit(Fold(std::move(dim.ubound().GetExplicit())));
477       }
478     }
479     for (ShapeSpec &dim : details->coshape()) {
480       if (dim.lbound().isExplicit()) {
481         dim.lbound().SetExplicit(Fold(std::move(dim.lbound().GetExplicit())));
482       }
483       if (dim.ubound().isExplicit()) {
484         dim.ubound().SetExplicit(Fold(std::move(dim.ubound().GetExplicit())));
485       }
486     }
487     if (const auto *parsedExpr{details->unanalyzedPDTComponentInit()}) {
488       // Analyze the parsed expression in this PDT instantiation context.
489       ComponentInitResetHelper resetter{scope_};
490       parser::Walk(*parsedExpr, resetter);
491       auto restorer{foldingContext().messages().SetLocation(newSymbol.name())};
492       details->set_init(evaluate::Fold(
493           foldingContext(), AnalyzeExpr(context(), *parsedExpr)));
494       details->set_unanalyzedPDTComponentInit(nullptr);
495       // Remove analysis results to prevent unparsing or other use of
496       // instantiation-specific expressions.
497       parser::Walk(*parsedExpr, resetter);
498     }
499     if (MaybeExpr & init{details->init()}) {
500       // Non-pointer components with default initializers are
501       // processed now so that those default initializers can be used
502       // in PARAMETER structure constructors.
503       auto restorer{foldingContext().messages().SetLocation(newSymbol.name())};
504       init = IsPointer(newSymbol)
505           ? Fold(std::move(*init))
506           : evaluate::NonPointerInitializationExpr(
507                 newSymbol, std::move(*init), foldingContext());
508     }
509   } else if (auto *procDetails{newSymbol.detailsIf<ProcEntityDetails>()}) {
510     // We have a procedure pointer.  Instantiate its return type
511     if (const DeclTypeSpec * returnType{InstantiateType(newSymbol)}) {
512       if (!procDetails->procInterface()) {
513         procDetails->ReplaceType(*returnType);
514       }
515     }
516   }
517 }
518 
519 const DeclTypeSpec *InstantiateHelper::InstantiateType(const Symbol &symbol) {
520   const DeclTypeSpec *type{symbol.GetType()};
521   if (!type) {
522     return nullptr; // error has occurred
523   } else if (const DerivedTypeSpec * spec{type->AsDerived()}) {
524     return &FindOrInstantiateDerivedType(scope_,
525         CreateDerivedTypeSpec(*spec, symbol.test(Symbol::Flag::ParentComp)),
526         type->category());
527   } else if (type->AsIntrinsic()) {
528     return &InstantiateIntrinsicType(symbol.name(), *type);
529   } else if (type->category() == DeclTypeSpec::ClassStar) {
530     return type;
531   } else {
532     common::die("InstantiateType: %s", type->AsFortran().c_str());
533   }
534 }
535 
536 /// Fold explicit length parameters of character components when the explicit
537 /// expression is a constant expression (if it only depends on KIND parameters).
538 /// Do not fold `character(len=pdt_length)`, even if the length parameter is
539 /// constant in the pdt instantiation, in order to avoid losing the information
540 /// that the character component is automatic (and must be a descriptor).
541 static ParamValue FoldCharacterLength(evaluate::FoldingContext &foldingContext,
542     const CharacterTypeSpec &characterSpec) {
543   if (const auto &len{characterSpec.length().GetExplicit()}) {
544     if (evaluate::IsConstantExpr(*len)) {
545       return ParamValue{evaluate::Fold(foldingContext, common::Clone(*len)),
546           common::TypeParamAttr::Len};
547     }
548   }
549   return characterSpec.length();
550 }
551 
552 // Apply type parameter values to an intrinsic type spec.
553 const DeclTypeSpec &InstantiateHelper::InstantiateIntrinsicType(
554     SourceName symbolName, const DeclTypeSpec &spec) {
555   const IntrinsicTypeSpec &intrinsic{DEREF(spec.AsIntrinsic())};
556   if (spec.category() != DeclTypeSpec::Character &&
557       evaluate::IsActuallyConstant(intrinsic.kind())) {
558     return spec; // KIND is already a known constant
559   }
560   // The expression was not originally constant, but now it must be so
561   // in the context of a parameterized derived type instantiation.
562   KindExpr copy{Fold(common::Clone(intrinsic.kind()))};
563   int kind{context().GetDefaultKind(intrinsic.category())};
564   if (auto value{evaluate::ToInt64(copy)}) {
565     if (foldingContext().targetCharacteristics().IsTypeEnabled(
566             intrinsic.category(), *value)) {
567       kind = *value;
568     } else {
569       foldingContext().messages().Say(symbolName,
570           "KIND parameter value (%jd) of intrinsic type %s "
571           "did not resolve to a supported value"_err_en_US,
572           *value,
573           parser::ToUpperCaseLetters(EnumToString(intrinsic.category())));
574     }
575   }
576   switch (spec.category()) {
577   case DeclTypeSpec::Numeric:
578     return scope_.MakeNumericType(intrinsic.category(), KindExpr{kind});
579   case DeclTypeSpec::Logical:
580     return scope_.MakeLogicalType(KindExpr{kind});
581   case DeclTypeSpec::Character:
582     return scope_.MakeCharacterType(
583         FoldCharacterLength(foldingContext(), spec.characterTypeSpec()),
584         KindExpr{kind});
585   default:
586     CRASH_NO_CASE;
587   }
588 }
589 
590 DerivedTypeSpec InstantiateHelper::CreateDerivedTypeSpec(
591     const DerivedTypeSpec &spec, bool isParentComp) {
592   DerivedTypeSpec result{spec};
593   result.CookParameters(foldingContext()); // enables AddParamValue()
594   if (isParentComp) {
595     // Forward any explicit type parameter values from the
596     // derived type spec under instantiation that define type parameters
597     // of the parent component to the derived type spec of the
598     // parent component.
599     const DerivedTypeSpec &instanceSpec{DEREF(foldingContext().pdtInstance())};
600     for (const auto &[name, value] : instanceSpec.parameters()) {
601       if (scope_.find(name) == scope_.end()) {
602         result.AddParamValue(name, ParamValue{value});
603       }
604     }
605   }
606   return result;
607 }
608 
609 std::string DerivedTypeSpec::VectorTypeAsFortran() const {
610   std::string buf;
611   llvm::raw_string_ostream ss{buf};
612 
613   switch (category()) {
614     SWITCH_COVERS_ALL_CASES
615   case (Fortran::semantics::DerivedTypeSpec::Category::IntrinsicVector): {
616     int64_t vecElemKind;
617     int64_t vecElemCategory;
618 
619     for (const auto &pair : parameters()) {
620       if (pair.first == "element_category") {
621         vecElemCategory =
622             Fortran::evaluate::ToInt64(pair.second.GetExplicit()).value_or(-1);
623       } else if (pair.first == "element_kind") {
624         vecElemKind =
625             Fortran::evaluate::ToInt64(pair.second.GetExplicit()).value_or(0);
626       }
627     }
628 
629     assert((vecElemCategory >= 0 &&
630                static_cast<size_t>(vecElemCategory) <
631                    Fortran::common::VectorElementCategory_enumSize) &&
632         "Vector element type is not specified");
633     assert(vecElemKind && "Vector element kind is not specified");
634 
635     ss << "vector(";
636     switch (static_cast<common::VectorElementCategory>(vecElemCategory)) {
637       SWITCH_COVERS_ALL_CASES
638     case common::VectorElementCategory::Integer:
639       ss << "integer(" << vecElemKind << ")";
640       break;
641     case common::VectorElementCategory::Unsigned:
642       ss << "unsigned(" << vecElemKind << ")";
643       break;
644     case common::VectorElementCategory::Real:
645       ss << "real(" << vecElemKind << ")";
646       break;
647     }
648     ss << ")";
649     break;
650   }
651   case (Fortran::semantics::DerivedTypeSpec::Category::PairVector):
652     ss << "__vector_pair";
653     break;
654   case (Fortran::semantics::DerivedTypeSpec::Category::QuadVector):
655     ss << "__vector_quad";
656     break;
657   case (Fortran::semantics::DerivedTypeSpec::Category::DerivedType):
658     Fortran::common::die("Vector element type not implemented");
659   }
660   return buf;
661 }
662 
663 std::string DerivedTypeSpec::AsFortran() const {
664   std::string buf;
665   llvm::raw_string_ostream ss{buf};
666   ss << originalTypeSymbol_.name();
667   if (!rawParameters_.empty()) {
668     CHECK(parameters_.empty());
669     ss << '(';
670     bool first = true;
671     for (const auto &[maybeKeyword, value] : rawParameters_) {
672       if (first) {
673         first = false;
674       } else {
675         ss << ',';
676       }
677       if (maybeKeyword) {
678         ss << maybeKeyword->v.source.ToString() << '=';
679       }
680       ss << value.AsFortran();
681     }
682     ss << ')';
683   } else if (!parameters_.empty()) {
684     ss << '(';
685     bool first = true;
686     for (const auto &[name, value] : parameters_) {
687       if (first) {
688         first = false;
689       } else {
690         ss << ',';
691       }
692       ss << name.ToString() << '=' << value.AsFortran();
693     }
694     ss << ')';
695   }
696   return buf;
697 }
698 
699 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const DerivedTypeSpec &x) {
700   return o << x.AsFortran();
701 }
702 
703 Bound::Bound(common::ConstantSubscript bound) : expr_{bound} {}
704 
705 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const Bound &x) {
706   if (x.isStar()) {
707     o << '*';
708   } else if (x.isColon()) {
709     o << ':';
710   } else if (x.expr_) {
711     x.expr_->AsFortran(o);
712   } else {
713     o << "<no-expr>";
714   }
715   return o;
716 }
717 
718 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const ShapeSpec &x) {
719   if (x.lb_.isStar()) {
720     CHECK(x.ub_.isStar());
721     o << "..";
722   } else {
723     if (!x.lb_.isColon()) {
724       o << x.lb_;
725     }
726     o << ':';
727     if (!x.ub_.isColon()) {
728       o << x.ub_;
729     }
730   }
731   return o;
732 }
733 
734 llvm::raw_ostream &operator<<(
735     llvm::raw_ostream &os, const ArraySpec &arraySpec) {
736   char sep{'('};
737   for (auto &shape : arraySpec) {
738     os << sep << shape;
739     sep = ',';
740   }
741   if (sep == ',') {
742     os << ')';
743   }
744   return os;
745 }
746 
747 ParamValue::ParamValue(MaybeIntExpr &&expr, common::TypeParamAttr attr)
748     : attr_{attr}, expr_{std::move(expr)} {}
749 ParamValue::ParamValue(SomeIntExpr &&expr, common::TypeParamAttr attr)
750     : attr_{attr}, expr_{std::move(expr)} {}
751 ParamValue::ParamValue(
752     common::ConstantSubscript value, common::TypeParamAttr attr)
753     : ParamValue(SomeIntExpr{evaluate::Expr<evaluate::SubscriptInteger>{value}},
754           attr) {}
755 
756 void ParamValue::SetExplicit(SomeIntExpr &&x) {
757   category_ = Category::Explicit;
758   expr_ = std::move(x);
759 }
760 
761 std::string ParamValue::AsFortran() const {
762   switch (category_) {
763     SWITCH_COVERS_ALL_CASES
764   case Category::Assumed:
765     return "*";
766   case Category::Deferred:
767     return ":";
768   case Category::Explicit:
769     if (expr_) {
770       std::string buf;
771       llvm::raw_string_ostream ss{buf};
772       expr_->AsFortran(ss);
773       return buf;
774     } else {
775       return "";
776     }
777   }
778 }
779 
780 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const ParamValue &x) {
781   return o << x.AsFortran();
782 }
783 
784 IntrinsicTypeSpec::IntrinsicTypeSpec(TypeCategory category, KindExpr &&kind)
785     : category_{category}, kind_{std::move(kind)} {
786   CHECK(category != TypeCategory::Derived);
787 }
788 
789 static std::string KindAsFortran(const KindExpr &kind) {
790   std::string buf;
791   llvm::raw_string_ostream ss{buf};
792   if (auto k{evaluate::ToInt64(kind)}) {
793     ss << *k; // emit unsuffixed kind code
794   } else {
795     kind.AsFortran(ss);
796   }
797   return buf;
798 }
799 
800 std::string IntrinsicTypeSpec::AsFortran() const {
801   return parser::ToUpperCaseLetters(common::EnumToString(category_)) + '(' +
802       KindAsFortran(kind_) + ')';
803 }
804 
805 llvm::raw_ostream &operator<<(
806     llvm::raw_ostream &os, const IntrinsicTypeSpec &x) {
807   return os << x.AsFortran();
808 }
809 
810 std::string CharacterTypeSpec::AsFortran() const {
811   return "CHARACTER(" + length_.AsFortran() + ',' + KindAsFortran(kind()) + ')';
812 }
813 
814 llvm::raw_ostream &operator<<(
815     llvm::raw_ostream &os, const CharacterTypeSpec &x) {
816   return os << x.AsFortran();
817 }
818 
819 DeclTypeSpec::DeclTypeSpec(NumericTypeSpec &&typeSpec)
820     : category_{Numeric}, typeSpec_{std::move(typeSpec)} {}
821 DeclTypeSpec::DeclTypeSpec(LogicalTypeSpec &&typeSpec)
822     : category_{Logical}, typeSpec_{std::move(typeSpec)} {}
823 DeclTypeSpec::DeclTypeSpec(const CharacterTypeSpec &typeSpec)
824     : category_{Character}, typeSpec_{typeSpec} {}
825 DeclTypeSpec::DeclTypeSpec(CharacterTypeSpec &&typeSpec)
826     : category_{Character}, typeSpec_{std::move(typeSpec)} {}
827 DeclTypeSpec::DeclTypeSpec(Category category, const DerivedTypeSpec &typeSpec)
828     : category_{category}, typeSpec_{typeSpec} {
829   CHECK(category == TypeDerived || category == ClassDerived);
830 }
831 DeclTypeSpec::DeclTypeSpec(Category category, DerivedTypeSpec &&typeSpec)
832     : category_{category}, typeSpec_{std::move(typeSpec)} {
833   CHECK(category == TypeDerived || category == ClassDerived);
834 }
835 DeclTypeSpec::DeclTypeSpec(Category category) : category_{category} {
836   CHECK(category == TypeStar || category == ClassStar);
837 }
838 bool DeclTypeSpec::IsNumeric(TypeCategory tc) const {
839   return category_ == Numeric && numericTypeSpec().category() == tc;
840 }
841 bool DeclTypeSpec::IsSequenceType() const {
842   if (const DerivedTypeSpec * derivedType{AsDerived()}) {
843     const auto *typeDetails{
844         derivedType->typeSymbol().detailsIf<DerivedTypeDetails>()};
845     return typeDetails && typeDetails->sequence();
846   }
847   return false;
848 }
849 
850 const NumericTypeSpec &DeclTypeSpec::numericTypeSpec() const {
851   CHECK(category_ == Numeric);
852   return std::get<NumericTypeSpec>(typeSpec_);
853 }
854 const LogicalTypeSpec &DeclTypeSpec::logicalTypeSpec() const {
855   CHECK(category_ == Logical);
856   return std::get<LogicalTypeSpec>(typeSpec_);
857 }
858 bool DeclTypeSpec::operator==(const DeclTypeSpec &that) const {
859   return category_ == that.category_ && typeSpec_ == that.typeSpec_;
860 }
861 
862 std::string DeclTypeSpec::AsFortran() const {
863   switch (category_) {
864     SWITCH_COVERS_ALL_CASES
865   case Numeric:
866     return numericTypeSpec().AsFortran();
867   case Logical:
868     return logicalTypeSpec().AsFortran();
869   case Character:
870     return characterTypeSpec().AsFortran();
871   case TypeDerived:
872     if (derivedTypeSpec()
873             .typeSymbol()
874             .get<DerivedTypeDetails>()
875             .isDECStructure()) {
876       return "RECORD" + derivedTypeSpec().typeSymbol().name().ToString();
877     } else if (derivedTypeSpec().IsVectorType()) {
878       return derivedTypeSpec().VectorTypeAsFortran();
879     } else {
880       return "TYPE(" + derivedTypeSpec().AsFortran() + ')';
881     }
882   case ClassDerived:
883     return "CLASS(" + derivedTypeSpec().AsFortran() + ')';
884   case TypeStar:
885     return "TYPE(*)";
886   case ClassStar:
887     return "CLASS(*)";
888   }
889 }
890 
891 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const DeclTypeSpec &x) {
892   return o << x.AsFortran();
893 }
894 
895 } // namespace Fortran::semantics
896