Bug 65071 - ICE on valid, sizeof...() of template template parameter pack in return type
Summary: ICE on valid, sizeof...() of template template parameter pack in return type
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 5.0
: P3 normal
Target Milestone: 6.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-02-15 15:05 UTC by Mikhail Maltsev
Modified: 2015-07-14 22:38 UTC (History)
0 users

See Also:
Host: x86_64-unknown-linux-gnu
Target: x86_64-unknown-linux-gnu
Build: x86_64-unknown-linux-gnu
Known to work:
Known to fail: 4.8.2, 4.9.2, 5.0
Last reconfirmed: 2015-03-16 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mikhail Maltsev 2015-02-15 15:05:05 UTC
The following (presumably valid) code causes segfault on trunk r220715 and 4.9.2:

$ cat ./ice_sizeof.cc
template<int N>
struct array
{
    int data[N];
};

template<template<typename> class... T1, typename T2>
array<sizeof...(T1)> make_array(T1<T2> ...init)
{
    return { 0 };
}

template<typename T>
struct S
{
    T a;
};

auto arr = make_array(S<int>{1});

======================================================

miyuki@gcc-devel2:~/gcc/test/ice_sizeof$ ../../obj/gcc/cc1plus -std=c++11 ice_sizeof.cc &> bug_report.txt; cat bug_report.txt
 array<sizeof... (T1)> make_array(T1<T2>...) array<sizeof... (T1)> make_array(T1<T2>...) [with T1 = {S}; T2 = int] void __static_initialization_and_destruction_0(int, int) void _GLOBAL__sub_I_arr()
Analyzing compilation unit

ice_sizeof.cc: In instantiation of 'array<sizeof... (T1)> make_array(T1<T2>...) [with T1 = {S}; T2 = int]':

ice_sizeof.cc:8:22: internal compiler error: tree check: expected class 'type', have 'declaration' (template_decl) in write_CV_qualifiers_for_type, at cp/mangle.c:2154
 array<sizeof...(T1)> make_array(T1<T2> ...init)
                      ^
0xefd737 tree_class_check_failed(tree_node const*, tree_code_class, char const*, int, char const*)
        /home/miyuki/gcc/src/gcc/tree.c:9341
0x7c9e9b tree_class_check(tree_node*, tree_code_class, char const*, int, char const*)
        /home/miyuki/gcc/src/gcc/tree.h:2969
0x7c9e9b write_CV_qualifiers_for_type
        /home/miyuki/gcc/src/gcc/cp/mangle.c:2154
0x7d03b3 write_type
        /home/miyuki/gcc/src/gcc/cp/mangle.c:1876
0x7d07e1 write_type
        /home/miyuki/gcc/src/gcc/cp/mangle.c:2049
0x7cf5b8 write_template_arg
        /home/miyuki/gcc/src/gcc/cp/mangle.c:3158
0x7cfcb8 write_template_args
        /home/miyuki/gcc/src/gcc/cp/mangle.c:2546
0x7ced2a write_name
        /home/miyuki/gcc/src/gcc/cp/mangle.c:831
0x7d09e6 write_class_enum_type
        /home/miyuki/gcc/src/gcc/cp/mangle.c:2517
0x7d09e6 write_type
        /home/miyuki/gcc/src/gcc/cp/mangle.c:1974
0x7d2d04 write_bare_function_type
        /home/miyuki/gcc/src/gcc/cp/mangle.c:2440
0x7d7b39 mangle_decl_string
        /home/miyuki/gcc/src/gcc/cp/mangle.c:3411
0x7d7d77 get_mangled_id
        /home/miyuki/gcc/src/gcc/cp/mangle.c:3433
0x7d7d77 mangle_decl(tree_node*)
        /home/miyuki/gcc/src/gcc/cp/mangle.c:3478
0xefdd10 decl_assembler_name(tree_node*)
        /home/miyuki/gcc/src/gcc/tree.c:697
0x910d77 symtab_node::get_comdat_group_id()
        /home/miyuki/gcc/src/gcc/cgraph.h:207
0x910d77 analyze_functions
        /home/miyuki/gcc/src/gcc/cgraphunit.c:973
0x9120e5 symbol_table::finalize_compilation_unit()
        /home/miyuki/gcc/src/gcc/cgraphunit.c:2427
0x6f3037 cp_write_global_declarations()
        /home/miyuki/gcc/src/gcc/cp/decl2.c:4750
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.

======================================================

GCC 4.9.2 20141030 (Red Hat 4.9.2-5.ac1), i386, also crashes.

GCC 4.8.2 20140120 (Red Hat 4.8.2-16) rejects the code with the following error:
./ice_sizeof.cc:8:20: error: template argument 1 is invalid
 array<sizeof...(T1)> make_array(T1<T2> ...init)

clang-3.7 compiles the file without errors.

Changing the declaration to
"auto make_array_ice(T1<T2> ...init) -> array<sizeof...(T1)>"
does not change the behavior, but
"auto make_array_ice(T1<T2> ...init) -> array<sizeof...(init)>"
gets compiled without errors by all 3 mentioned versions of g++.
Comment 1 Mikhail Maltsev 2015-02-16 04:39:01 UTC
A few more comments. I wrote that GCC 5.0 segfaults. That's actually not true, I could not reproduce segfault on checked builds (only release version of 4.9.2), but never the less it's still ICE.

So, here is a bit more minimized example:

$ cat ice_sizeof.cc
template<int> struct S { };

template<template<int> class... T, int N>
S<sizeof...(T)> foo(T<N>...);

auto x = foo(S<2>{});

==========================================

The problem occurs during name mangling. I defined
#define DEBUG_MANGLE 1
The debug output (before ICE happens) ends with this:

  identifier              : S
  ++ add_substitution (template_decl at 0x7fb804560100)
  ++ substitutions   S-1_ = foo (template_decl at 0x7fb804560400)
                     S0_ = S (template_decl at 0x7fb804560100)
  template-arg            : integer_cst              (0x7fb80441c570)
  type                    : integer_type             (0x7fb8043fe690)
  ++ find_substitution (integer_type at 0x7fb8043fe690)
  bare-function-type      : function_type            (0x7fb804552c78)
  type                    : record_type              (0x7fb804552930)
  ++ find_substitution (record_type at 0x7fb804552930)
  name                    : type_decl                (0x7fb80454e5f0)
  unscoped-template-name  : template_decl            (0x7fb804560100)
  ++ find_substitution (template_decl at 0x7fb804560100)
  substitution            :
  template-args           : tree_vec                 (0x7fb80455cca0)
  template-arg            : sizeof_expr              (0x7fb80455cc60)
  type                    : type_pack_expansion      (0x7fb804552888)
  ++ find_substitution (type_pack_expansion at 0x7fb804552888)
  type                    : template_decl            (0x7fb804560280)
  ++ find_substitution (template_decl at 0x7fb804560280)

If I understand correctly, tree_class_check fails when we attempt to mangle the argument of sizeof...(T). It is (probably) represented through parameter pack expansion (sizeof...(T) must have the same value as the number of parameters in the pack "T<N>..."), which in turn depends on substitution of template template parameter T. Template template parameters are represented using TEMPLATE_DECL:
...
  else if (code == TEMPLATE_DECL)
    /* A template appearing as a template arg is a template template arg. */
    write_template_template_arg (node);
...
And write_CV_qualifiers_for_type rejects it.
Comment 2 Marek Polacek 2015-03-16 11:06:14 UTC
I can confirm the ICE.
Comment 3 Mikhail Maltsev 2015-03-16 14:29:50 UTC
For the record: a patch for this PR https://gcc.gnu.org/ml/gcc-patches/2015-02/msg01067.html
Comment 4 paolo@gcc.gnu.org 2015-07-14 22:37:21 UTC
Author: paolo
Date: Tue Jul 14 22:36:50 2015
New Revision: 225793

URL: https://gcc.gnu.org/viewcvs?rev=225793&root=gcc&view=rev
Log:
/cp
2015-07-14  Andrea Azzarone  <azzaronea@gmail.com>

	PR c++/65071
	* parser.c (cp_parser_sizeof_pack): Also consider template template
	parameters.

/testsuite
2015-07-14  Andrea Azzarone  <azzaronea@gmail.com>

	PR c++/65071
	* g++.dg/cpp0x/vt-65071.C: New.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/vt-65071.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/parser.c
    trunk/gcc/testsuite/ChangeLog
Comment 5 Paolo Carlini 2015-07-14 22:38:36 UTC
Fixed.