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