The NOP_EXPR are changing the "visible" types without changing
the representation; sometimes it is about lvalueness being thrown
away (which I suspect is the case here).  I've always grumbled about not
having a uniform way of saying "convert this expression to type T
to an expression of type U".

On Sat, May 5, 2012 at 5:38 AM, Paolo Carlini <paolo.carl...@oracle.com> wrote:
> Hi,
>
> I'm analyzing this PR and the various testcases which come with it. It looks
> like we have indeed two separate issues: one, which looks simpler, with
> decltype, leading to ICEs; a more complex one with constexpr. The former is
> about ADDR_EXPR unhandled in the finish_decltype_type switch for this
> testcase:
>
> template <typename T, T V>
> struct C
> {
> static constexpr decltype(V) c() { return V; }
> };
>
> struct D
> {
> static constexpr int d() { return 10; }
> };
>
> static_assert((C<int(*)(), &D::d>::c())() == 10, "oops");
>
> Would it make sense to just handle ADDR_EXPR too like in the patchlet below?
> It seems we are in this case too in the same situation which led to handling
> INTEGER_CST and PTRMEM_CST, or we have an issue with const-ness?
>
> The problems with constexpr look more nasty, are all about testcases similar
> to the above, many variants of it, like:
>
> template <typename T, T V>
> struct B
> {
> typedef T type;
> static constexpr type b() { return V; }
> };
>
> struct D
> {
> static constexpr int d() { return 10; }
> };
>
> static_assert((B<int(*)(), &D::d>::b())() == 10, "oops");
>
> which is rejected like:
>
> 52282.C:32:1: error: non-constant condition for static assertion
> static_assert((B<int(*)(), &D::d>::b())() == 10, "oops"); // line 30
>
> 52282.C:32:38: error: expression ā€˜D::d’ does not designate a constexpr
> function
> static_assert((B<int(*)(), &D::d>::b())() == 10, "oops"); // line 30
>
> For this kind of testcase I see a lot of NOP_EXPRs around, which I don't
> really understand and *appear* to confuse quite a bit code we have in the
> cxx_eval_* functions. For example, for the above, one crops up at the
> beginning of cxx_eval_call_expression:
>
> if (TREE_CODE (fun) != FUNCTION_DECL)
> {
> /* Might be a constexpr function pointer. */
> fun = cxx_eval_constant_expression (old_call, fun, allow_non_constant,
> /*addr*/false, non_constant_p);
> if (TREE_CODE (fun) == ADDR_EXPR)
> fun = TREE_OPERAND (fun, 0);
> }
>
> as the fun returned by cxx_eval_constant_expression and the logic handling
> ADDR_EXPR doesn't seem to work as designed. If I force a STRIP_NOPS the
> testcase is "accepted". But really I see something brittle about all these
> NOP_EXPRs and I'm looking for comments / hints. I don't think we just want
> to add STRIP_NOPS in a ton of places, which, if I understand correctly,
> would probably also imply the need to unshare_expr, but I don't have
> brilliant ideas right now...
>
> Another kind of weird issue we are facing is for:
>
> template <typename T, T V>
> struct W_ { static constexpr T value = V; };
>
> constexpr struct C {
> constexpr int c1() const { return 10; }
> } c;
>
> static_assert((c.*W_<int(C::*)()const, &C::c1>::value)() == 10, "oops");
>
> which leads to:
>
> ice.cpp:72:1: error: non-constant condition for static assertion
> static_assert((c.*W_<int(C::*)()const, &C::c1>::value)() == 10, "oops");
>
> ice.cpp:72:56: error: expression ā€˜0u’ does not designate a constexpr
> function
> static_assert((c.*W_<int(C::*)()const, &C::c1>::value)() == 10, "oops");
>
> note the '0u'! (the error message comes from the beginning of
> cxx_eval_call_expression) I guess these issues should not require major
> surgeries if a testcase like the latter but using, instead of W_:
>
> template <typename T, T V>
> struct W { static constexpr T value() { return V; } };
>
> works fine. In this case too, if I follow the long chain of cxx_eval_* I see
> a lot of NOP_EXPRs, but I'm not sure it's all there is to the issue, maybe
> we are just doing something wrong with the pointers...
>
> Thanks for any comment!
> Paolo.
>
>
>
>

Reply via email to