Bug 57509 - Segmentation fault when using __builtin_shuffle in templated class.
Summary: Segmentation fault when using __builtin_shuffle in templated class.
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.1
: P3 normal
Target Milestone: 4.9.0
Assignee: Marc Glisse
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-06-03 11:26 UTC by Maciej Pendolski
Modified: 2013-06-27 21:31 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-06-08 00:00:00


Attachments
Untested patch (3.00 KB, patch)
2013-06-08 21:41 UTC, Marc Glisse
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Maciej Pendolski 2013-06-03 11:26:09 UTC
Ubuntu 12.10 64-bit


GCC 4.8.1 which I built from source:
COLLECT_GCC=/opt/custom/gcc-4.8.1/bin/gcc
COLLECT_LTO_WRAPPER=/opt/custom/gcc-4.8.1/libexec/gcc/x86_64-unknown-linux-gnu/4.8.1/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-4.8.1/configure --prefix=/opt/custom/gcc-4.8.1 --enable-languages=c,c++
Thread model: posix
gcc version 4.8.1 (GCC) 


/opt/custom/gcc-4.8.1/bin/gcc test.cpp
test.cpp: In static member function ‘static int_v4<Tp>::Tpv int_v4<Tp>::shuffle(const int_v4<Tp>&, const int_v4<Tp>&, const int_v4<Tp>&)’:
test.cpp:8:49: internal compiler error: Segmentation fault
         return __builtin_shuffle(u1.v, u2.v, s.v);
                                                 ^
0x8d7dff crash_signal
	../../gcc-4.8.1/gcc/toplev.c:332
0x632761 c_build_vec_perm_expr(unsigned int, tree_node*, tree_node*, tree_node*)
	../../gcc-4.8.1/gcc/c-family/c-common.c:2280
0x5965f3 cp_parser_postfix_expression
	../../gcc-4.8.1/gcc/cp/parser.c:5558
0x5983bd cp_parser_unary_expression
	../../gcc-4.8.1/gcc/cp/parser.c:6729
0x598eef cp_parser_binary_expression
	../../gcc-4.8.1/gcc/cp/parser.c:7421
0x59939f cp_parser_assignment_expression
	../../gcc-4.8.1/gcc/cp/parser.c:7657
0x59af93 cp_parser_expression
	../../gcc-4.8.1/gcc/cp/parser.c:7819
0x5932ce cp_parser_expression
	../../gcc-4.8.1/gcc/cp/parser.c:7858
0x5932ce cp_parser_jump_statement
	../../gcc-4.8.1/gcc/cp/parser.c:10144
0x5932ce cp_parser_statement
	../../gcc-4.8.1/gcc/cp/parser.c:8874
0x593a8e cp_parser_statement_seq_opt
	../../gcc-4.8.1/gcc/cp/parser.c:9238
0x593bae cp_parser_compound_statement
	../../gcc-4.8.1/gcc/cp/parser.c:9192
0x5a1d28 cp_parser_function_body
	../../gcc-4.8.1/gcc/cp/parser.c:17827
0x5a1d28 cp_parser_ctor_initializer_opt_and_function_body
	../../gcc-4.8.1/gcc/cp/parser.c:17863
0x5a2a5f cp_parser_function_definition_after_declarator
	../../gcc-4.8.1/gcc/cp/parser.c:21843
0x58de44 cp_parser_late_parsing_for_member
	../../gcc-4.8.1/gcc/cp/parser.c:22484
0x58de44 cp_parser_class_specifier_1
	../../gcc-4.8.1/gcc/cp/parser.c:18586
0x58de44 cp_parser_class_specifier
	../../gcc-4.8.1/gcc/cp/parser.c:18610
0x58de44 cp_parser_type_specifier
	../../gcc-4.8.1/gcc/cp/parser.c:13677
0x5a0711 cp_parser_decl_specifier_seq
	../../gcc-4.8.1/gcc/cp/parser.c:11003
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.


--------- test.cpp ---------
template <typename Tp>
class int_v4
{
    typedef Tp Tpv __attribute__((vector_size(4 * sizeof(Tp))));
    Tpv v;

    static Tpv shuffle(const int_v4& u1, const int_v4& u2, const int_v4& s) {
        return __builtin_shuffle(u1.v, u2.v, s.v); //segfault
    }

    Tpv shuffle2(const int_v4& u1, const int_v4& u2, const int_v4& s) {
        return __builtin_shuffle(v, v, v); //error if shuffle() is removed
    }
};

int main()
{
    int_v4<int> iv4;
    int_v4<unsigned int> uv4;
    return 0;
}

-----------

If: 

    typedef int Tp;

is added at the top and the lines with template stuff are removed then it compiles just fine but with the use of templates there is a segfault in shuffle() and if shuffle() is removed then there is: 

    "error: __builtin_shuffle last argument must be an integer vector" 

in shuffle2(). When compiling with GCC 4.7.2 (which is shipping with Ubuntu 12.10) then everything compiles, even if the line:
 
    int_v4<float> fv4; 

is added to main() (meaning that it was possible to pass non-integer vector as the last argument of __builtin_shuffle in GCC 4.7.2).

I'm guessing that the bug is somehow related to the presence/addition of error handling code. It looks like (I am not a GCC developer) GCC is trying to determine the type of the last argument before any variables using the template are even defined (they can be removed and the error message will still be there).
Comment 1 Paolo Carlini 2013-06-05 18:29:36 UTC
Maybe Marc is interested in this.
Comment 2 Marc Glisse 2013-06-08 19:44:06 UTC
(In reply to Paolo Carlini from comment #1)
> Maybe Marc is interested in this.

ChangeLog says this is probably my fault...

c_build_vec_perm_expr is missing some code like we can find in build_x_unary_op for instance:

  if (processing_template_decl)
    {
      if (type_dependent_expression_p (xarg))
        return build_min_nt_loc (loc, code, xarg, NULL_TREE);

      xarg = build_non_dependent_expr (xarg);
    }

RID_BUILTIN_SHUFFLE is handled very early in parser.c which directly calls c_build_vec_perm_expr. I guess we could use build_min_nt(VEC_PERM_EXPR,...) to store the template version, and make sure that c_build_vec_perm_expr is called once the types are instantiated (in tsubst_copy(_and_build)?).
Comment 3 Paolo Carlini 2013-06-08 21:29:30 UTC
Thanks Marc. Please take your own plan very seriously! ;)
Comment 4 Marc Glisse 2013-06-08 21:41:28 UTC
Created attachment 30281 [details]
Untested patch

There are quite a few issues with the c++ version...
Comment 5 Paolo Carlini 2013-06-09 09:04:51 UTC
Detail: normally we just pass around tsubst_flags_ts, no complain & tf_error to bool, etc.
Comment 6 Marc Glisse 2013-06-09 09:14:51 UTC
(In reply to Paolo Carlini from comment #5)
> Detail: normally we just pass around tsubst_flags_ts, no complain & tf_error
> to bool, etc.

Those flags are not available in c-family, this is not the first place where we pass a bool in this case.
Comment 7 Paolo Carlini 2013-06-09 11:29:42 UTC
I see, I never fiddled with those.
Comment 8 Marc Glisse 2013-06-13 19:43:50 UTC
Patch posted:
http://gcc.gnu.org/ml/gcc-patches/2013-06/msg00470.html
Comment 9 Marc Glisse 2013-06-27 21:31:39 UTC
r200495 | glisse | 2013-06-27 23:29:22 +0200 (Thu, 27 Jun 2013) | 20 lines

2013-06-27  Marc Glisse  <marc.glisse@inria.fr>

        PR c++/57509

gcc/c-family/
        * c-common.h (c_build_vec_perm_expr): New complain argument.
        * c-common.c (c_build_vec_perm_expr): Likewise.
        Use save_expr also in C++.

gcc/cp/
        * typeck.c (cp_build_vec_perm_expr): New function.
        * cp-tree.h: Declare it.
        * parser.c (cp_parser_postfix_expression): Call it.
        * pt.c (tsubst_copy): Handle VEC_PERM_EXPR.
        (tsubst_copy_and_build): Likewise.

gcc/testsuite/
        * g++.dg/ext/pr57509.C: New file.