From: peter klausler Date: Wed, 22 Sep 2021 23:49:09 +0000 (-0700) Subject: [flang] Represent (parentheses around derived types) X-Git-Tag: upstream/15.0.7~30688 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f6ecea1a35758bbb504bc8d6f5dccf353ea1355b;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/flang/include/flang/Evaluate/expression.h b/flang/include/flang/Evaluate/expression.h index 8eacdef..ea68f6e 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); static constexpr std::size_t operands{sizeof...(OPERANDS)}; + // Allow specific intrinsic types and Parentheses + static_assert(IsSpecificIntrinsicType || + (operands == 1 && std::is_same_v)); template using Operand = std::tuple_element_t; // Unary operations wrap a single Expr with a CopyableIndirection. @@ -172,7 +174,9 @@ public: } } - static constexpr std::optional GetType() { + static constexpr std::conditional_t, void> + GetType() { return Result::GetType(); } int Rank() const { @@ -222,6 +226,17 @@ struct Parentheses : public Operation, A, A> { using Base::Base; }; +template <> +struct Parentheses + : public Operation, SomeDerived, SomeDerived> { +public: + using Result = SomeDerived; + using Operand = SomeDerived; + using Base = Operation; + using Base::Base; + DynamicType GetType() const; +}; + template struct Negate : public Operation, A, A> { using Result = A; using Operand = A; @@ -730,7 +745,7 @@ public: using Result = SomeDerived; EVALUATE_UNION_CLASS_BOILERPLATE(Expr) std::variant, ArrayConstructor, StructureConstructor, - Designator, FunctionRef> + Designator, FunctionRef, Parentheses> u; }; diff --git a/flang/lib/Evaluate/expression.cpp b/flang/lib/Evaluate/expression.cpp index 7f8c9eb..c08e977 100644 --- a/flang/lib/Evaluate/expression.cpp +++ b/flang/lib/Evaluate/expression.cpp @@ -107,6 +107,10 @@ template int ExpressionBase::Rank() const { derived().u); } +DynamicType Parentheses::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 dd66259..bf50eb9 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -35,9 +35,10 @@ Expr Parenthesize(Expr &&expr) { return std::visit( [&](auto &&x) { using T = std::decay_t; - if constexpr (common::HasMember || - std::is_same_v>) { - return expr; // no parentheses around typeless or derived type + if constexpr (common::HasMember) { + return expr; // no parentheses around typeless + } else if constexpr (std::is_same_v>) { + return AsGenericExpr(Parentheses{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 0000000..c0f8437 --- /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