forked from OSchip/llvm-project
[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:
parent
1c95fef459
commit
140b4adcfe
|
@ -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_
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))});
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue