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 "flang/Evaluate/fold.h"
11 #include "flang/Parser/characters.h"
12 #include "flang/Semantics/scope.h"
13 #include "flang/Semantics/symbol.h"
14 #include "flang/Semantics/tools.h"
15 #include <ostream>
16 #include <sstream>
17 
18 namespace Fortran::semantics {
19 
20 DerivedTypeSpec::DerivedTypeSpec(SourceName name, const Symbol &typeSymbol)
21   : name_{name}, typeSymbol_{typeSymbol} {
22   CHECK(typeSymbol.has<DerivedTypeDetails>());
23 }
24 DerivedTypeSpec::DerivedTypeSpec(const DerivedTypeSpec &that) = default;
25 DerivedTypeSpec::DerivedTypeSpec(DerivedTypeSpec &&that) = default;
26 
27 void DerivedTypeSpec::set_scope(const Scope &scope) {
28   CHECK(!scope_);
29   ReplaceScope(scope);
30 }
31 void DerivedTypeSpec::ReplaceScope(const Scope &scope) {
32   CHECK(scope.IsDerivedType());
33   scope_ = &scope;
34 }
35 
36 void DerivedTypeSpec::AddRawParamValue(
37     const std::optional<parser::Keyword> &keyword, ParamValue &&value) {
38   CHECK(parameters_.empty());
39   rawParameters_.emplace_back(keyword ? &*keyword : nullptr, std::move(value));
40 }
41 
42 void DerivedTypeSpec::CookParameters(evaluate::FoldingContext &foldingContext) {
43   if (cooked_) {
44     return;
45   }
46   cooked_ = true;
47   auto &messages{foldingContext.messages()};
48   if (IsForwardReferenced()) {
49     messages.Say(typeSymbol_.name(),
50         "Derived type '%s' was used but never defined"_err_en_US,
51         typeSymbol_.name());
52     return;
53   }
54 
55   // Parameters of the most deeply nested "base class" come first when the
56   // derived type is an extension.
57   auto parameterNames{OrderParameterNames(typeSymbol_)};
58   auto parameterDecls{OrderParameterDeclarations(typeSymbol_)};
59   auto nextNameIter{parameterNames.begin()};
60   RawParameters raw{std::move(rawParameters_)};
61   for (auto &[maybeKeyword, value] : raw) {
62     SourceName name;
63     common::TypeParamAttr attr{common::TypeParamAttr::Kind};
64     if (maybeKeyword) {
65       name = maybeKeyword->v.source;
66       auto it{std::find_if(parameterDecls.begin(), parameterDecls.end(),
67           [&](const Symbol &symbol) { return symbol.name() == name; })};
68       if (it == parameterDecls.end()) {
69         messages.Say(name,
70             "'%s' is not the name of a parameter for derived type '%s'"_err_en_US,
71             name, typeSymbol_.name());
72       } else {
73         // Resolve the keyword's symbol
74         maybeKeyword->v.symbol = const_cast<Symbol *>(&it->get());
75         attr = it->get().get<TypeParamDetails>().attr();
76       }
77     } else if (nextNameIter != parameterNames.end()) {
78       name = *nextNameIter++;
79       auto it{std::find_if(parameterDecls.begin(), parameterDecls.end(),
80           [&](const Symbol &symbol) { return symbol.name() == name; })};
81       CHECK(it != parameterDecls.end());
82       attr = it->get().get<TypeParamDetails>().attr();
83     } else {
84       messages.Say(name_,
85           "Too many type parameters given for derived type '%s'"_err_en_US,
86           typeSymbol_.name());
87       break;
88     }
89     if (FindParameter(name)) {
90       messages.Say(name_,
91           "Multiple values given for type parameter '%s'"_err_en_US, name);
92     } else {
93       value.set_attr(attr);
94       AddParamValue(name, std::move(value));
95     }
96   }
97 }
98 
99 void DerivedTypeSpec::EvaluateParameters(
100     evaluate::FoldingContext &foldingContext) {
101   CookParameters(foldingContext);
102   if (evaluated_) {
103     return;
104   }
105   evaluated_ = true;
106   auto &messages{foldingContext.messages()};
107 
108   // Fold the explicit type parameter value expressions first.  Do not
109   // fold them within the scope of the derived type being instantiated;
110   // these expressions cannot use its type parameters.  Convert the values
111   // of the expressions to the declared types of the type parameters.
112   auto parameterDecls{OrderParameterDeclarations(typeSymbol_)};
113   for (const Symbol &symbol : parameterDecls) {
114     const SourceName &name{symbol.name()};
115     if (ParamValue * paramValue{FindParameter(name)}) {
116       if (const MaybeIntExpr & expr{paramValue->GetExplicit()}) {
117         if (auto converted{evaluate::ConvertToType(symbol, SomeExpr{*expr})}) {
118           SomeExpr folded{
119               evaluate::Fold(foldingContext, std::move(*converted))};
120           if (auto *intExpr{std::get_if<SomeIntExpr>(&folded.u)}) {
121             paramValue->SetExplicit(std::move(*intExpr));
122             continue;
123           }
124         }
125         evaluate::SayWithDeclaration(messages, symbol,
126             "Value of type parameter '%s' (%s) is not convertible to its type"_err_en_US,
127             name, expr->AsFortran());
128       }
129     }
130   }
131 
132   // Default initialization expressions for the derived type's parameters
133   // may reference other parameters so long as the declaration precedes the
134   // use in the expression (10.1.12).  This is not necessarily the same
135   // order as "type parameter order" (7.5.3.2).
136   // Type parameter default value expressions are folded in declaration order
137   // within the scope of the derived type so that the values of earlier type
138   // parameters are available for use in the default initialization
139   // expressions of later parameters.
140   auto restorer{foldingContext.WithPDTInstance(*this)};
141   for (const Symbol &symbol : parameterDecls) {
142     const SourceName &name{symbol.name()};
143     if (!FindParameter(name)) {
144       const TypeParamDetails &details{symbol.get<TypeParamDetails>()};
145       if (details.init()) {
146         auto expr{
147             evaluate::Fold(foldingContext, common::Clone(details.init()))};
148         AddParamValue(name, ParamValue{std::move(*expr), details.attr()});
149       } else {
150         messages.Say(name_,
151             "Type parameter '%s' lacks a value and has no default"_err_en_US,
152             name);
153       }
154     }
155   }
156 }
157 
158 void DerivedTypeSpec::AddParamValue(SourceName name, ParamValue &&value) {
159   CHECK(cooked_);
160   auto pair{parameters_.insert(std::make_pair(name, std::move(value)))};
161   CHECK(pair.second);  // name was not already present
162 }
163 
164 bool DerivedTypeSpec::MightBeParameterized() const {
165   return !cooked_ || !parameters_.empty();
166 }
167 
168 bool DerivedTypeSpec::IsForwardReferenced() const {
169   return typeSymbol_.get<DerivedTypeDetails>().isForwardReferenced();
170 }
171 
172 bool DerivedTypeSpec::HasDefaultInitialization() const {
173   for (const Scope *scope{scope_}; scope;
174        scope = scope->GetDerivedTypeParent()) {
175     for (const auto &pair : *scope) {
176       const Symbol &symbol{*pair.second};
177       if (IsAllocatable(symbol) || IsInitialized(symbol)) {
178         return true;
179       }
180     }
181   }
182   return false;
183 }
184 
185 ParamValue *DerivedTypeSpec::FindParameter(SourceName target) {
186   return const_cast<ParamValue *>(
187       const_cast<const DerivedTypeSpec *>(this)->FindParameter(target));
188 }
189 
190 void DerivedTypeSpec::Instantiate(
191     Scope &containingScope, SemanticsContext &context) {
192   if (instantiated_) {
193     return;
194   }
195   instantiated_ = true;
196   auto &foldingContext{context.foldingContext()};
197   if (IsForwardReferenced()) {
198     foldingContext.messages().Say(typeSymbol_.name(),
199         "The derived type '%s' was forward-referenced but not defined"_err_en_US,
200         typeSymbol_.name());
201     return;
202   }
203   CookParameters(foldingContext);
204   EvaluateParameters(foldingContext);
205   const Scope &typeScope{DEREF(typeSymbol_.scope())};
206   if (!MightBeParameterized()) {
207     scope_ = &typeScope;
208     for (const auto &pair : typeScope) {
209       const Symbol &symbol{*pair.second};
210       if (const DeclTypeSpec * type{symbol.GetType()}) {
211         if (const DerivedTypeSpec * derived{type->AsDerived()}) {
212           if (!(derived->IsForwardReferenced() &&
213                   IsAllocatableOrPointer(symbol))) {
214             auto &instantiatable{*const_cast<DerivedTypeSpec *>(derived)};
215             instantiatable.Instantiate(containingScope, context);
216           }
217         }
218       }
219     }
220     return;
221   }
222   Scope &newScope{containingScope.MakeScope(Scope::Kind::DerivedType)};
223   newScope.set_derivedTypeSpec(*this);
224   ReplaceScope(newScope);
225   for (const Symbol &symbol : OrderParameterDeclarations(typeSymbol_)) {
226     const SourceName &name{symbol.name()};
227     if (typeScope.find(symbol.name()) != typeScope.end()) {
228       // This type parameter belongs to the derived type itself, not to
229       // one of its ancestors.  Put the type parameter expression value
230       // into the new scope as the initialization value for the parameter.
231       if (ParamValue * paramValue{FindParameter(name)}) {
232         const TypeParamDetails &details{symbol.get<TypeParamDetails>()};
233         paramValue->set_attr(details.attr());
234         if (MaybeIntExpr expr{paramValue->GetExplicit()}) {
235           // Ensure that any kind type parameters with values are
236           // constant by now.
237           if (details.attr() == common::TypeParamAttr::Kind) {
238             // Any errors in rank and type will have already elicited
239             // messages, so don't pile on by complaining further here.
240             if (auto maybeDynamicType{expr->GetType()}) {
241               if (expr->Rank() == 0 &&
242                   maybeDynamicType->category() == TypeCategory::Integer) {
243                 if (!evaluate::ToInt64(*expr)) {
244                   if (auto *msg{foldingContext.messages().Say(
245                           "Value of kind type parameter '%s' (%s) is not "
246                           "a scalar INTEGER constant"_err_en_US,
247                           name, expr->AsFortran())}) {
248                     msg->Attach(name, "declared here"_en_US);
249                   }
250                 }
251               }
252             }
253           }
254           TypeParamDetails instanceDetails{details.attr()};
255           if (const DeclTypeSpec * type{details.type()}) {
256             instanceDetails.set_type(*type);
257           }
258           instanceDetails.set_init(std::move(*expr));
259           newScope.try_emplace(name, std::move(instanceDetails));
260         }
261       }
262     }
263   }
264   // Instantiate every non-parameter symbol from the original derived
265   // type's scope into the new instance.
266   auto restorer{foldingContext.WithPDTInstance(*this)};
267   newScope.AddSourceRange(typeScope.sourceRange());
268   for (const auto &pair : typeScope) {
269     const Symbol &symbol{*pair.second};
270     symbol.InstantiateComponent(newScope, context);
271   }
272 }
273 
274 std::string DerivedTypeSpec::AsFortran() const {
275   std::stringstream ss;
276   ss << name_;
277   if (!rawParameters_.empty()) {
278     CHECK(parameters_.empty());
279     ss << '(';
280     bool first = true;
281     for (const auto &[maybeKeyword, value] : rawParameters_) {
282       if (first) {
283         first = false;
284       } else {
285         ss << ',';
286       }
287       if (maybeKeyword) {
288         ss << maybeKeyword->v.source.ToString() << '=';
289       }
290       ss << value.AsFortran();
291     }
292     ss << ')';
293   } else if (!parameters_.empty()) {
294     ss << '(';
295     bool first = true;
296     for (const auto &[name, value] : parameters_) {
297       if (first) {
298         first = false;
299       } else {
300         ss << ',';
301       }
302       ss << name.ToString() << '=' << value.AsFortran();
303     }
304     ss << ')';
305   }
306   return ss.str();
307 }
308 
309 std::ostream &operator<<(std::ostream &o, const DerivedTypeSpec &x) {
310   return o << x.AsFortran();
311 }
312 
313 Bound::Bound(int bound) : expr_{bound} {}
314 
315 std::ostream &operator<<(std::ostream &o, const Bound &x) {
316   if (x.isAssumed()) {
317     o << '*';
318   } else if (x.isDeferred()) {
319     o << ':';
320   } else if (x.expr_) {
321     x.expr_->AsFortran(o);
322   } else {
323     o << "<no-expr>";
324   }
325   return o;
326 }
327 
328 std::ostream &operator<<(std::ostream &o, const ShapeSpec &x) {
329   if (x.lb_.isAssumed()) {
330     CHECK(x.ub_.isAssumed());
331     o << "..";
332   } else {
333     if (!x.lb_.isDeferred()) {
334       o << x.lb_;
335     }
336     o << ':';
337     if (!x.ub_.isDeferred()) {
338       o << x.ub_;
339     }
340   }
341   return o;
342 }
343 
344 bool ArraySpec::IsExplicitShape() const {
345   return CheckAll([](const ShapeSpec &x) { return x.ubound().isExplicit(); });
346 }
347 bool ArraySpec::IsAssumedShape() const {
348   return CheckAll([](const ShapeSpec &x) { return x.ubound().isDeferred(); });
349 }
350 bool ArraySpec::IsDeferredShape() const {
351   return CheckAll([](const ShapeSpec &x) {
352     return x.lbound().isDeferred() && x.ubound().isDeferred();
353   });
354 }
355 bool ArraySpec::IsImpliedShape() const {
356   return !IsAssumedRank() &&
357       CheckAll([](const ShapeSpec &x) { return x.ubound().isAssumed(); });
358 }
359 bool ArraySpec::IsAssumedSize() const {
360   return !empty() && !IsAssumedRank() && back().ubound().isAssumed() &&
361       std::all_of(begin(), end() - 1,
362           [](const ShapeSpec &x) { return x.ubound().isExplicit(); });
363 }
364 bool ArraySpec::IsAssumedRank() const {
365   return Rank() == 1 && front().lbound().isAssumed();
366 }
367 
368 std::ostream &operator<<(std::ostream &os, const ArraySpec &arraySpec) {
369   char sep{'('};
370   for (auto &shape : arraySpec) {
371     os << sep << shape;
372     sep = ',';
373   }
374   if (sep == ',') {
375     os << ')';
376   }
377   return os;
378 }
379 
380 ParamValue::ParamValue(MaybeIntExpr &&expr, common::TypeParamAttr attr)
381   : attr_{attr}, expr_{std::move(expr)} {}
382 ParamValue::ParamValue(SomeIntExpr &&expr, common::TypeParamAttr attr)
383   : attr_{attr}, expr_{std::move(expr)} {}
384 ParamValue::ParamValue(
385     common::ConstantSubscript value, common::TypeParamAttr attr)
386   : ParamValue(
387         SomeIntExpr{evaluate::Expr<evaluate::SubscriptInteger>{value}}, attr) {}
388 
389 void ParamValue::SetExplicit(SomeIntExpr &&x) {
390   category_ = Category::Explicit;
391   expr_ = std::move(x);
392 }
393 
394 std::string ParamValue::AsFortran() const {
395   switch (category_) {
396     SWITCH_COVERS_ALL_CASES
397   case Category::Assumed: return "*";
398   case Category::Deferred: return ":";
399   case Category::Explicit:
400     if (expr_) {
401       std::stringstream ss;
402       expr_->AsFortran(ss);
403       return ss.str();
404     } else {
405       return "";
406     }
407   }
408 }
409 
410 std::ostream &operator<<(std::ostream &o, const ParamValue &x) {
411   return o << x.AsFortran();
412 }
413 
414 IntrinsicTypeSpec::IntrinsicTypeSpec(TypeCategory category, KindExpr &&kind)
415   : category_{category}, kind_{std::move(kind)} {
416   CHECK(category != TypeCategory::Derived);
417 }
418 
419 static std::string KindAsFortran(const KindExpr &kind) {
420   std::stringstream ss;
421   if (auto k{evaluate::ToInt64(kind)}) {
422     ss << *k;  // emit unsuffixed kind code
423   } else {
424     kind.AsFortran(ss);
425   }
426   return ss.str();
427 }
428 
429 std::string IntrinsicTypeSpec::AsFortran() const {
430   return parser::ToUpperCaseLetters(common::EnumToString(category_)) + '(' +
431       KindAsFortran(kind_) + ')';
432 }
433 
434 std::ostream &operator<<(std::ostream &os, const IntrinsicTypeSpec &x) {
435   return os << x.AsFortran();
436 }
437 
438 std::string CharacterTypeSpec::AsFortran() const {
439   return "CHARACTER(" + length_.AsFortran() + ',' + KindAsFortran(kind()) + ')';
440 }
441 
442 std::ostream &operator<<(std::ostream &os, const CharacterTypeSpec &x) {
443   return os << x.AsFortran();
444 }
445 
446 DeclTypeSpec::DeclTypeSpec(NumericTypeSpec &&typeSpec)
447   : category_{Numeric}, typeSpec_{std::move(typeSpec)} {}
448 DeclTypeSpec::DeclTypeSpec(LogicalTypeSpec &&typeSpec)
449   : category_{Logical}, typeSpec_{std::move(typeSpec)} {}
450 DeclTypeSpec::DeclTypeSpec(const CharacterTypeSpec &typeSpec)
451   : category_{Character}, typeSpec_{typeSpec} {}
452 DeclTypeSpec::DeclTypeSpec(CharacterTypeSpec &&typeSpec)
453   : category_{Character}, typeSpec_{std::move(typeSpec)} {}
454 DeclTypeSpec::DeclTypeSpec(Category category, const DerivedTypeSpec &typeSpec)
455   : category_{category}, typeSpec_{typeSpec} {
456   CHECK(category == TypeDerived || category == ClassDerived);
457 }
458 DeclTypeSpec::DeclTypeSpec(Category category, DerivedTypeSpec &&typeSpec)
459   : category_{category}, typeSpec_{std::move(typeSpec)} {
460   CHECK(category == TypeDerived || category == ClassDerived);
461 }
462 DeclTypeSpec::DeclTypeSpec(Category category) : category_{category} {
463   CHECK(category == TypeStar || category == ClassStar);
464 }
465 bool DeclTypeSpec::IsNumeric(TypeCategory tc) const {
466   return category_ == Numeric && numericTypeSpec().category() == tc;
467 }
468 IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic() {
469   return const_cast<IntrinsicTypeSpec *>(
470       const_cast<const DeclTypeSpec *>(this)->AsIntrinsic());
471 }
472 const NumericTypeSpec &DeclTypeSpec::numericTypeSpec() const {
473   CHECK(category_ == Numeric);
474   return std::get<NumericTypeSpec>(typeSpec_);
475 }
476 const LogicalTypeSpec &DeclTypeSpec::logicalTypeSpec() const {
477   CHECK(category_ == Logical);
478   return std::get<LogicalTypeSpec>(typeSpec_);
479 }
480 bool DeclTypeSpec::operator==(const DeclTypeSpec &that) const {
481   return category_ == that.category_ && typeSpec_ == that.typeSpec_;
482 }
483 
484 std::string DeclTypeSpec::AsFortran() const {
485   switch (category_) {
486     SWITCH_COVERS_ALL_CASES
487   case Numeric: return numericTypeSpec().AsFortran();
488   case Logical: return logicalTypeSpec().AsFortran();
489   case Character: return characterTypeSpec().AsFortran();
490   case TypeDerived: return "TYPE(" + derivedTypeSpec().AsFortran() + ')';
491   case ClassDerived: return "CLASS(" + derivedTypeSpec().AsFortran() + ')';
492   case TypeStar: return "TYPE(*)";
493   case ClassStar: return "CLASS(*)";
494   }
495 }
496 
497 std::ostream &operator<<(std::ostream &o, const DeclTypeSpec &x) {
498   return o << x.AsFortran();
499 }
500 
501 void ProcInterface::set_symbol(const Symbol &symbol) {
502   CHECK(!type_);
503   symbol_ = &symbol;
504 }
505 void ProcInterface::set_type(const DeclTypeSpec &type) {
506   CHECK(!symbol_);
507   type_ = &type;
508 }
509 }
510