Patchwork [C++,Patch/RFC] PR 52282

login
register
mail settings
Submitter Paolo Carlini
Date May 1, 2013, 7:47 p.m.
Message ID <5181713C.8040507@oracle.com>
Download mbox | patch
Permalink /patch/240806/
State New
Headers show

Comments

Paolo Carlini - May 1, 2013, 7:47 p.m.
Hi,

with the recent fix for c++/57092, we don't ICE anymore on the various 
testcases part of c++/52282, but we still have problems. An issue I can 
see - maybe we already discussed it a bit in the past - is that of 
NOP_EXPRs which I don't fully understand: anyway, with the attached 
patchlet, the original testcase passes and adding the STRIP_NOPS seems 
to me rather natural in the light of many other existing uses right 
before handling ADDR_EXPRs. The patchlet passes testing and helps a lot 
for c++/52892 too (all the first testcases pass besides the last one, 
which however appears to point to a rather unrelated issue, at least 
judging by the error message). Does the additional STRIP_NOPS make sense 
to you?

Then, to the second, big testcase attached to c++/52282: with the 
STRIP_NOPS in place, we make good progress on it, but we still have 
errors for the following 4 tests which don't seem just matter of easy to 
strip NOPs:

static_assert((c.*W_<int(C::*)()const, &C::c1>::value)() == 10, "oops"); 
// incorrect evaluation
static_assert((c.*X_<int(C::*)()const, &C::c1>::value)() == 10, "oops"); 
// incorrect evaluation
static_assert((c.*Y_<int(C::*)()const, &C::c1>::value)() == 10, "oops"); 
// incorrect evaluation
static_assert((c.*Z_<int(C::*)()const, &C::c1>::value)() == 10, "oops"); 
// incorrect evaluation

For the first one, for example, we have:

52282_1.C:65:1: error: non-constant condition for static assertion
static_assert((c.*W_<int(C::*)()const, &C::c1>::value)() == 10, "oops"); 
// incorrect evaluation
^
52282_1.C:65:56: error: expression ā€˜0uā€™ does not designate a constexpr 
function
static_assert((c.*W_<int(C::*)()const, &C::c1>::value)() == 10, "oops"); 
// incorrect evaluation
^
Note the bizarre '0u', which characterizes all the remaining failures.

I'm also adding below the condition tree for the failure above, with the 
EQ_EXPR which is remaining unfolded. Please help ;)

Thanks!
Paolo.

//////////////////

<eq_expr 0x7ffff68bdeb0
type <boolean_type 0x7ffff6730b28 bool public unsigned QI
size <integer_cst 0x7ffff6715f80 constant 8>
unit size <integer_cst 0x7ffff6715fa0 constant 1>
align 8 symtab 0 alias set -1 canonical type 0x7ffff6730b28 precision 1 
min <integer_cst 0x7ffff6733340 0> max <integer_cst 0x7ffff6733380 1>>
side-effects
arg 0 <call_expr 0x7ffff68b6150
type <integer_type 0x7ffff67305e8 int public type_6 SI
size <integer_cst 0x7ffff6733140 constant 32>
unit size <integer_cst 0x7ffff6733160 constant 4>
align 32 symtab 0 alias set -1 canonical type 0x7ffff67305e8 precision 
32 min <integer_cst 0x7ffff67330e0 -2147483648> max <integer_cst 
0x7ffff6733100 2147483647>
pointer_to_this <pointer_type 0x7ffff67382a0>>
side-effects
fn <nop_expr 0x7ffff68c00c0 type <pointer_type 0x7ffff68b7000>

arg 0 <component_ref 0x7ffff68b2780 type <pointer_type 0x7ffff68bf2a0>
arg 0 <var_decl 0x7ffff68aeb48 value> arg 1 <field_decl 0x7ffff68aec78 
__pfn>
52282_1.C:65:56>>
arg 0 <pointer_plus_expr 0x7ffff68bde88 type <pointer_type 0x7ffff68b0690>

arg 0 <addr_expr 0x7ffff68c0020 type <pointer_type 0x7ffff68b0690>
readonly constant arg 0 <var_decl 0x7ffff68ae2f8 c>>
arg 1 <nop_expr 0x7ffff68c0080 type <integer_type 0x7ffff6730000 sizetype>

arg 0 <component_ref 0x7ffff68b27b0 type <integer_type 0x7ffff68bf498 
long int>
arg 0 <var_decl 0x7ffff68aeb48 value> arg 1 <field_decl 0x7ffff68aed10 
__delta>
52282_1.C:65:56>>>
52282_1.C:65:56>
arg 1 <integer_cst 0x7ffff686f7c0 type <integer_type 0x7ffff67305e8 int> 
constant 10>
52282_1.C:65:58>

Patch

Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 198488)
+++ cp/semantics.c	(working copy)
@@ -6754,6 +6754,7 @@  cxx_eval_call_expression (const constexpr_call *ol
       /* Might be a constexpr function pointer.  */
       fun = cxx_eval_constant_expression (old_call, fun, allow_non_constant,
 					  /*addr*/false, non_constant_p, overflow_p);
+      STRIP_NOPS (fun);
       if (TREE_CODE (fun) == ADDR_EXPR)
 	fun = TREE_OPERAND (fun, 0);
     }
Index: testsuite/g++.dg/cpp0x/constexpr-52282.C
===================================================================
--- testsuite/g++.dg/cpp0x/constexpr-52282.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/constexpr-52282.C	(working copy)
@@ -0,0 +1,29 @@ 
+// PR c++/52282
+// { dg-do compile { target c++11 } }
+
+template <typename T, T V>
+struct A
+    {
+    static constexpr T a() { return V; }
+    };
+template <typename T, T V>
+struct B
+    {
+    typedef T type;
+    static constexpr type b() { return V; }
+    };
+template <typename T, T V>
+struct C
+    {
+    static constexpr decltype(V) c() { return V; }
+    };
+static_assert(A<int, 10>::a() == 10, "oops");
+static_assert(B<int, 10>::b() == 10, "oops");
+static_assert(C<int, 10>::c() == 10, "oops");
+struct D
+    {
+    static constexpr int d() { return 10; }
+    };
+static_assert((A<int(*)(), &D::d>::a())() == 10, "oops");
+static_assert((B<int(*)(), &D::d>::b())() == 10, "oops"); // error
+static_assert((C<int(*)(), &D::d>::c())() == 10, "oops");