User account creation filtered due to spam.

Bug 46003 - cond5.C fails for ARM EABI tests.
Summary: cond5.C fails for ARM EABI tests.
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: 4.6.1
Assignee: Yufeng Zhang
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2010-10-13 11:47 UTC by Ramana Radhakrishnan
Modified: 2012-12-11 17:52 UTC (History)
4 users (show)

See Also:
Host: x86_64-unknown-linux-gnu
Target: arm-eabi
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-12-03 09:32:03


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ramana Radhakrishnan 2010-10-13 11:47:32 UTC
The test cond5.C fails for testing with arm-eabi in the following manner. 

 
/arm/scratch/pdtltest/work/sandboxes/fsf/trunk/source/gcc-fsf/gcc/testsuite/g++.dg/template/cond5.C: In function 'void foo(const A&)':
/arm/scratch/pdtltest/work/sandboxes/fsf/trunk/source/gcc-fsf/gcc/testsuite/g++.dg/template/cond5.C:9:55: internal compiler error: in build_target_expr, at cp/tree.c:287
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.


The compiler was configured with the following options:

 --with-cpu=cortex-a9 --with-float=softfp --with-fpu=neon
Comment 1 Ramana Radhakrishnan 2010-12-03 09:32:03 UTC
Even something as simple as this brings the compiler down. 

struct A
{
  A(int);
  operator void*() const;
};

template<int> void foo(const A& x) 
{ 0 ? x : 0; }


Here's a backtrace from gdb if that helps. 

0  fancy_abort (file=0xe5e0ed "../../combined/gcc/cp/tree.c", line=287, function=0xe60260 "build_target_expr") at ../../combined/gcc/diagnostic.c:892
#1  0x00000000005e7c68 in build_target_expr (decl=0x2ac80b326280, value=0x2ac80b42f678) at ../../combined/gcc/cp/tree.c:284
#2  0x00000000005eceeb in build_cplus_new (type=0x2ac80b43ff18, init=<value optimized out>) at ../../combined/gcc/cp/tree.c:450
#3  0x000000000049c742 in convert_like_real (convs=0x70ca550, expr=0x2ac80b42f678, fn=0x0, argnum=0, inner=<value optimized out>, issue_conversion_warnings=<value optimized out>, c_cast_p=0 '\0', complain=3) at ../../combined/gcc/cp/call.c:5300
#4  0x000000000049e0c9 in build_conditional_expr (arg1=0x2ac80b3128d0, arg2=0x2ac80b3128a0, arg3=0x2ac80b302f50, complain=3) at ../../combined/gcc/cp/call.c:3965
#5  0x000000000058a840 in build_x_conditional_expr (ifexp=0x2ac80b302f50, op1=0x2ac80b3128a0, op2=0xe60260, complain=3) at ../../combined/gcc/cp/typeck.c:5478
#6  0x000000000056d43e in cp_parser_assignment_expression (parser=0x2ac80b44d000, cast_p=<value optimized out>, pidk=0x0) at ../../combined/gcc/cp/parser.c:6972
#7  0x000000000056d6b0 in cp_parser_expression (parser=0xe5e0ed, cast_p=<value optimized out>, pidk=0xe60260) at ../../combined/gcc/cp/parser.c:7149
#8  0x000000000056da50 in cp_parser_expression_statement (parser=0x2ac80b44d000, in_statement_expr=0x0) at ../../combined/gcc/cp/parser.c:8264
#9  0x000000000057a496 in cp_parser_statement (parser=0x2ac80b44d000, in_statement_expr=0x0, in_compound=1 '\001', if_p=0x0) at ../../combined/gcc/cp/parser.c:8129
#10 0x000000000057b4d6 in cp_parser_statement_seq_opt (parser=0x2ac80b44d000, in_statement_expr=0x0) at ../../combined/gcc/cp/parser.c:8378
#11 0x000000000057b614 in cp_parser_compound_statement (parser=0x2ac80b44d000, in_statement_expr=0x0, in_try=<value optimized out>) at ../../combined/gcc/cp/parser.c:8332
#12 0x000000000057d8de in cp_parser_ctor_initializer_opt_and_function_body (parser=0x2ac80b44d000) at ../../combined/gcc/cp/parser.c:16319
#13 0x000000000057dc17 in cp_parser_function_definition_after_declarator (parser=0x2ac80b44d000, inline_p=0 '\0') at ../../combined/gcc/cp/parser.c:19747
#14 0x000000000057eb6c in cp_parser_init_declarator (parser=0x2ac80b44d000, decl_specifiers=0x7fff9f7fc170, checks=0x0, function_definition_allowed_p=1 '\001', member_p=0 '\0', declares_class_or_enum=<value optimized out>, function_definition_p=0x7fff9f7fc1df "\001") at ../../combined/gcc/cp/parser.c:19677
#15 0x000000000057eebb in cp_parser_single_declaration (parser=0x2ac80b44d000, checks=0x0, member_p=0 '\0', explicit_specialization_p=0 '\0', friend_p=0x7fff9f7fc247 "") at ../../combined/gcc/cp/parser.c:20002
#16 0x000000000057f0cb in cp_parser_template_declaration_after_export (parser=0x2ac80b44d000, member_p=96 '`') at ../../combined/gcc/cp/parser.c:19852
#17 0x00000000005840e2 in cp_parser_declaration (parser=0x2ac80b44d000) at ../../combined/gcc/cp/parser.c:9415
#18 0x0000000000582405 in cp_parser_declaration_seq_opt (parser=0x2ac80b44d000) at ../../combined/gcc/cp/parser.c:9337
#19 0x000000000058271b in c_parse_file () at ../../combined/gcc/cp/parser.c:3454
#20 0x000000000065ceed in c_common_parse_file () at ../../combined/gcc/c-family/c-opts.c:1071
#21 0x0000000000940017 in toplev_main (argc=3, argv=0x7fff9f7fc4a8) at ../../combined/gcc/toplev.c:579
#22 0x000000350401d974 in __libc_start_main () from /lib64/libc.so.6
#23 0x000000000048a669 in _start ()
Comment 2 Yufeng Zhang 2011-01-25 21:27:32 UTC
Add me to CC list.
Comment 3 Yufeng Zhang 2011-02-10 17:36:12 UTC
The repro can be reduced to:

------------ CODE ------------
struct A
{
  A(int);
};

template<int> void foo(A& x) 
{ 0 ? x : 0; }

------------ CUT ------------

The assertion failure occurs in cp/tree.c:build_target_expr(tree decl, tree value), which is expecting the TREE_TYPE of the VALUE to meet one of the following conditions:

1. is VOID_TYPE
2. is the same as the type of the DECL, which is to be initialized with the VALUE
3. passes useless_type_conversion_p()

The assertions fails when the TREE_TYPE of the VALUE is found to be POINTER_TYPE, while the DECL has VOID_TYPE.

Note that the assertion does not fail in the x86-targeted (or any of many other targets targeted) compiler, because of the difference in the ARM C++ ABI on constructor return values. The ARM C++ ABI requires C1 and C2 constructors to return this (instead of being void functions).

During the parsing of an conditional expression, the C++ front-end needs to determine the expression type, especially when the 2nd and 3rd operands are of different types. For 0 ? x : 0 in the repro code, it seems that ctors (constructors) of A (including the user defined ctor and the compiler generated copy ctor) are invoked to convert the type of the 3rd operand from INTEGER_TYPE to the RECORD_TYPE of A. This is part of the process in order to match the type of the 3rd operand to that of the 2nd one.

When the assertion happens, the VALUE is the following like tree node:

  CALL_EXPR (pointer_type to struct A)
    COMPONENT_REF  (pointer_type to method_type of a method in A)
      INDIRECT_REF (record_type of A)
        INTEGER_CST 0 (pointer_type to A)
        BASELINK
          OVERLOAD
            A* A::A(const A&)
            A* A::A(int)
    TARGET_EXPR (record_type of A)
      VAR_DECL
      AGGR_INIT_EXPR (void_type)
        op0: (A*)0
        op1: (int)0
        func: ADDR_EXPR (method_type)
                FUNCTION_DECL __comp_ctor A* A::A(int)

Basically what the tree is doing is:

  ((A)0).A((A*)0->A(0))

i.e. construct a temporary object of A by explicitly calling the user-defined ctor, and pass it to the copy ctor of A to construct another temporary object of A, but this time replying on the overload resolution to get the copy ctor selected.

Leave aside the kids nodes of the CALL_EXPR tree node, and focus on its TREE_TYPE, which is the return type of the routine to be called. Because the routine is a ctor and the compiler targets ARM, it has the TREE_TYPE of POINTER_TYPE (conforming to the ABI). When the CALL_EXPR tree node is passed to build_target_expr as the VALUE to initialize the DECL, which sensibly has the type of RECORD_TYPE (of A), the compiler complains: mismatching types!! You cannot use a tree node of POINTER_TYPE to initialize a RECORD_TYPE tree node!

In x86-targeted GCC, however, such a CALL_EXPR tree node has VOID_TYPE as a ctor returns void as specified by the generic C++ ABI, and thus the assertion failure will not happen.
Comment 4 Janis Johnson 2011-05-26 01:19:47 UTC
Test g++.dg/template/cond5.C started failing for arm-none-linux-gnueabi with this patch:

r132158 | aoliva | 2008-02-06 20:31:43 +0000 (Wed, 06 Feb 2008) | 10 lines

gcc/cp/ChangeLog:
PR c++/35056
* tree.c: Include tree-flow.h.
(build_target_expr): Check type compatibility.
* Make-lang.in (cp/tree.o): Depend on $(TREE_FLOW_H).
* call.c (convert_like_real): Convert bitfield to expected type.
gcc/testsuite/ChangeLog:
PR c++/35056
* g++.dg/conversion/bitfield8.C: New.
Comment 5 Yufeng Zhang 2011-06-03 10:48:29 UTC
(In reply to comment #4)
> Test g++.dg/template/cond5.C started failing for arm-none-linux-gnueabi with
> this patch:
> 
> r132158 | aoliva | 2008-02-06 20:31:43 +0000 (Wed, 06 Feb 2008) | 10 lines
> 
> gcc/cp/ChangeLog:
> PR c++/35056
> * tree.c: Include tree-flow.h.
> (build_target_expr): Check type compatibility.

The type checking introduced by this commit to build_target_expr is indeed where the ICE occurs, i.e. the assertion failure. The added type-checking exposes the problem.

Jason Merrill has suggested updating build_conditional_expr to "have a template case that just determines the appropriate type and then builds up a COND_EXPR with that type from the unconverted operands, like we do for calls in finish_call_expr" (http://gcc.gnu.org/ml/gcc-patches/2011-03/msg00164.html)

I've been distracted by other work, but will come back to this very soon.
Comment 6 Dodji Seketeli 2011-06-08 10:42:09 UTC
Shouldn't this be fixed by the commit of  PR c++/49134 ?
Comment 7 Janis Johnson 2011-06-08 15:49:02 UTC
Test g++.dg/template/cond5.C starts passing for arm-none-linux-gnueabi with r174682, the fix for PR49134 mentioned in comment 6.
Comment 8 Yufeng Zhang 2011-06-09 17:15:14 UTC
(In reply to comment #6)
> Shouldn't this be fixed by the commit of  PR c++/49134 ?

(In reply to comment #7)
> Test g++.dg/template/cond5.C starts passing for arm-none-linux-gnueabi with
> r174682, the fix for PR49134 mentioned in comment 6.

Thanks for pointing out the related bug fix. The test case g++.dg/template/cond5.C indeed starts 'passing' now, as the fix for PR c++/49134 has essentially loosened the same checking where assertion had blown up. I'll spend some more time looking into the underlying issue and put more information here later. If it turns out to be necessary, I'll close this bugzilla and open a new one for it.
Comment 9 Ramana Radhakrishnan 2012-12-11 17:52:41 UTC
Assuming fixed - if there is a problem a new PR can be filed.