[flang] Merge with current master, address early review comments.

Original-commit: flang-compiler/f18@d1f981ddb4
Reviewed-on: https://github.com/flang-compiler/f18/pull/183
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-09-12 13:53:14 -07:00
parent a73eebdbca
commit 55763194f1
5 changed files with 49 additions and 92 deletions

View File

@ -78,8 +78,9 @@ struct OverMembersHelper<T, std::tuple<Ts...>> {
using type = T<Ts...>; using type = T<Ts...>;
}; };
template<template<typename...> class T, typename TorV> template<template<typename...> class T, typename TUPLEorVARIANT>
using OverMembers = typename OverMembersHelper<T, std::decay_t<TorV>>::type; using OverMembers =
typename OverMembersHelper<T, std::decay_t<TUPLEorVARIANT>>::type;
// SearchMembers<PREDICATE> scans the types that constitute the alternatives // SearchMembers<PREDICATE> scans the types that constitute the alternatives
// of a std::variant instantiation or elements of a std::tuple. // of a std::variant instantiation or elements of a std::tuple.
@ -92,31 +93,14 @@ template<template<typename> class PREDICATE> struct SearchMembersHelper {
}; };
}; };
template<template<typename> class PREDICATE, typename TorV> template<template<typename> class PREDICATE, typename TUPLEorVARIANT>
constexpr int SearchMembers{ constexpr int SearchMembers{
OverMembers<SearchMembersHelper<PREDICATE>::template Scanner, OverMembers<SearchMembersHelper<PREDICATE>::template Scanner,
TorV>::value()}; TUPLEorVARIANT>::value()};
template<typename A, typename TorV> template<typename A, typename TUPLEorVARIANT>
constexpr bool HasMember{ constexpr bool HasMember{
SearchMembers<MatchType<A>::template Match, TorV> >= 0}; SearchMembers<MatchType<A>::template Match, TUPLEorVARIANT> >= 0};
// const A * -> std::optional<A>
template<typename A> std::optional<A> GetIfNonNull(const A *p) {
if (p) {
return {*p};
}
return std::nullopt;
}
// const std::variant<..., A, ...> -> std::optional<A>
// i.e., when a variant holds a value of a particular type, return a copy
// of that value in a std::optional<>. The type A must be a valid
// alternative for the variant.
template<typename A, typename VARIANT>
std::optional<A> GetIf(const VARIANT &u) {
return GetIfNonNull(std::get_if<A>(&u));
}
// std::optional<std::optional<A>> -> std::optional<A> // std::optional<std::optional<A>> -> std::optional<A>
template<typename A> template<typename A>
@ -209,9 +193,10 @@ template<template<typename> class F, template<typename...> class PACKAGE,
struct MapTemplateHelper<F, PACKAGE, std::variant<Ts...>> { struct MapTemplateHelper<F, PACKAGE, std::variant<Ts...>> {
using type = PACKAGE<F<Ts>...>; using type = PACKAGE<F<Ts>...>;
}; };
template<template<typename> class F, typename TorV, template<template<typename> class F, typename TUPLEorVARIANT,
template<typename...> class PACKAGE = std::variant> template<typename...> class PACKAGE = std::variant>
using MapTemplate = typename MapTemplateHelper<F, PACKAGE, TorV>::type; using MapTemplate =
typename MapTemplateHelper<F, PACKAGE, TUPLEorVARIANT>::type;
// std::tuple<std::optional<>...> -> std::optional<std::tuple<...>> // std::tuple<std::optional<>...> -> std::optional<std::tuple<...>>
// i.e., inverts a tuple of optional values into an optional tuple that has // i.e., inverts a tuple of optional values into an optional tuple that has

View File

@ -503,13 +503,13 @@ template<typename RESULT>
auto ExpressionBase<RESULT>::ScalarValue() const auto ExpressionBase<RESULT>::ScalarValue() const
-> std::optional<Scalar<Result>> { -> std::optional<Scalar<Result>> {
if constexpr (Result::isSpecificType) { if constexpr (Result::isSpecificType) {
if (auto c{common::GetIf<Constant<Result>>(derived().u)}) { if (auto *c{std::get_if<Constant<Result>>(&derived().u)}) {
return {c->value}; return {c->value};
} }
// TODO: every specifically-typed Expr should support Parentheses // TODO: every specifically-typed Expr should support Parentheses
if constexpr (common::HasMember<Parentheses<Result>, if constexpr (common::HasMember<Parentheses<Result>,
decltype(derived().u)>) { decltype(derived().u)>) {
if (auto p{common::GetIf<Parentheses<Result>>(derived().u)}) { if (auto *p{std::get_if<Parentheses<Result>>(&derived().u)}) {
return p->left().ScalarValue(); return p->left().ScalarValue();
} }
} }

View File

@ -103,7 +103,7 @@ Expr<TO> ConvertToType(Expr<SomeKind<FROMCAT>> &&x) {
} }
} else { } else {
// Same type category // Same type category
if (auto already{common::GetIf<Expr<TO>>(x.u)}) { if (auto *already{std::get_if<Expr<TO>>(&x.u)}) {
return std::move(*already); return std::move(*already);
} }
if constexpr (TO::category == TypeCategory::Complex) { if constexpr (TO::category == TypeCategory::Complex) {

View File

@ -210,7 +210,7 @@ template<typename TYPES> struct SomeScalar {
SomeScalar(std::enable_if_t<!std::is_reference_v<A>, A> &&x) SomeScalar(std::enable_if_t<!std::is_reference_v<A>, A> &&x)
: u{std::move(x)} {} : u{std::move(x)} {}
auto ToInt64() const { std::optional<std::int64_t> ToInt64() const {
return std::visit( return std::visit(
[](const auto &x) -> std::optional<std::int64_t> { [](const auto &x) -> std::optional<std::int64_t> {
if constexpr (TypeOf<decltype(x)>::category == if constexpr (TypeOf<decltype(x)>::category ==
@ -222,7 +222,7 @@ template<typename TYPES> struct SomeScalar {
u); u);
} }
auto ToString() const { std::optional<std::string> ToString() const {
return std::visit( return std::visit(
[](const auto &x) -> std::optional<std::string> { [](const auto &x) -> std::optional<std::string> {
if constexpr (std::is_same_v<std::string, if constexpr (std::is_same_v<std::string,
@ -234,7 +234,7 @@ template<typename TYPES> struct SomeScalar {
u); u);
} }
auto IsTrue() const { std::optional<bool> IsTrue() const {
return std::visit( return std::visit(
[](const auto &x) -> std::optional<bool> { [](const auto &x) -> std::optional<bool> {
if constexpr (TypeOf<decltype(x)>::category == if constexpr (TypeOf<decltype(x)>::category ==
@ -246,10 +246,6 @@ template<typename TYPES> struct SomeScalar {
u); u);
} }
template<typename T> auto GetIf() const {
return common::GetIf<Scalar<T>>(u);
}
common::MapTemplate<Scalar, Types> u; common::MapTemplate<Scalar, Types> u;
}; };

View File

@ -323,9 +323,11 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::RealLiteralConstant &x) {
MaybeExpr ExprAnalyzer::Analyze(const parser::SignedRealLiteralConstant &x) { MaybeExpr ExprAnalyzer::Analyze(const parser::SignedRealLiteralConstant &x) {
if (MaybeExpr result{Analyze(std::get<parser::RealLiteralConstant>(x.t))}) { if (MaybeExpr result{Analyze(std::get<parser::RealLiteralConstant>(x.t))}) {
auto *realExpr{std::get_if<Expr<SomeReal>>(&result->u)};
CHECK(realExpr != nullptr);
if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) { if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) {
if (sign == parser::Sign::Negative) { if (sign == parser::Sign::Negative) {
return {AsGenericExpr(-*common::GetIf<Expr<SomeReal>>(result->u))}; return {AsGenericExpr(-std::move(*realExpr))};
} }
} }
return result; return result;
@ -397,66 +399,42 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
return {AsGenericExpr(value.value)}; return {AsGenericExpr(value.value)};
} }
template<typename TYPE, TypeCategory CATEGORY> template<TypeCategory CATEGORY>
MaybeExpr DataRefIfType( MaybeExpr TypedDataRefHelper(int kind, DataRef &&dataRef) {
const semantics::Symbol &symbol, int defaultKind, DataRef &&dataRef) { return common::SearchDynamicTypes(
TypeKindVisitor<CATEGORY, DataReference, DataRef>{
kind, std::move(dataRef)});
}
static MaybeExpr TypedDataRef(
const semantics::Symbol &symbol, DataRef &&dataRef) {
if (auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) { if (auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
if (details->type().has_value()) { if (details->type().has_value()) {
if (details->type()->category() == if (details->type()->category() ==
semantics::DeclTypeSpec::Category::Intrinsic) { semantics::DeclTypeSpec::Category::Intrinsic) {
std::uint64_t kindParam{ TypeCategory category{details->type()->intrinsicTypeSpec().category()};
details->type()->intrinsicTypeSpec().kind().value().value()}; int kind{details->type()->intrinsicTypeSpec().kind()};
int kind = static_cast<int>(kindParam); switch (category) {
if (static_cast<std::uint64_t>(kind) == kindParam) { case TypeCategory::Integer:
// TODO: Inspection of semantics::IntrinsicTypeSpec requires the use return TypedDataRefHelper<TypeCategory::Integer>(
// of forbidden RTTI via dynamic_cast<>. See whether kind, std::move(dataRef));
// semantics::IntrinsicTypeSpec can be augmented with query case TypeCategory::Real:
// interfaces instead. return TypedDataRefHelper<TypeCategory::Real>(
if (dynamic_cast<const TYPE *>( kind, std::move(dataRef));
&details->type()->intrinsicTypeSpec()) != nullptr) { case TypeCategory::Complex:
if (kind == 0) { // TODO: resolve default kinds in semantics return TypedDataRefHelper<TypeCategory::Complex>(
kind = defaultKind; kind, std::move(dataRef));
} case TypeCategory::Character:
if (MaybeExpr result{common::SearchDynamicTypes( return TypedDataRefHelper<TypeCategory::Character>(
TypeKindVisitor<CATEGORY, DataReference, DataRef>{ kind, std::move(dataRef));
kind, std::move(dataRef)})}) { case TypeCategory::Logical:
return result; return TypedDataRefHelper<TypeCategory::Logical>(
kind, std::move(dataRef));
default: CRASH_NO_CASE;
} }
} }
} }
} }
}
}
return std::nullopt;
}
static MaybeExpr TypedDataRef(const semantics::Symbol &symbol,
const semantics::IntrinsicTypeDefaultKinds &defaults, DataRef &&dataRef) {
if (MaybeExpr result{
DataRefIfType<semantics::IntegerTypeSpec, TypeCategory::Integer>(
symbol, defaults.defaultIntegerKind, std::move(dataRef))}) {
return result;
}
if (MaybeExpr result{
DataRefIfType<semantics::RealTypeSpec, TypeCategory::Real>(
symbol, defaults.defaultRealKind, std::move(dataRef))}) {
return result;
}
if (MaybeExpr result{
DataRefIfType<semantics::ComplexTypeSpec, TypeCategory::Complex>(
symbol, defaults.defaultRealKind, std::move(dataRef))}) {
return result;
}
if (MaybeExpr result{
DataRefIfType<semantics::CharacterTypeSpec, TypeCategory::Character>(
symbol, defaults.defaultCharacterKind, std::move(dataRef))}) {
return result;
}
if (MaybeExpr result{
DataRefIfType<semantics::LogicalTypeSpec, TypeCategory::Logical>(
symbol, defaults.defaultLogicalKind, std::move(dataRef))}) {
return result;
}
return std::nullopt; return std::nullopt;
} }
@ -471,8 +449,7 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::Name &n) {
"TODO: PARAMETER references not yet implemented"_err_en_US); "TODO: PARAMETER references not yet implemented"_err_en_US);
// TODO: enumerators, do they have the PARAMETER attribute? // TODO: enumerators, do they have the PARAMETER attribute?
} else { } else {
if (MaybeExpr result{ if (MaybeExpr result{TypedDataRef(*n.symbol, DataRef{*n.symbol})}) {
TypedDataRef(*n.symbol, defaults, DataRef{*n.symbol})}) {
return result; return result;
} }
context.messages.Say("'%s' is not of a supported type and kind"_err_en_US, context.messages.Say("'%s' is not of a supported type and kind"_err_en_US,
@ -562,8 +539,7 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::ArrayElement &ae) {
name->ToString().data()); name->ToString().data());
} else { } else {
ArrayRef arrayRef{*name->symbol, std::move(subscripts)}; ArrayRef arrayRef{*name->symbol, std::move(subscripts)};
return TypedDataRef( return TypedDataRef(*name->symbol, DataRef{std::move(arrayRef)});
*name->symbol, defaults, DataRef{std::move(arrayRef)});
} }
} else if (const auto *component{ } else if (const auto *component{
std::get_if<common::Indirection<parser::StructureComponent>>( std::get_if<common::Indirection<parser::StructureComponent>>(