[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...>;
};
template<template<typename...> class T, typename TorV>
using OverMembers = typename OverMembersHelper<T, std::decay_t<TorV>>::type;
template<template<typename...> class T, typename TUPLEorVARIANT>
using OverMembers =
typename OverMembersHelper<T, std::decay_t<TUPLEorVARIANT>>::type;
// SearchMembers<PREDICATE> scans the types that constitute the alternatives
// 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{
OverMembers<SearchMembersHelper<PREDICATE>::template Scanner,
TorV>::value()};
TUPLEorVARIANT>::value()};
template<typename A, typename TorV>
template<typename A, typename TUPLEorVARIANT>
constexpr bool HasMember{
SearchMembers<MatchType<A>::template Match, TorV> >= 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));
}
SearchMembers<MatchType<A>::template Match, TUPLEorVARIANT> >= 0};
// std::optional<std::optional<A>> -> std::optional<A>
template<typename A>
@ -209,9 +193,10 @@ template<template<typename> class F, template<typename...> class PACKAGE,
struct MapTemplateHelper<F, PACKAGE, std::variant<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>
using MapTemplate = typename MapTemplateHelper<F, PACKAGE, TorV>::type;
using MapTemplate =
typename MapTemplateHelper<F, PACKAGE, TUPLEorVARIANT>::type;
// std::tuple<std::optional<>...> -> std::optional<std::tuple<...>>
// 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
-> std::optional<Scalar<Result>> {
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};
}
// TODO: every specifically-typed Expr should support Parentheses
if constexpr (common::HasMember<Parentheses<Result>,
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();
}
}

View File

@ -103,7 +103,7 @@ Expr<TO> ConvertToType(Expr<SomeKind<FROMCAT>> &&x) {
}
} else {
// 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);
}
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)
: u{std::move(x)} {}
auto ToInt64() const {
std::optional<std::int64_t> ToInt64() const {
return std::visit(
[](const auto &x) -> std::optional<std::int64_t> {
if constexpr (TypeOf<decltype(x)>::category ==
@ -222,7 +222,7 @@ template<typename TYPES> struct SomeScalar {
u);
}
auto ToString() const {
std::optional<std::string> ToString() const {
return std::visit(
[](const auto &x) -> std::optional<std::string> {
if constexpr (std::is_same_v<std::string,
@ -234,7 +234,7 @@ template<typename TYPES> struct SomeScalar {
u);
}
auto IsTrue() const {
std::optional<bool> IsTrue() const {
return std::visit(
[](const auto &x) -> std::optional<bool> {
if constexpr (TypeOf<decltype(x)>::category ==
@ -246,10 +246,6 @@ template<typename TYPES> struct SomeScalar {
u);
}
template<typename T> auto GetIf() const {
return common::GetIf<Scalar<T>>(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) {
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 (sign == parser::Sign::Negative) {
return {AsGenericExpr(-*common::GetIf<Expr<SomeReal>>(result->u))};
return {AsGenericExpr(-std::move(*realExpr))};
}
}
return result;
@ -397,32 +399,38 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
return {AsGenericExpr(value.value)};
}
template<typename TYPE, TypeCategory CATEGORY>
MaybeExpr DataRefIfType(
const semantics::Symbol &symbol, int defaultKind, DataRef &&dataRef) {
template<TypeCategory CATEGORY>
MaybeExpr TypedDataRefHelper(int kind, 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 (details->type().has_value()) {
if (details->type()->category() ==
semantics::DeclTypeSpec::Category::Intrinsic) {
std::uint64_t kindParam{
details->type()->intrinsicTypeSpec().kind().value().value()};
int kind = static_cast<int>(kindParam);
if (static_cast<std::uint64_t>(kind) == kindParam) {
// TODO: Inspection of semantics::IntrinsicTypeSpec requires the use
// of forbidden RTTI via dynamic_cast<>. See whether
// semantics::IntrinsicTypeSpec can be augmented with query
// interfaces instead.
if (dynamic_cast<const TYPE *>(
&details->type()->intrinsicTypeSpec()) != nullptr) {
if (kind == 0) { // TODO: resolve default kinds in semantics
kind = defaultKind;
}
if (MaybeExpr result{common::SearchDynamicTypes(
TypeKindVisitor<CATEGORY, DataReference, DataRef>{
kind, std::move(dataRef)})}) {
return result;
}
}
TypeCategory category{details->type()->intrinsicTypeSpec().category()};
int kind{details->type()->intrinsicTypeSpec().kind()};
switch (category) {
case TypeCategory::Integer:
return TypedDataRefHelper<TypeCategory::Integer>(
kind, std::move(dataRef));
case TypeCategory::Real:
return TypedDataRefHelper<TypeCategory::Real>(
kind, std::move(dataRef));
case TypeCategory::Complex:
return TypedDataRefHelper<TypeCategory::Complex>(
kind, std::move(dataRef));
case TypeCategory::Character:
return TypedDataRefHelper<TypeCategory::Character>(
kind, std::move(dataRef));
case TypeCategory::Logical:
return TypedDataRefHelper<TypeCategory::Logical>(
kind, std::move(dataRef));
default: CRASH_NO_CASE;
}
}
}
@ -430,36 +438,6 @@ MaybeExpr DataRefIfType(
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;
}
MaybeExpr ExprAnalyzer::Analyze(const parser::Name &n) {
if (n.symbol == nullptr) {
// TODO: convert this to a CHECK later
@ -471,8 +449,7 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::Name &n) {
"TODO: PARAMETER references not yet implemented"_err_en_US);
// TODO: enumerators, do they have the PARAMETER attribute?
} else {
if (MaybeExpr result{
TypedDataRef(*n.symbol, defaults, DataRef{*n.symbol})}) {
if (MaybeExpr result{TypedDataRef(*n.symbol, DataRef{*n.symbol})}) {
return result;
}
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());
} else {
ArrayRef arrayRef{*name->symbol, std::move(subscripts)};
return TypedDataRef(
*name->symbol, defaults, DataRef{std::move(arrayRef)});
return TypedDataRef(*name->symbol, DataRef{std::move(arrayRef)});
}
} else if (const auto *component{
std::get_if<common::Indirection<parser::StructureComponent>>(