[flang] Address review comments, fix some f90_correct failures

Original-commit: flang-compiler/f18@e468f8cd54
Reviewed-on: https://github.com/flang-compiler/f18/pull/271
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2019-01-31 09:58:40 -08:00
parent 1c95fef459
commit 140b4adcfe
15 changed files with 169 additions and 111 deletions

View File

@ -0,0 +1,43 @@
// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Utility: before overwriting a variable, capture its value and
// ensure that it will be restored when the Restorer goes out of scope.
//
// int x{3};
// {
// auto save{common::ScopedSet(x, 4)};
// // x is now 4
// }
// // x is back to 3
#ifndef FORTRAN_COMMON_RESTORER_H_
#define FORTRAN_COMMON_RESTORER_H_
namespace Fortran::common {
template<typename A> class Restorer {
public:
explicit Restorer(A &p) : p_{p}, original_{std::move(p)} {}
~Restorer() { p_ = std::move(original_); }
private:
A &p_;
A original_;
};
template<typename A> Restorer<A> ScopedSet(A &to, A &&from) {
Restorer<A> result{to};
to = std::move(from);
return result;
}
}
#endif // FORTRAN_COMMON_RESTORER_H_

View File

@ -194,18 +194,19 @@ template<typename A> using CopyableIndirection = common::Indirection<A, true>;
// definition
template<typename A> class Expr;
// TODO pmk: convert to a class
struct FoldingContext {
explicit FoldingContext(const parser::ContextualMessages &m,
Rounding round = defaultRounding, bool flush = false)
: messages{m}, rounding{round}, flushSubnormalsToZero{flush} {}
FoldingContext(const FoldingContext &that)
: messages{that.messages}, rounding{that.rounding},
flushDenormalsToZero{that.flushDenormalsToZero},
flushSubnormalsToZero{that.flushSubnormalsToZero},
pdtInstance{that.pdtInstance}, impliedDos{that.impliedDos} {}
FoldingContext(
const FoldingContext &that, const parser::ContextualMessages &m)
: messages{m}, rounding{that.rounding},
flushDenormalsToZero{that.flushDenormalsToZero},
flushSubnormalsToZero{that.flushSubnormalsToZero},
pdtInstance{that.pdtInstance}, impliedDos{that.impliedDos} {}
parser::ContextualMessages messages;

View File

@ -94,8 +94,8 @@ template<typename T>
std::ostream &Emit(std::ostream &o, const ImpliedDo<T> &implDo) {
o << '(';
Emit(o, *implDo.values);
o << ',' << ImpliedDoIndex::Result::AsFortran() << "::";
o << '=';
o << ',' << ImpliedDoIndex::Result::AsFortran()
<< "::" << implDo.name.ToString() << '=';
implDo.lower->AsFortran(o) << ',';
implDo.upper->AsFortran(o) << ',';
implDo.stride->AsFortran(o) << ')';
@ -222,9 +222,8 @@ bool ImpliedDoIndex::operator==(const ImpliedDoIndex &that) const {
template<typename T>
bool ImpliedDo<T>::operator==(const ImpliedDo<T> &that) const {
return controlVariableName == that.controlVariableName &&
lower == that.lower && upper == that.upper && stride == that.stride &&
values == that.values;
return name == that.name && lower == that.lower && upper == that.upper &&
stride == that.stride && values == that.values;
}
template<typename R>

View File

@ -405,7 +405,7 @@ struct ImpliedDoIndex {
template<typename RESULT> struct ImpliedDo {
using Result = RESULT;
bool operator==(const ImpliedDo &) const;
parser::CharBlock controlVariableName;
parser::CharBlock name;
CopyableIndirection<Expr<ResultType<ImpliedDoIndex>>> lower, upper, stride;
CopyableIndirection<ArrayConstructorValues<RESULT>> values;
};

View File

@ -217,8 +217,11 @@ Expr<T> FoldOperation(FoldingContext &context, Designator<T> &&designator) {
Expr<ImpliedDoIndex::Result> FoldOperation(
FoldingContext &context, ImpliedDoIndex &&iDo) {
auto iter{context.impliedDos.find(iDo.name)};
CHECK(iter != context.impliedDos.end());
return Expr<ImpliedDoIndex::Result>{iter->second};
if (iter != context.impliedDos.end()) {
return Expr<ImpliedDoIndex::Result>{iter->second};
} else {
return Expr<ImpliedDoIndex::Result>{std::move(iDo)};
}
}
template<typename T> class ArrayConstructorFolder {
@ -268,8 +271,7 @@ private:
std::optional<std::int64_t> start{ToInt64(lower)}, end{ToInt64(upper)},
step{ToInt64(stride)};
if (start.has_value() && end.has_value() && step.has_value()) {
auto pair{context_.impliedDos.insert(
std::make_pair(iDo.controlVariableName, *start))};
auto pair{context_.impliedDos.insert(std::make_pair(iDo.name, *start))};
CHECK(pair.second);
bool result{true};
for (std::int64_t &j{pair.first->second}; j <= *end; j += *step) {
@ -300,9 +302,12 @@ private:
template<typename T>
Expr<T> FoldOperation(FoldingContext &context, ArrayConstructor<T> &&array) {
ArrayConstructorFolder<T> folder{context};
return folder.FoldArray(std::move(array));
Expr<T> result{folder.FoldArray(std::move(array))};
return result;
}
// TODO this specializations is a placeholder: don't fold array constructors
// of derived type for now
Expr<SomeDerived> FoldOperation(
FoldingContext &context, ArrayConstructor<SomeDerived> &&array) {
return Expr<SomeDerived>{std::move(array)};
@ -326,21 +331,20 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldOperation(
if (iter != scope->end()) {
const Symbol &symbol{*iter->second};
const auto *details{symbol.detailsIf<semantics::TypeParamDetails>()};
CHECK(details != nullptr);
CHECK(details->init().has_value());
Expr<SomeInteger> expr{*details->init()};
return Fold(context,
Expr<IntKIND>{
Convert<IntKIND, TypeCategory::Integer>(std::move(expr))});
} else {
if (details && details->init().has_value()) {
Expr<SomeInteger> expr{*details->init()};
return Fold(context,
Expr<IntKIND>{
Convert<IntKIND, TypeCategory::Integer>(std::move(expr))});
}
} else if (const auto *value{context.pdtInstance->FindParameter(
inquiry.parameter->name())}) {
// Parameter of a parent derived type; these are saved in the spec.
const auto *value{
context.pdtInstance->FindParameter(inquiry.parameter->name())};
CHECK(value != nullptr);
CHECK(value->isExplicit());
return Fold(context,
Expr<IntKIND>{Convert<IntKIND, TypeCategory::Integer>(
value->GetExplicit().value())});
if (value->isExplicit()) {
return Fold(context,
Expr<IntKIND>{Convert<IntKIND, TypeCategory::Integer>(
value->GetExplicit().value())});
}
}
}
return Expr<IntKIND>{std::move(inquiry)};
@ -818,7 +822,7 @@ bool IsConstExpr(ConstExprContext &context, const ImpliedDo<V> &impliedDo) {
return false;
}
ConstExprContext newContext{context};
newContext.constantNames.insert(impliedDo.controlVariableName);
newContext.constantNames.insert(impliedDo.name);
return IsConstExpr(newContext, impliedDo.values);
}
template<typename A>

View File

@ -462,20 +462,16 @@ int BaseObject::Rank() const {
}
int Component::Rank() const {
int baseRank{base_->Rank()};
int symbolRank{symbol_->Rank()};
CHECK(baseRank == 0 || symbolRank == 0);
return baseRank + symbolRank;
if (int rank{symbol_->Rank()}; rank > 0) {
return rank;
}
return base_->Rank();
}
int Subscript::Rank() const {
return std::visit(
common::visitors{
[](const IndirectSubscriptIntegerExpr &x) {
int rank{x->Rank()};
CHECK(rank <= 1);
return rank;
},
[](const IndirectSubscriptIntegerExpr &x) { return x->Rank(); },
[](const Triplet &) { return 1; },
},
u);
@ -483,22 +479,24 @@ int Subscript::Rank() const {
int ArrayRef::Rank() const {
int rank{0};
for (std::size_t j{0}; j < subscript.size(); ++j) {
rank += subscript[j].Rank();
for (const auto &expr : subscript) {
rank += expr.Rank();
}
if (std::holds_alternative<const Symbol *>(u)) {
if (rank > 0) {
return rank;
} else {
int baseRank{std::get_if<Component>(&u)->Rank()};
CHECK(rank == 0 || baseRank == 0);
return baseRank + rank;
}
return std::visit(
common::visitors{
[=](const Symbol *s) { return 0; },
[=](const Component &c) { return c.Rank(); },
},
u);
}
int CoarrayRef::Rank() const {
int rank{0};
for (std::size_t j{0}; j < subscript_.size(); ++j) {
rank += subscript_[j].Rank();
for (const auto &expr : subscript_) {
rank += expr.Rank();
}
return rank;
}

View File

@ -129,7 +129,7 @@ std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
intrinsic{typeSpec->AsIntrinsic()}) {
TypeCategory category{intrinsic->category()};
if (auto kind{ToInt64(intrinsic->kind())}) {
DynamicTypeWithLength result{category, static_cast<int>(*kind)};
DynamicTypeWithLength result{{category, static_cast<int>(*kind)}};
if (category == TypeCategory::Character) {
const semantics::CharacterTypeSpec &cts{
typeSpec->characterTypeSpec()};
@ -145,7 +145,7 @@ std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
}
} else if (const semantics::DerivedTypeSpec *
derived{typeSpec->AsDerived()}) {
return DynamicTypeWithLength{TypeCategory::Derived, 0, derived};
return DynamicTypeWithLength{{TypeCategory::Derived, 0, derived}};
}
}
}
@ -382,13 +382,16 @@ static MaybeExpr CompleteSubscripts(
} else if (subscripts == 0) {
// nothing to check
} else if (Component * component{std::get_if<Component>(&ref.u)}) {
int baseRank{component->Rank()};
int baseRank{component->base().Rank()};
if (baseRank > 0) {
int rank{ref.Rank()};
if (rank > 0) {
context.Say("Subscripts of rank-%d component reference have rank %d, "
"but must all be scalar"_err_en_US,
baseRank, rank);
int subscriptRank{0};
for (const auto &expr : ref.subscript) {
subscriptRank += expr.Rank();
}
if (subscriptRank > 0) {
context.Say("Subscripts of component '%s' of rank-%d derived type "
"array have rank %d but must all be scalar"_err_en_US,
symbol.name().ToString().data(), baseRank, subscriptRank);
}
}
} else if (const auto *details{
@ -1035,12 +1038,14 @@ static MaybeExpr AnalyzeExpr(
}
if (sym->detailsIf<semantics::TypeParamDetails>()) {
if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) {
std::optional<DynamicType> dyType{GetSymbolType(sym)};
CHECK(dyType.has_value());
CHECK(dyType->category == TypeCategory::Integer);
return AsMaybeExpr(
common::SearchTypes(TypeParamInquiryVisitor{dyType->kind,
IgnoreAnySubscripts(std::move(*designator)), *sym}));
if (std::optional<DynamicType> dyType{GetSymbolType(sym)}) {
if (dyType->category == TypeCategory::Integer) {
return AsMaybeExpr(
common::SearchTypes(TypeParamInquiryVisitor{dyType->kind,
IgnoreAnySubscripts(std::move(*designator)), *sym}));
}
}
context.Say(name, "type parameter is not INTEGER"_err_en_US);
} else {
context.Say(name,
"type parameter inquiry must be applied to a designator"_err_en_US);
@ -1263,8 +1268,7 @@ void ArrayConstructorContext::Add(const parser::AcValue &x) {
}
// Inverts a collection of generic ArrayConstructorValues<SomeType> that
// all happen to have or be convertible to the same actual type T into
// one ArrayConstructor<T>.
// all happen to have the same actual type T into one ArrayConstructor<T>.
template<typename T>
ArrayConstructorValues<T> MakeSpecific(
ArrayConstructorValues<SomeType> &&from) {
@ -1278,9 +1282,8 @@ ArrayConstructorValues<T> MakeSpecific(
to.Push(std::move(*typed));
},
[&](ImpliedDo<SomeType> &&impliedDo) {
to.Push(ImpliedDo<T>{impliedDo.controlVariableName,
std::move(*impliedDo.lower), std::move(*impliedDo.upper),
std::move(*impliedDo.stride),
to.Push(ImpliedDo<T>{impliedDo.name, std::move(*impliedDo.lower),
std::move(*impliedDo.upper), std::move(*impliedDo.stride),
MakeSpecific<T>(std::move(*impliedDo.values))});
},
},

View File

@ -2696,7 +2696,7 @@ void DeclarationVisitor::Post(const parser::DerivedTypeSpec &x) {
// values, and check constraints.
auto inLocation{
GetFoldingContext().messages.SetLocation(*currStmtSource())};
type.derivedTypeSpec().Instantiate(currScope(), GetFoldingContext());
type.derivedTypeSpec().Instantiate(currScope(), context());
}
SetDeclTypeSpec(type);
}

View File

@ -13,6 +13,7 @@
// limitations under the License.
#include "scope.h"
#include "semantics.h"
#include "symbol.h"
#include "type.h"
#include "../evaluate/fold.h"
@ -105,10 +106,10 @@ const DeclTypeSpec &Scope::MakeDerivedType(
}
const DeclTypeSpec &Scope::MakeDerivedType(DeclTypeSpec::Category category,
DerivedTypeSpec &&instance, evaluate::FoldingContext &foldingContext) {
DerivedTypeSpec &&instance, SemanticsContext &semanticsContext) {
DeclTypeSpec &type{declTypeSpecs_.emplace_back(
category, DerivedTypeSpec{std::move(instance)})};
type.derivedTypeSpec().Instantiate(*this, foldingContext);
type.derivedTypeSpec().Instantiate(*this, semanticsContext);
return type;
}
@ -234,29 +235,29 @@ const DeclTypeSpec *Scope::FindInstantiatedDerivedType(
}
const DeclTypeSpec &Scope::FindOrInstantiateDerivedType(DerivedTypeSpec &&spec,
DeclTypeSpec::Category category, evaluate::FoldingContext &foldingContext) {
spec.FoldParameterExpressions(foldingContext);
DeclTypeSpec::Category category, SemanticsContext &semanticsContext) {
spec.FoldParameterExpressions(semanticsContext.foldingContext());
if (const DeclTypeSpec * type{FindInstantiatedDerivedType(spec, category)}) {
return *type;
}
// Create a new instantiation of this parameterized derived type
// for this particular distinct set of actual parameter values.
DeclTypeSpec &type{MakeDerivedType(std::move(spec), category)};
type.derivedTypeSpec().Instantiate(*this, foldingContext);
type.derivedTypeSpec().Instantiate(*this, semanticsContext);
return type;
}
void Scope::InstantiateDerivedType(
Scope &clone, evaluate::FoldingContext &foldingContext) const {
Scope &clone, SemanticsContext &semanticsContext) const {
clone.sourceRange_ = sourceRange_;
clone.chars_ = chars_;
for (const auto &pair : symbols_) {
pair.second->Instantiate(clone, foldingContext);
pair.second->Instantiate(clone, semanticsContext);
}
}
const DeclTypeSpec &Scope::InstantiateIntrinsicType(
const DeclTypeSpec &spec, evaluate::FoldingContext &foldingContext) {
const DeclTypeSpec &spec, SemanticsContext &semanticsContext) {
const IntrinsicTypeSpec *intrinsic{spec.AsIntrinsic()};
CHECK(intrinsic != nullptr);
if (evaluate::ToInt64(intrinsic->kind()).has_value()) {
@ -265,27 +266,34 @@ const DeclTypeSpec &Scope::InstantiateIntrinsicType(
// The expression was not originally constant, but now it must be so
// in the context of a parameterized derived type instantiation.
KindExpr copy{intrinsic->kind()};
evaluate::FoldingContext &foldingContext{semanticsContext.foldingContext()};
copy = evaluate::Fold(foldingContext, std::move(copy));
auto value{evaluate::ToInt64(copy)};
CHECK(value.has_value() &&
"KIND parameter of intrinsic type did not resolve to a "
"constant INTEGER value in a parameterized derived type instance");
if (!evaluate::IsValidKindOfIntrinsicType(intrinsic->category(), *value)) {
int kind{
semanticsContext.defaultKinds().GetDefaultKind(intrinsic->category())};
if (auto value{evaluate::ToInt64(copy)}) {
if (evaluate::IsValidKindOfIntrinsicType(intrinsic->category(), *value)) {
kind = *value;
} else {
foldingContext.messages.Say(
"KIND parameter value (%jd) of intrinsic type %s did not resolve to a supported value"_err_en_US,
static_cast<std::intmax_t>(*value),
parser::ToUpperCaseLetters(
common::EnumToString(intrinsic->category()))
.data());
}
} else {
foldingContext.messages.Say(
"KIND parameter value (%jd) of intrinsic type %s did not resolve to a supported value"_err_en_US,
static_cast<std::intmax_t>(*value),
parser::ToUpperCaseLetters(common::EnumToString(intrinsic->category()))
.data());
"KIND parameter value did not resolve to a constant value"_err_en_US);
}
switch (spec.category()) {
case DeclTypeSpec::Numeric:
return declTypeSpecs_.emplace_back(
NumericTypeSpec{intrinsic->category(), KindExpr{*value}});
NumericTypeSpec{intrinsic->category(), KindExpr{kind}});
case DeclTypeSpec::Logical:
return declTypeSpecs_.emplace_back(LogicalTypeSpec{KindExpr{*value}});
return declTypeSpecs_.emplace_back(LogicalTypeSpec{KindExpr{kind}});
case DeclTypeSpec::Character:
return declTypeSpecs_.emplace_back(CharacterTypeSpec{
ParamValue{spec.characterTypeSpec().length()}, KindExpr{*value}});
ParamValue{spec.characterTypeSpec().length()}, KindExpr{kind}});
default: CRASH_NO_CASE;
}
}

View File

@ -25,12 +25,9 @@
#include <set>
#include <string>
namespace Fortran::evaluate {
struct FoldingContext;
}
namespace Fortran::semantics {
class SemanticsContext;
using namespace parser::literals;
class Scope {
@ -143,7 +140,7 @@ public:
const DeclTypeSpec &MakeDerivedType(
DeclTypeSpec::Category, DerivedTypeSpec &&);
const DeclTypeSpec &MakeDerivedType(
DeclTypeSpec::Category, DerivedTypeSpec &&, evaluate::FoldingContext &);
DeclTypeSpec::Category, DerivedTypeSpec &&, SemanticsContext &);
DeclTypeSpec &MakeDerivedType(const Symbol &);
DeclTypeSpec &MakeDerivedType(DerivedTypeSpec &&, DeclTypeSpec::Category);
const DeclTypeSpec &MakeTypeStarType();
@ -181,13 +178,13 @@ public:
// Returns a matching derived type instance if one exists, otherwise
// creates one
const DeclTypeSpec &FindOrInstantiateDerivedType(
DerivedTypeSpec &&, DeclTypeSpec::Category, evaluate::FoldingContext &);
DerivedTypeSpec &&, DeclTypeSpec::Category, SemanticsContext &);
// Clones a DerivedType scope into a new derived type instance's scope.
void InstantiateDerivedType(Scope &, evaluate::FoldingContext &) const;
void InstantiateDerivedType(Scope &, SemanticsContext &) const;
const DeclTypeSpec &InstantiateIntrinsicType(
const DeclTypeSpec &, evaluate::FoldingContext &);
const DeclTypeSpec &, SemanticsContext &);
private:
Scope &parent_; // this is enclosing scope, not extended derived type base

View File

@ -14,6 +14,7 @@
#include "symbol.h"
#include "scope.h"
#include "semantics.h"
#include "../common/idioms.h"
#include "../evaluate/fold.h"
#include <ostream>
@ -480,7 +481,8 @@ std::ostream &DumpForUnparse(
}
Symbol &Symbol::Instantiate(
Scope &scope, evaluate::FoldingContext &foldingContext) const {
Scope &scope, SemanticsContext &semanticsContext) const {
evaluate::FoldingContext foldingContext{semanticsContext.foldingContext()};
CHECK(foldingContext.pdtInstance != nullptr);
const DerivedTypeSpec &instanceSpec{*foldingContext.pdtInstance};
auto pair{scope.try_emplace(name_, attrs_)};
@ -513,11 +515,12 @@ Symbol &Symbol::Instantiate(
}
}
}
details.ReplaceType(scope.FindOrInstantiateDerivedType(
std::move(newSpec), origType->category(), foldingContext));
details.ReplaceType(
scope.FindOrInstantiateDerivedType(std::move(newSpec),
origType->category(), semanticsContext));
} else if (origType->AsIntrinsic() != nullptr) {
const DeclTypeSpec &newType{
scope.InstantiateIntrinsicType(*origType, foldingContext)};
const DeclTypeSpec &newType{scope.InstantiateIntrinsicType(
*origType, semanticsContext)};
details.ReplaceType(newType);
} else {
common::die("instantiated component has type that is "
@ -540,13 +543,14 @@ Symbol &Symbol::Instantiate(
},
[&](const ProcBindingDetails &that) {
symbol.details_ = ProcBindingDetails{
that.symbol().Instantiate(scope, foldingContext)};
that.symbol().Instantiate(scope, semanticsContext)};
},
[&](const GenericBindingDetails &that) {
symbol.details_ = GenericBindingDetails{};
GenericBindingDetails &details{symbol.get<GenericBindingDetails>()};
for (const Symbol *sym : that.specificProcs()) {
details.add_specificProc(sym->Instantiate(scope, foldingContext));
details.add_specificProc(
sym->Instantiate(scope, semanticsContext));
}
},
[&](const TypeParamDetails &that) {

View File

@ -22,10 +22,6 @@
#include <list>
#include <optional>
namespace Fortran::evaluate {
struct FoldingContext;
}
namespace Fortran::semantics {
/// A Symbol consists of common information (name, owner, and attributes)
@ -33,6 +29,7 @@ namespace Fortran::semantics {
/// *Details classes.
class Scope;
class SemanticsContext;
class Symbol;
using SymbolList = std::list<const Symbol *>;
@ -485,7 +482,7 @@ public:
}
// Clones the Symbol in the context of a parameterized derived type instance
Symbol &Instantiate(Scope &, evaluate::FoldingContext &) const;
Symbol &Instantiate(Scope &, SemanticsContext &) const;
// If there is a parent component, return a pointer to its
// derived type spec.

View File

@ -17,6 +17,7 @@
#include "scope.h"
#include "semantics.h"
#include "symbol.h"
#include "../common/restorer.h"
#include "../evaluate/fold.h"
#include "../evaluate/tools.h"
#include "../evaluate/type.h"
@ -64,7 +65,7 @@ void DerivedTypeSpec::FoldParameterExpressions(
}
void DerivedTypeSpec::Instantiate(
Scope &containingScope, evaluate::FoldingContext &origFoldingContext) {
Scope &containingScope, SemanticsContext &semanticsContext) {
CHECK(scope_ == nullptr);
Scope &newScope{containingScope.MakeScope(Scope::Kind::DerivedType)};
newScope.set_derivedTypeSpec(*this);
@ -78,8 +79,9 @@ void DerivedTypeSpec::Instantiate(
// parameter values to depend on those of their predecessors.
// The folded values of the expressions replace the init() expressions
// of the parameters' symbols in the instantiation's scope.
evaluate::FoldingContext foldingContext{origFoldingContext};
foldingContext.pdtInstance = this;
evaluate::FoldingContext &foldingContext{semanticsContext.foldingContext()};
auto savePDTInstance{common::ScopedSet(
foldingContext.pdtInstance, const_cast<const DerivedTypeSpec *>(this))};
for (Symbol *symbol : typeDetails.OrderParameterDeclarations(typeSymbol_)) {
const SourceName &name{symbol->name()};
@ -139,7 +141,7 @@ void DerivedTypeSpec::Instantiate(
// type's scope into the new instance.
const Scope *typeScope{typeSymbol_.scope()};
CHECK(typeScope != nullptr);
typeScope->InstantiateDerivedType(newScope, foldingContext);
typeScope->InstantiateDerivedType(newScope, semanticsContext);
}
std::ostream &operator<<(std::ostream &o, const DerivedTypeSpec &x) {

View File

@ -238,7 +238,7 @@ public:
}
}
void FoldParameterExpressions(evaluate::FoldingContext &);
void Instantiate(Scope &, evaluate::FoldingContext &);
void Instantiate(Scope &, SemanticsContext &);
bool operator==(const DerivedTypeSpec &) const; // for std::find()
private:

View File

@ -23,6 +23,7 @@ module m
real, parameter :: a5(:) = [6.0, 7.0, 8.0]
real, parameter :: a6(2) = [9, 10]
real, parameter :: a7(6) = [([(1.0*k,k=1,j)],j=1,3)]
real, parameter :: a8(13) = [real::1,2_1,3_2,4_4,5_8,6_16,7._2,8._3,9._4,10._8,11._16,(12.,12.5),(13._8,13.5)]
end module m
!Expect: m.mod
@ -35,4 +36,5 @@ end module m
!real(4),parameter::a5(1_8:)=[Real(4)::6._4,7._4,8._4]
!real(4),parameter::a6(1_8:2_8)=[Integer(4)::9_4,10_4]
!real(4),parameter::a7(1_8:6_8)=[Real(4)::1._4,1._4,2._4,1._4,2._4,3._4]
!real(4),parameter::a8(1_8:13_8)=[Real(4)::1._4,2._4,3._4,4._4,5._4,6._4,7._4,8._4,9._4,10._4,11._4,12._4,13._4]
!end