This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix PR c++/69694 (non-dependent MODOP_EXPR with NULL type)


On Sat, Feb 20, 2016 at 5:22 PM, Patrick Palka <patrick@parcs.ath.cx> wrote:
> The problem here is that when processing_template_decl, the non-compound
> MODOP_EXPRs we build (i.e. a = b and not a += b) are given a NULL
> TREE_TYPE even if none of its operands are dependent.  This causes
> decltypes such as "decltype (a = b)" (where a and b are not dependent)
> to fail to get resolved to a concrete type since the MODOP_EXPR within
> is considered to be dependent according to instantiation_dependent_expression_p.
> And in the case of decltype65.C this causes partial-specialization
> selection to malfunction since the template parameter type
> "void_t<decltype (a = b)>" never gets resolved to "void".
>
> This patch fixes this issue by adjusting build_x_modify_expr to give
> non-compound non-dependent MODOP_EXPRs an accurate non-NULL TREE_TYPE.
> To do this we have to first process the assignment at template
> processing time using cp_build_modify_expr.  This means we will now
> diagnose invalid assignments at template-processing time, necessitating
> some minor adjustments to the testsuite.
>
> The changes to the test suite are trivial except for the change to
> unary2.C.  Here, whereas before we were always failing to diagnose at
> template processing time the invalid assignment -n = 0 (whose LHS is not
> an lvalue), after this patch we now fail to diagnose this invalid
> assignment only with c++98.  This is because lvalue_kind treats
> NON_DEPENDENT_EXPRs differently depending on the cxx_dialect:
>
>     case NON_DEPENDENT_EXPR:
>       /* We just return clk_ordinary for NON_DEPENDENT_EXPR in C++98, but
>          in C++11 lvalues don't bind to rvalue references, so we need to
>          work harder to avoid bogus errors (c++/44870).  */
>       if (cxx_dialect < cxx11)
>         return clk_ordinary;
>       else
>         return lvalue_kind (TREE_OPERAND (ref, 0));
>
> So in c++98 mode any NON_DEPENDENT_EXPR is considered to be a valid LHS
> of an assignment even if the underlying expression is not actually an
> lvalue.  Removing this special case is not completely trivial.
>
> Bootstrap + regtest in progress on x86_64-pc-linux-gnu, will also test
> against Boost.  Does this look OK if testing passes?
>
> gcc/cp/ChangeLog:
>
>         PR c++/69694
>         * semantics.c (finish_paranthesized_expr): Set the
>         TREE_NO_WARNING flag on MODOP_EXPRs that are wrapped in an
>         implicit INDIRECT_REF.
>         * typeck.c (build_x_modify_expr): Give the middle operand of
>         the resulting MODOP_EXPR a dummy non-NULL type.  When MODIFYCODE
>         is NOP_EXPR and the operands are not dependent, don't exit early
>         and instead process the expression with cp_build_modify_expr.
>         Assert that the return value of build_new_op is non-NULL.
>
> gcc/testsuite/ChangeLog:
>
>         PR c++/69694
>         * g++.dg/cpp0x/decltype64.C: New test.
>         * g++.dg/cpp0x/decltype65.C: New test.
>         * g++.dg/expr/unary2.C: The XFAILs no longer fail
>         on c++11 or later, only with c++98.
>         * g++.dg/cpp0x/error2.C: Adjust expected error message.
>         * g++.dg/ext/fixed1.C: Likewise.
>         * g++.dg/template/error35.C: Likewise.
>         * g++.dg/template/init7.C: Likewise.

Just noticed that this patch would cause auto deduction to malfunction
when a non-dependent plain assignment resolves to an operator
overload.  In that case we should be building the assignment using
build_min_non_dep_op_overload as well.  Test case:

struct Foo
{
  int operator=(const Foo &)
  {
    return 5;
  }
};

template <typename>
void
foo (Foo &x, Foo &y)
{
  auto&& a = (x = y);
  const int &b = a;
}

void
bar ()
{
  Foo a;
  Foo b;

  foo<int> (a, b);
}

operator=.cc: In instantiation of âvoid foo(Foo&, Foo&) [with
<template-parameter-1-1> = int]â:
operator=.cc:23:17:   required from here
operator=.cc:13:17: error: invalid initialization of non-const
reference of type âint&â from an rvalue of type âintâ
   auto&& a = (x = y);
              ~~~^~~~


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]