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