xref: /llvm-project/flang/lib/Evaluate/expression.cpp (revision 3a8a52f4a52e0c301a5f3d6acce684c7fd4a6d57)
164ab3302SCarolineConcatto //===-- lib/Evaluate/expression.cpp ---------------------------------------===//
264ab3302SCarolineConcatto //
364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664ab3302SCarolineConcatto //
764ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
864ab3302SCarolineConcatto 
964ab3302SCarolineConcatto #include "flang/Evaluate/expression.h"
1064ab3302SCarolineConcatto #include "int-power.h"
1164ab3302SCarolineConcatto #include "flang/Common/idioms.h"
1264ab3302SCarolineConcatto #include "flang/Evaluate/common.h"
1364ab3302SCarolineConcatto #include "flang/Evaluate/tools.h"
1464ab3302SCarolineConcatto #include "flang/Evaluate/variable.h"
15b34f1168SPeter Steinfeld #include "flang/Parser/char-block.h"
1664ab3302SCarolineConcatto #include "flang/Parser/message.h"
17b34f1168SPeter Steinfeld #include "flang/Semantics/scope.h"
18b34f1168SPeter Steinfeld #include "flang/Semantics/symbol.h"
19b34f1168SPeter Steinfeld #include "flang/Semantics/tools.h"
20b34f1168SPeter Steinfeld #include "flang/Semantics/type.h"
218670e499SCaroline Concatto #include "llvm/Support/raw_ostream.h"
2264ab3302SCarolineConcatto #include <string>
2364ab3302SCarolineConcatto #include <type_traits>
2464ab3302SCarolineConcatto 
2564ab3302SCarolineConcatto using namespace Fortran::parser::literals;
2664ab3302SCarolineConcatto 
2764ab3302SCarolineConcatto namespace Fortran::evaluate {
2864ab3302SCarolineConcatto 
2964ab3302SCarolineConcatto template <int KIND>
3064ab3302SCarolineConcatto std::optional<Expr<SubscriptInteger>>
3164ab3302SCarolineConcatto Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
3264ab3302SCarolineConcatto   using T = std::optional<Expr<SubscriptInteger>>;
33cd03e96fSPeter Klausler   return common::visit(
3464ab3302SCarolineConcatto       common::visitors{
3564ab3302SCarolineConcatto           [](const Constant<Result> &c) -> T {
3664ab3302SCarolineConcatto             return AsExpr(Constant<SubscriptInteger>{c.LEN()});
3764ab3302SCarolineConcatto           },
3801688ee9SPeter Klausler           [](const ArrayConstructor<Result> &a) -> T {
3901688ee9SPeter Klausler             if (const auto *len{a.LEN()}) {
4001688ee9SPeter Klausler               return T{*len};
4101688ee9SPeter Klausler             } else {
4201688ee9SPeter Klausler               return std::nullopt;
4301688ee9SPeter Klausler             }
4401688ee9SPeter Klausler           },
4564ab3302SCarolineConcatto           [](const Parentheses<Result> &x) { return x.left().LEN(); },
4664ab3302SCarolineConcatto           [](const Convert<Result> &x) {
47cd03e96fSPeter Klausler             return common::visit(
4864ab3302SCarolineConcatto                 [&](const auto &kx) { return kx.LEN(); }, x.left().u);
4964ab3302SCarolineConcatto           },
5064ab3302SCarolineConcatto           [](const Concat<KIND> &c) -> T {
5164ab3302SCarolineConcatto             if (auto llen{c.left().LEN()}) {
5264ab3302SCarolineConcatto               if (auto rlen{c.right().LEN()}) {
5364ab3302SCarolineConcatto                 return *std::move(llen) + *std::move(rlen);
5464ab3302SCarolineConcatto               }
5564ab3302SCarolineConcatto             }
5664ab3302SCarolineConcatto             return std::nullopt;
5764ab3302SCarolineConcatto           },
5864ab3302SCarolineConcatto           [](const Extremum<Result> &c) -> T {
5964ab3302SCarolineConcatto             if (auto llen{c.left().LEN()}) {
6064ab3302SCarolineConcatto               if (auto rlen{c.right().LEN()}) {
6164ab3302SCarolineConcatto                 return Expr<SubscriptInteger>{Extremum<SubscriptInteger>{
6264ab3302SCarolineConcatto                     Ordering::Greater, *std::move(llen), *std::move(rlen)}};
6364ab3302SCarolineConcatto               }
6464ab3302SCarolineConcatto             }
6564ab3302SCarolineConcatto             return std::nullopt;
6664ab3302SCarolineConcatto           },
6764ab3302SCarolineConcatto           [](const Designator<Result> &dr) { return dr.LEN(); },
6864ab3302SCarolineConcatto           [](const FunctionRef<Result> &fr) { return fr.LEN(); },
6964ab3302SCarolineConcatto           [](const SetLength<KIND> &x) -> T { return x.right(); },
7064ab3302SCarolineConcatto       },
7164ab3302SCarolineConcatto       u);
7264ab3302SCarolineConcatto }
7364ab3302SCarolineConcatto 
7464ab3302SCarolineConcatto Expr<SomeType>::~Expr() = default;
7564ab3302SCarolineConcatto 
7664ab3302SCarolineConcatto #if defined(__APPLE__) && defined(__GNUC__)
7764ab3302SCarolineConcatto template <typename A>
7864ab3302SCarolineConcatto typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() {
7964ab3302SCarolineConcatto   return *static_cast<Derived *>(this);
8064ab3302SCarolineConcatto }
8164ab3302SCarolineConcatto 
8264ab3302SCarolineConcatto template <typename A>
8364ab3302SCarolineConcatto const typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() const {
8464ab3302SCarolineConcatto   return *static_cast<const Derived *>(this);
8564ab3302SCarolineConcatto }
8664ab3302SCarolineConcatto #endif
8764ab3302SCarolineConcatto 
8864ab3302SCarolineConcatto template <typename A>
8964ab3302SCarolineConcatto std::optional<DynamicType> ExpressionBase<A>::GetType() const {
9064ab3302SCarolineConcatto   if constexpr (IsLengthlessIntrinsicType<Result>) {
9164ab3302SCarolineConcatto     return Result::GetType();
9264ab3302SCarolineConcatto   } else {
93cd03e96fSPeter Klausler     return common::visit(
9464ab3302SCarolineConcatto         [&](const auto &x) -> std::optional<DynamicType> {
9564ab3302SCarolineConcatto           if constexpr (!common::HasMember<decltype(x), TypelessExpression>) {
9664ab3302SCarolineConcatto             return x.GetType();
9764ab3302SCarolineConcatto           }
9864ab3302SCarolineConcatto           return std::nullopt; // w/o "else" to dodge bogus g++ 8.1 warning
9964ab3302SCarolineConcatto         },
10064ab3302SCarolineConcatto         derived().u);
10164ab3302SCarolineConcatto   }
10264ab3302SCarolineConcatto }
10364ab3302SCarolineConcatto 
10464ab3302SCarolineConcatto template <typename A> int ExpressionBase<A>::Rank() const {
105cd03e96fSPeter Klausler   return common::visit(
10664ab3302SCarolineConcatto       [](const auto &x) {
10764ab3302SCarolineConcatto         if constexpr (common::HasMember<decltype(x), TypelessExpression>) {
10864ab3302SCarolineConcatto           return 0;
10964ab3302SCarolineConcatto         } else {
11064ab3302SCarolineConcatto           return x.Rank();
11164ab3302SCarolineConcatto         }
11264ab3302SCarolineConcatto       },
11364ab3302SCarolineConcatto       derived().u);
11464ab3302SCarolineConcatto }
11564ab3302SCarolineConcatto 
116*3a8a52f4SPeter Klausler template <typename A> int ExpressionBase<A>::Corank() const {
117*3a8a52f4SPeter Klausler   return common::visit(
118*3a8a52f4SPeter Klausler       [](const auto &x) {
119*3a8a52f4SPeter Klausler         if constexpr (common::HasMember<decltype(x), TypelessExpression>) {
120*3a8a52f4SPeter Klausler           return 0;
121*3a8a52f4SPeter Klausler         } else {
122*3a8a52f4SPeter Klausler           return x.Corank();
123*3a8a52f4SPeter Klausler         }
124*3a8a52f4SPeter Klausler       },
125*3a8a52f4SPeter Klausler       derived().u);
126*3a8a52f4SPeter Klausler }
127*3a8a52f4SPeter Klausler 
128f6ecea1aSpeter klausler DynamicType Parentheses<SomeDerived>::GetType() const {
129f6ecea1aSpeter klausler   return left().GetType().value();
130f6ecea1aSpeter klausler }
131f6ecea1aSpeter klausler 
132fdcbb540SJean Perier #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
133fdcbb540SJean Perier template <typename A> LLVM_DUMP_METHOD void ExpressionBase<A>::dump() const {
134fdcbb540SJean Perier   llvm::errs() << "Expr is <{" << AsFortran() << "}>\n";
135fdcbb540SJean Perier }
136fdcbb540SJean Perier #endif
137fdcbb540SJean Perier 
138e03b20e6Speter klausler // Equality testing
13964ab3302SCarolineConcatto 
140d2126ec1SPeter Klausler template <typename A> bool Extremum<A>::operator==(const Extremum &that) const {
141d2126ec1SPeter Klausler   return ordering == that.ordering && Base::operator==(that);
142d2126ec1SPeter Klausler }
143d2126ec1SPeter Klausler 
144d2126ec1SPeter Klausler template <int KIND>
145d2126ec1SPeter Klausler bool LogicalOperation<KIND>::operator==(const LogicalOperation &that) const {
146d2126ec1SPeter Klausler   return logicalOperator == that.logicalOperator && Base::operator==(that);
147d2126ec1SPeter Klausler }
148d2126ec1SPeter Klausler 
149d2126ec1SPeter Klausler template <typename A>
150d2126ec1SPeter Klausler bool Relational<A>::operator==(const Relational &that) const {
151d2126ec1SPeter Klausler   return opr == that.opr && Base::operator==(that);
152d2126ec1SPeter Klausler }
153d2126ec1SPeter Klausler 
154d2126ec1SPeter Klausler bool Relational<SomeType>::operator==(const Relational &that) const {
155d2126ec1SPeter Klausler   return u == that.u;
156d2126ec1SPeter Klausler }
157d2126ec1SPeter Klausler 
15864ab3302SCarolineConcatto bool ImpliedDoIndex::operator==(const ImpliedDoIndex &that) const {
15964ab3302SCarolineConcatto   return name == that.name;
16064ab3302SCarolineConcatto }
16164ab3302SCarolineConcatto 
16264ab3302SCarolineConcatto template <typename T>
16364ab3302SCarolineConcatto bool ImpliedDo<T>::operator==(const ImpliedDo<T> &that) const {
16464ab3302SCarolineConcatto   return name_ == that.name_ && lower_ == that.lower_ &&
16564ab3302SCarolineConcatto       upper_ == that.upper_ && stride_ == that.stride_ &&
16664ab3302SCarolineConcatto       values_ == that.values_;
16764ab3302SCarolineConcatto }
16864ab3302SCarolineConcatto 
169e03b20e6Speter klausler template <typename T>
170e03b20e6Speter klausler bool ArrayConstructorValue<T>::operator==(
171e03b20e6Speter klausler     const ArrayConstructorValue<T> &that) const {
172e03b20e6Speter klausler   return u == that.u;
173e03b20e6Speter klausler }
174e03b20e6Speter klausler 
17564ab3302SCarolineConcatto template <typename R>
17664ab3302SCarolineConcatto bool ArrayConstructorValues<R>::operator==(
17764ab3302SCarolineConcatto     const ArrayConstructorValues<R> &that) const {
17864ab3302SCarolineConcatto   return values_ == that.values_;
17964ab3302SCarolineConcatto }
18064ab3302SCarolineConcatto 
18164ab3302SCarolineConcatto template <int KIND>
18201688ee9SPeter Klausler auto ArrayConstructor<Type<TypeCategory::Character, KIND>>::set_LEN(
18301688ee9SPeter Klausler     Expr<SubscriptInteger> &&len) -> ArrayConstructor & {
18401688ee9SPeter Klausler   length_.emplace(std::move(len));
18501688ee9SPeter Klausler   return *this;
18601688ee9SPeter Klausler }
18701688ee9SPeter Klausler 
18801688ee9SPeter Klausler template <int KIND>
18964ab3302SCarolineConcatto bool ArrayConstructor<Type<TypeCategory::Character, KIND>>::operator==(
19064ab3302SCarolineConcatto     const ArrayConstructor &that) const {
19164ab3302SCarolineConcatto   return length_ == that.length_ &&
19264ab3302SCarolineConcatto       static_cast<const Base &>(*this) == static_cast<const Base &>(that);
19364ab3302SCarolineConcatto }
19464ab3302SCarolineConcatto 
19564ab3302SCarolineConcatto bool ArrayConstructor<SomeDerived>::operator==(
19664ab3302SCarolineConcatto     const ArrayConstructor &that) const {
19764ab3302SCarolineConcatto   return result_ == that.result_ &&
19864ab3302SCarolineConcatto       static_cast<const Base &>(*this) == static_cast<const Base &>(that);
19964ab3302SCarolineConcatto   ;
20064ab3302SCarolineConcatto }
20164ab3302SCarolineConcatto 
20264ab3302SCarolineConcatto StructureConstructor::StructureConstructor(
20364ab3302SCarolineConcatto     const semantics::DerivedTypeSpec &spec,
20464ab3302SCarolineConcatto     const StructureConstructorValues &values)
20564ab3302SCarolineConcatto     : result_{spec}, values_{values} {}
20664ab3302SCarolineConcatto StructureConstructor::StructureConstructor(
20764ab3302SCarolineConcatto     const semantics::DerivedTypeSpec &spec, StructureConstructorValues &&values)
20864ab3302SCarolineConcatto     : result_{spec}, values_{std::move(values)} {}
20964ab3302SCarolineConcatto 
21064ab3302SCarolineConcatto bool StructureConstructor::operator==(const StructureConstructor &that) const {
21164ab3302SCarolineConcatto   return result_ == that.result_ && values_ == that.values_;
21264ab3302SCarolineConcatto }
21364ab3302SCarolineConcatto 
214e03b20e6Speter klausler template <int KIND>
215e03b20e6Speter klausler bool Expr<Type<TypeCategory::Integer, KIND>>::operator==(
216e03b20e6Speter klausler     const Expr<Type<TypeCategory::Integer, KIND>> &that) const {
217e03b20e6Speter klausler   return u == that.u;
218e03b20e6Speter klausler }
219e03b20e6Speter klausler 
220e03b20e6Speter klausler template <int KIND>
221e03b20e6Speter klausler bool Expr<Type<TypeCategory::Real, KIND>>::operator==(
222e03b20e6Speter klausler     const Expr<Type<TypeCategory::Real, KIND>> &that) const {
223e03b20e6Speter klausler   return u == that.u;
224e03b20e6Speter klausler }
225e03b20e6Speter klausler 
226e03b20e6Speter klausler template <int KIND>
227e03b20e6Speter klausler bool Expr<Type<TypeCategory::Complex, KIND>>::operator==(
228e03b20e6Speter klausler     const Expr<Type<TypeCategory::Complex, KIND>> &that) const {
229e03b20e6Speter klausler   return u == that.u;
230e03b20e6Speter klausler }
231e03b20e6Speter klausler 
232e03b20e6Speter klausler template <int KIND>
233e03b20e6Speter klausler bool Expr<Type<TypeCategory::Logical, KIND>>::operator==(
234e03b20e6Speter klausler     const Expr<Type<TypeCategory::Logical, KIND>> &that) const {
235e03b20e6Speter klausler   return u == that.u;
236e03b20e6Speter klausler }
237e03b20e6Speter klausler 
238e03b20e6Speter klausler template <int KIND>
239e03b20e6Speter klausler bool Expr<Type<TypeCategory::Character, KIND>>::operator==(
240e03b20e6Speter klausler     const Expr<Type<TypeCategory::Character, KIND>> &that) const {
241e03b20e6Speter klausler   return u == that.u;
242e03b20e6Speter klausler }
243e03b20e6Speter klausler 
244fc97d2e6SPeter Klausler template <int KIND>
245fc97d2e6SPeter Klausler bool Expr<Type<TypeCategory::Unsigned, KIND>>::operator==(
246fc97d2e6SPeter Klausler     const Expr<Type<TypeCategory::Unsigned, KIND>> &that) const {
247fc97d2e6SPeter Klausler   return u == that.u;
248fc97d2e6SPeter Klausler }
249fc97d2e6SPeter Klausler 
250e03b20e6Speter klausler template <TypeCategory CAT>
251e03b20e6Speter klausler bool Expr<SomeKind<CAT>>::operator==(const Expr<SomeKind<CAT>> &that) const {
252e03b20e6Speter klausler   return u == that.u;
253e03b20e6Speter klausler }
254e03b20e6Speter klausler 
255e03b20e6Speter klausler bool Expr<SomeDerived>::operator==(const Expr<SomeDerived> &that) const {
256e03b20e6Speter klausler   return u == that.u;
257e03b20e6Speter klausler }
258e03b20e6Speter klausler 
259e03b20e6Speter klausler bool Expr<SomeCharacter>::operator==(const Expr<SomeCharacter> &that) const {
260e03b20e6Speter klausler   return u == that.u;
261e03b20e6Speter klausler }
262e03b20e6Speter klausler 
263e03b20e6Speter klausler bool Expr<SomeType>::operator==(const Expr<SomeType> &that) const {
264e03b20e6Speter klausler   return u == that.u;
265e03b20e6Speter klausler }
266e03b20e6Speter klausler 
26764ab3302SCarolineConcatto DynamicType StructureConstructor::GetType() const { return result_.GetType(); }
26864ab3302SCarolineConcatto 
269b34f1168SPeter Steinfeld std::optional<Expr<SomeType>> StructureConstructor::CreateParentComponent(
27064ab3302SCarolineConcatto     const Symbol &component) const {
271b34f1168SPeter Steinfeld   if (const semantics::DerivedTypeSpec *
272b34f1168SPeter Steinfeld       parentSpec{GetParentTypeSpec(derivedTypeSpec())}) {
273b34f1168SPeter Steinfeld     StructureConstructor structureConstructor{*parentSpec};
274b34f1168SPeter Steinfeld     if (const auto *parentDetails{
275b34f1168SPeter Steinfeld             component.detailsIf<semantics::DerivedTypeDetails>()}) {
276b34f1168SPeter Steinfeld       auto parentIter{parentDetails->componentNames().begin()};
277b34f1168SPeter Steinfeld       for (const auto &childIter : values_) {
278b34f1168SPeter Steinfeld         if (parentIter == parentDetails->componentNames().end()) {
279b34f1168SPeter Steinfeld           break; // There are more components in the child
280b34f1168SPeter Steinfeld         }
281b34f1168SPeter Steinfeld         SymbolRef componentSymbol{childIter.first};
282b34f1168SPeter Steinfeld         structureConstructor.Add(
283b34f1168SPeter Steinfeld             *componentSymbol, common::Clone(childIter.second.value()));
284b34f1168SPeter Steinfeld         ++parentIter;
285b34f1168SPeter Steinfeld       }
286b34f1168SPeter Steinfeld       Constant<SomeDerived> constResult{std::move(structureConstructor)};
287b34f1168SPeter Steinfeld       Expr<SomeDerived> result{std::move(constResult)};
288b34f1168SPeter Steinfeld       return std::optional<Expr<SomeType>>{result};
289b34f1168SPeter Steinfeld     }
290b34f1168SPeter Steinfeld   }
291b34f1168SPeter Steinfeld   return std::nullopt;
292b34f1168SPeter Steinfeld }
293b34f1168SPeter Steinfeld 
294b34f1168SPeter Steinfeld static const Symbol *GetParentComponentSymbol(const Symbol &symbol) {
295b34f1168SPeter Steinfeld   if (symbol.test(Symbol::Flag::ParentComp)) {
296b34f1168SPeter Steinfeld     // we have a created parent component
297b34f1168SPeter Steinfeld     const auto &compObject{symbol.get<semantics::ObjectEntityDetails>()};
298b34f1168SPeter Steinfeld     if (const semantics::DeclTypeSpec * compType{compObject.type()}) {
299b34f1168SPeter Steinfeld       const semantics::DerivedTypeSpec &dtSpec{compType->derivedTypeSpec()};
300b34f1168SPeter Steinfeld       const semantics::Symbol &compTypeSymbol{dtSpec.typeSymbol()};
301b34f1168SPeter Steinfeld       return &compTypeSymbol;
302b34f1168SPeter Steinfeld     }
303b34f1168SPeter Steinfeld   }
304b34f1168SPeter Steinfeld   if (symbol.detailsIf<semantics::DerivedTypeDetails>()) {
305b34f1168SPeter Steinfeld     // we have an implicit parent type component
306b34f1168SPeter Steinfeld     return &symbol;
307b34f1168SPeter Steinfeld   }
30864ab3302SCarolineConcatto   return nullptr;
30964ab3302SCarolineConcatto }
310b34f1168SPeter Steinfeld 
311b34f1168SPeter Steinfeld std::optional<Expr<SomeType>> StructureConstructor::Find(
312b34f1168SPeter Steinfeld     const Symbol &component) const {
313b34f1168SPeter Steinfeld   if (auto iter{values_.find(component)}; iter != values_.end()) {
314b34f1168SPeter Steinfeld     return iter->second.value();
315b34f1168SPeter Steinfeld   }
316b34f1168SPeter Steinfeld   // The component wasn't there directly, see if we're looking for the parent
317b34f1168SPeter Steinfeld   // component of an extended type
318b34f1168SPeter Steinfeld   if (const Symbol * typeSymbol{GetParentComponentSymbol(component)}) {
319b34f1168SPeter Steinfeld     return CreateParentComponent(*typeSymbol);
320b34f1168SPeter Steinfeld   }
321b34f1168SPeter Steinfeld   // Look for the component in the parent type component.  The parent type
322b34f1168SPeter Steinfeld   // component is always the first one
323b34f1168SPeter Steinfeld   if (!values_.empty()) {
324b34f1168SPeter Steinfeld     const Expr<SomeType> *parentExpr{&values_.begin()->second.value()};
325b34f1168SPeter Steinfeld     if (const Expr<SomeDerived> *derivedExpr{
326b34f1168SPeter Steinfeld             std::get_if<Expr<SomeDerived>>(&parentExpr->u)}) {
327b34f1168SPeter Steinfeld       if (const Constant<SomeDerived> *constExpr{
328b34f1168SPeter Steinfeld               std::get_if<Constant<SomeDerived>>(&derivedExpr->u)}) {
329b34f1168SPeter Steinfeld         if (std::optional<StructureConstructor> parentComponentValue{
330b34f1168SPeter Steinfeld                 constExpr->GetScalarValue()}) {
331b34f1168SPeter Steinfeld           // Try to find the component in the parent structure constructor
332b34f1168SPeter Steinfeld           return parentComponentValue->Find(component);
333b34f1168SPeter Steinfeld         }
334b34f1168SPeter Steinfeld       }
335b34f1168SPeter Steinfeld     }
336b34f1168SPeter Steinfeld   }
337b34f1168SPeter Steinfeld   return std::nullopt;
33864ab3302SCarolineConcatto }
33964ab3302SCarolineConcatto 
34064ab3302SCarolineConcatto StructureConstructor &StructureConstructor::Add(
34164ab3302SCarolineConcatto     const Symbol &symbol, Expr<SomeType> &&expr) {
34264ab3302SCarolineConcatto   values_.emplace(symbol, std::move(expr));
34364ab3302SCarolineConcatto   return *this;
34464ab3302SCarolineConcatto }
34564ab3302SCarolineConcatto 
34664ab3302SCarolineConcatto GenericExprWrapper::~GenericExprWrapper() {}
34764ab3302SCarolineConcatto 
3488a8bb078Speter klausler void GenericExprWrapper::Deleter(GenericExprWrapper *p) { delete p; }
3498a8bb078Speter klausler 
35064ab3302SCarolineConcatto GenericAssignmentWrapper::~GenericAssignmentWrapper() {}
35164ab3302SCarolineConcatto 
3528a8bb078Speter klausler void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *p) {
3538a8bb078Speter klausler   delete p;
3548a8bb078Speter klausler }
3558a8bb078Speter klausler 
35664ab3302SCarolineConcatto template <TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const {
357cd03e96fSPeter Klausler   return common::visit(
35864ab3302SCarolineConcatto       [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
35964ab3302SCarolineConcatto       u);
36064ab3302SCarolineConcatto }
36164ab3302SCarolineConcatto 
36264ab3302SCarolineConcatto int Expr<SomeCharacter>::GetKind() const {
363cd03e96fSPeter Klausler   return common::visit(
36464ab3302SCarolineConcatto       [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
36564ab3302SCarolineConcatto       u);
36664ab3302SCarolineConcatto }
36764ab3302SCarolineConcatto 
36864ab3302SCarolineConcatto std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const {
369cd03e96fSPeter Klausler   return common::visit([](const auto &kx) { return kx.LEN(); }, u);
37064ab3302SCarolineConcatto }
37164ab3302SCarolineConcatto 
3725c5bde1bSPeter Klausler #ifdef _MSC_VER // disable bogus warning about missing definitions
3735c5bde1bSPeter Klausler #pragma warning(disable : 4661)
3745c5bde1bSPeter Klausler #endif
37564ab3302SCarolineConcatto INSTANTIATE_EXPRESSION_TEMPLATES
3761f879005STim Keith } // namespace Fortran::evaluate
377