[flang-commits] [flang] f6ecea1 - [flang] Represent (parentheses around derived types)
peter klausler via flang-commits
flang-commits at lists.llvm.org
Thu Sep 23 13:40:39 PDT 2021
Author: peter klausler
Date: 2021-09-23T13:03:13-07:00
New Revision: f6ecea1a35758bbb504bc8d6f5dccf353ea1355b
URL: https://github.com/llvm/llvm-project/commit/f6ecea1a35758bbb504bc8d6f5dccf353ea1355b
DIFF: https://github.com/llvm/llvm-project/commit/f6ecea1a35758bbb504bc8d6f5dccf353ea1355b.diff
LOG: [flang] Represent (parentheses around derived types)
The strongly typed expression representation classes supported
a representation of parentheses only around intrinsic types
with specific kinds. Parentheses around derived type variables
must also be preserved so that expressions may be distinguished
from variables; this distinction matters for actual arguments &
construct associations.
Differential Revision: https://reviews.llvm.org/D110355
Added:
flang/test/Evaluate/expr01.f90
Modified:
flang/include/flang/Evaluate/expression.h
flang/lib/Evaluate/expression.cpp
flang/lib/Evaluate/tools.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Evaluate/expression.h b/flang/include/flang/Evaluate/expression.h
index 8eacdef227353..ea68f6e3e9de0 100644
--- a/flang/include/flang/Evaluate/expression.h
+++ b/flang/include/flang/Evaluate/expression.h
@@ -116,8 +116,10 @@ class Operation {
public:
using Derived = DERIVED;
using Result = RESULT;
- static_assert(IsSpecificIntrinsicType<Result>);
static constexpr std::size_t operands{sizeof...(OPERANDS)};
+ // Allow specific intrinsic types and Parentheses<SomeDerived>
+ static_assert(IsSpecificIntrinsicType<Result> ||
+ (operands == 1 && std::is_same_v<Result, SomeDerived>));
template <int J> using Operand = std::tuple_element_t<J, OperandTypes>;
// Unary operations wrap a single Expr with a CopyableIndirection.
@@ -172,7 +174,9 @@ class Operation {
}
}
- static constexpr std::optional<DynamicType> GetType() {
+ static constexpr std::conditional_t<Result::category != TypeCategory::Derived,
+ std::optional<DynamicType>, void>
+ GetType() {
return Result::GetType();
}
int Rank() const {
@@ -222,6 +226,17 @@ struct Parentheses : public Operation<Parentheses<A>, A, A> {
using Base::Base;
};
+template <>
+struct Parentheses<SomeDerived>
+ : public Operation<Parentheses<SomeDerived>, SomeDerived, SomeDerived> {
+public:
+ using Result = SomeDerived;
+ using Operand = SomeDerived;
+ using Base = Operation<Parentheses, SomeDerived, SomeDerived>;
+ using Base::Base;
+ DynamicType GetType() const;
+};
+
template <typename A> struct Negate : public Operation<Negate<A>, A, A> {
using Result = A;
using Operand = A;
@@ -730,7 +745,7 @@ template <> class Expr<SomeDerived> : public ExpressionBase<SomeDerived> {
using Result = SomeDerived;
EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
std::variant<Constant<Result>, ArrayConstructor<Result>, StructureConstructor,
- Designator<Result>, FunctionRef<Result>>
+ Designator<Result>, FunctionRef<Result>, Parentheses<Result>>
u;
};
diff --git a/flang/lib/Evaluate/expression.cpp b/flang/lib/Evaluate/expression.cpp
index 7f8c9eb32f3f2..c08e9771514b0 100644
--- a/flang/lib/Evaluate/expression.cpp
+++ b/flang/lib/Evaluate/expression.cpp
@@ -107,6 +107,10 @@ template <typename A> int ExpressionBase<A>::Rank() const {
derived().u);
}
+DynamicType Parentheses<SomeDerived>::GetType() const {
+ return left().GetType().value();
+}
+
// Equality testing
bool ImpliedDoIndex::operator==(const ImpliedDoIndex &that) const {
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index dd66259789ff4..bf50eb99e1267 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -35,9 +35,10 @@ Expr<SomeType> Parenthesize(Expr<SomeType> &&expr) {
return std::visit(
[&](auto &&x) {
using T = std::decay_t<decltype(x)>;
- if constexpr (common::HasMember<T, TypelessExpression> ||
- std::is_same_v<T, Expr<SomeDerived>>) {
- return expr; // no parentheses around typeless or derived type
+ if constexpr (common::HasMember<T, TypelessExpression>) {
+ return expr; // no parentheses around typeless
+ } else if constexpr (std::is_same_v<T, Expr<SomeDerived>>) {
+ return AsGenericExpr(Parentheses<SomeDerived>{std::move(x)});
} else {
return std::visit(
[](auto &&y) {
diff --git a/flang/test/Evaluate/expr01.f90 b/flang/test/Evaluate/expr01.f90
new file mode 100644
index 0000000000000..c0f843778406c
--- /dev/null
+++ b/flang/test/Evaluate/expr01.f90
@@ -0,0 +1,34 @@
+! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
+! Ensures that parentheses are preserved with derived types
+module m
+ type :: t
+ integer :: n
+ end type
+ contains
+ subroutine sub(x)
+ type(t), intent(in) :: x
+ end subroutine
+ function f(m)
+ type(t), pointer :: f
+ integer, intent(in) :: m
+ type(t), save, target :: res
+ res%n = m
+ f => res
+ end function
+ subroutine test
+ type(t) :: x
+ x = t(1)
+ !CHECK: CALL sub(t(n=1_4))
+ call sub(t(1))
+ !CHECK: CALL sub((t(n=1_4)))
+ call sub((t(1)))
+ !CHECK: CALL sub(x)
+ call sub(x)
+ !CHECK: CALL sub((x))
+ call sub((x))
+ !CHECK: CALL sub(f(2_4))
+ call sub(f(2))
+ !CHECK: CALL sub((f(2_4)))
+ call sub((f(2)))
+ end subroutine
+end module
More information about the flang-commits
mailing list