On Tue, Oct 31, 2017 at 5:09 PM, David Malcolm <[email protected]> wrote:
> On Tue, 2017-10-24 at 09:53 -0400, Jason Merrill wrote:
>> On Fri, Oct 20, 2017 at 5:53 PM, David Malcolm <[email protected]>
>> wrote:
>> > Design questions:
>> >
>> > * The patch introduces a new kind of tree node, currently called
>> > DECL_WRAPPER_EXPR (although it's used for wrapping constants as
>> > well
>> > as decls). Should wrappers be a new kind of tree node, or should
>> > they
>> > reuse an existing TREE_CODE? (e.g. NOP_EXPR, CONVERT_EXPR, etc).
>> > * NOP_EXPR: seems to be for use as an rvalue
>> > * CONVERT_EXPR: for type conversions
>> > * NON_LVALUE_EXPR: "Value is same as argument, but guaranteed
>> > not an
>> > lvalue"
>> > * but we *do* want to support lvalues here
>>
>> I think using NON_LVALUE_EXPR for constants would be appropriate.
>>
>> > * VIEW_CONVERT_EXPR: viewing one thing as of a different type
>> > * can it support lvalues?
>>
>> Yes, the purpose of VIEW_CONVERT_EXPR is to support lvalues, it seems
>> like the right choice.
>>
>> Jason
>
> Thanks. I've been working on a new version of the patch using those
> tree codes, but have run into an issue.
>
> In g++.dg/conversion/reinterpret1.C:
>
> // PR c++/15076
>
> struct Y { Y(int &); };
>
> int v;
> Y y1(reinterpret_cast<int>(v)); // { dg-error "" }
>
> With trunk, this successfully generates an error:
>
> reinterpret1.C:6:6: error: cannot bind non-const lvalue reference of type
> ‘int&’ to an rvalue of type ‘int’
> Y y1(reinterpret_cast<int>(v)); // { dg-error "" }
> ^~~~~~~~~~~~~~~~~~~~~~~~
> reinterpret1.C:3:12: note: initializing argument 1 of ‘Y::Y(int&)’
> struct Y { Y(int &); };
> ^
>
> where internally there's a NON_LVALUE_EXPR around a VAR_DECL, where
> both have the same type:
>
> (gdb) call debug_tree (expr)
> <non_lvalue_expr 0x7ffff145f6e0
> type <integer_type 0x7ffff132e5e8 int public type_6 SI
> size <integer_cst 0x7ffff1331120 constant 32>
> unit-size <integer_cst 0x7ffff1331138 constant 4>
> align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
> 0x7ffff132e5e8 precision:32 min <integer_cst 0x7ffff13310d8 -2147483648> max
> <integer_cst 0x7ffff13310f0 2147483647>
> pointer_to_this <pointer_type 0x7ffff1336a80> reference_to_this
> <reference_type 0x7ffff144ca80>>
>
> arg:0 <var_decl 0x7ffff7ffbd80 v type <integer_type 0x7ffff132e5e8 int>
> used public static tree_1 read SI
> /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:5:5
> size <integer_cst 0x7ffff1331120 32> unit-size <integer_cst 0x7ffff1331138 4>
> align:32 warn_if_not_align:0 context <translation_unit_decl
> 0x7ffff131e168
> /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> chain <type_decl 0x7ffff141a720 Y type <record_type 0x7ffff144c150 Y>
> public decl_2 VOID
> /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:3:8
> align:8 warn_if_not_align:0 context <translation_unit_decl
> 0x7ffff131e168
> /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> chain <function_decl 0x7ffff144f800 __cxa_call_unexpected>>>
>
> /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6
> start:
> /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6
> finish:
> /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:29>
>
> The problem is that this reinterpret cast "looks" just like one of my
> location wrappers.
Your code shouldn't strip a NON_LVALUE_EXPR around a VAR_DECL.
> I see a similar issue with constants, where with:
>
> struct Y { Y(int &); };
> Y y1(reinterpret_cast<int>(42));
>
> trunk generates an error like the above, but my code handles the
> NON_LVALUE_EXPR<int>(INTEGER_CST<int>(42))
> as if it were a location wrapper around the INTEGER_CST, and thus
> doesn't emit the error.
Why doesn't it emit the error? We should get the same error whether
or not we strip the wrapper.
Jason