On Sun, Sep 4, 2016 at 11:30 PM, Tom de Vries <tom_devr...@mentor.com> wrote:
> On 04/09/16 16:08, Richard Biener wrote:
>>
>> On September 4, 2016 12:33:02 PM GMT+02:00, Tom de Vries
>> <tom_devr...@mentor.com> wrote:
>>>
>>> On 04/09/16 08:12, Richard Biener wrote:
>>>>
>>>> On September 3, 2016 5:23:35 PM GMT+02:00, Tom de Vries
>>>
>>> <tom_devr...@mentor.com> wrote:
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> this patch fixes a c++ ICE, a p1 6/7 regression.
>>>>>>
>>>>>>
>>>>>> Consider test.C:
>>>>>> ...
>>>>>> void bar (__builtin_va_list &);
>>>>>>
>>>>>> struct c
>>>>>> {
>>>>>>   operator const __builtin_va_list &();
>>>>>>   operator __builtin_va_list &();
>>>>>> };
>>>>>>
>>>>>> void
>>>>>> foo (void) {
>>>>>>   struct c c1;
>>>>>>
>>>>>>   bar (c1);
>>>>>> }
>>>>>> ...
>>>>>>
>>>>>> The compiler ICEs as follows:
>>>>>> ...
>>>>>> test.C: In function ‘void foo()’:
>>>>>> test.C:13:10: internal compiler error: canonical types differ for
>>>>>> identical types __va_list_tag [1] and __va_list_tag [1]
>>>>>>    bar (c1);
>>>>>>           ^
>>>>>> comptypes(tree_node*, tree_node*, int)
>>>>>>         src/gcc/cp/typeck.c:1430
>>>>>> reference_related_p(tree_node*, tree_node*)
>>>>>>         src/gcc/cp/call.c:1415
>>>>>> reference_binding
>>>>>>         src/gcc/cp/call.c:1559
>>>>>> implicit_conversion
>>>>>>         src/gcc/cp/call.c:1805
>>>>>> build_user_type_conversion_1
>>>>>>         src/gcc/cp/call.c:3776
>>>>>> reference_binding
>>>>>>         src/gcc/cp/call.c:1664
>>>>>> implicit_conversion
>>>>>>         src/gcc/cp/call.c:1805
>>>>>> add_function_candidate
>>>>>>         src/gcc/cp/call.c:2141
>>>>>> add_candidates
>>>>>>         src/gcc/cp/call.c:5394
>>>>>> perform_overload_resolution
>>>>>>         src/gcc/cp/call.c:4066
>>>>>> build_new_function_call(tree_node*, vec<tree_node*, va_gc,
>>>
>>> vl_embed>**,
>>>>>>
>>>>>>   bool, int)
>>>>>>         src/gcc/cp/call.c:4143
>>>>>> finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**,
>>>
>>> bool,
>>>>>>
>>>>>>   bool, int)
>>>>>>         src/gcc/cp/semantics.c:2440
>>>>>> ...
>>>>>>
>>>>>> The regression is caused by the commit for PR70955, that adds a
>>>>>> "sysv_abi va_list" attribute to the struct in the va_list type
>>>
>>> (which
>>>>>>
>>>>>> is
>>>>>> an array of one of struct).
>>>>>>
>>>>>> The ICE in comptypes happens as follows: we're comparing two
>>>
>>> versions
>>>>>>
>>>>>> of
>>>>>> va_list type (with identical array element type), each with the
>>>>>> canonical type set to themselves. Since the types are considered
>>>>>> identical, they're supposed to have identical canonical types,
>>>
>>> which is
>>>
>>>> Did you figure out why they are not assigned the same canonical type?
>>>
>>>
>>> When constructing the first type in ix86_build_builtin_va_list_64, it's
>>>
>>> cached.
>>>
>>> When constructing the second type in build_array_type_1 (with call
>>> stack: grokdeclarator -> cp_build_qualified_type_real ->
>>> build_cplus_array_type -> build_cplus_array_type -> build_array_type ->
>>>
>>> build_array_type_1), we call type_hash_canon.
>>>
>>> But the cached type has name __builtin_sysv_va_list, and the new type
>>> has no name, so we hit the clause 'TYPE_NAME (a->type) != TYPE_NAME
>>> (b->type)' in type_cache_hasher::equal.
>>>
>>> Consequently, TYPE_CANONICAL for the new type remain set to self.
>>
>>
>> But how did it then work before the patch causing this?
>
>
> Before the patch that introduced the attribute, rather than assigning the
> result of ix86_build_builtin_va_list_64 directly sysv_va_list_type_node, an
> intermediate build_variant_type_copy was used.
>
> This had as consequence that the copy was named and not added to the cache,
> and that the original in the type cache remained unnamed.
>
> Adding the build_variant_type_copy back fixes the ICE. But I'm not sure if
> that's a correct fix. The copy would have it's canonical type set to the
> original type. But if we'd search for the canonical type of the copy in the
> type cache, we wouldn't find it.

Huh.  Can't see how making a copy would affect the type cache -- AFAIK nothing
adds the record to the type hash.  The array type is there (and the
FEs have some
"interesting" code regarding qualifiers on arrays).  Btw,

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 4531647..4e00dee 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10550,9 +10550,13 @@ ix86_build_builtin_va_list_64 (void)

   TYPE_ATTRIBUTES (record) = tree_cons (get_identifier ("sysv_abi va_list"),
                                        NULL_TREE, TYPE_ATTRIBUTES (record));
+  SET_TYPE_STRUCTURAL_EQUALITY (record);


This should be enough

   /* The correct type is an array type of one element.  */
-  return build_array_type (record, build_index_type (size_zero_node));
+  tree res = build_array_type (record, build_index_type (size_zero_node));
+  SET_TYPE_STRUCTURAL_EQUALITY (res);
+

and this should be done automagically by build_array_type.

I'm fine with that part but the cp/tree.c part looks very generic, excluding
all records from handling.

Richard.

+  return res;
 }


> Thanks,
> - Tom
>

Reply via email to