Bug 92625 - [8/9/10 Regression] Internal compiler error accessing element in static constexpr char array in template class using alias
Summary: [8/9/10 Regression] Internal compiler error accessing element in static const...
Status: RESOLVED DUPLICATE of bug 90966
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.1.0
: P2 normal
Target Milestone: 8.4
Assignee: Jason Merrill
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2019-11-22 01:34 UTC by Haoran Ni
Modified: 2020-02-04 20:01 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-11-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Haoran Ni 2019-11-22 01:34:23 UTC
The internal compiler error can be reproduced by the following minimal example that I was able to boil down to.

//------ te.cpp

template< typename T >
struct G {

    using my_int = char;
    static constexpr my_int my_array[1] {0};

};

void work() {
    G<double>::my_array[0];
}

//------ end

Compiling command:
    g++ -std=c++17 -c -o te.o -save-temps te.cpp

My GCC information (from g++ -v):
    Using built-in specs.
    COLLECT_GCC=g++
    COLLECT_LTO_WRAPPER=/afs/glue.umd.edu/software/gcc/9.1.0/sys/bin/../libexec/gcc/x86_64-pc-linux-gnu/9.1.0/lto-wrapper
    Target: x86_64-pc-linux-gnu
    Configured with: ../src/configure --prefix=/cell_root/software/gcc/9.1.0/sys --enable-languages=c,c++,fortran --with-gmp=/usr/local/gmp --with-isl=/usr/local/isl --with-mpfr=/usr/local/mpfr --with-mpc=/usr/local/mpc --with-as=/usr/local/binutils/2.26/bin/as --with-ld=/usr/local/binutils/2.26/bin/ld
    Thread model: posix
    gcc version 9.1.0 (GCC)

My OS information:
    Red Hat Enterprise Linux Server release 6.10 (Santiago)

Compiler output:

//------ start output

te.cpp: In instantiation of 'constexpr const my_int G<double>::my_array [1]':
te.cpp:11:16:   required from here
te.cpp:6:29: internal compiler error: in tsubst_copy, at cp/pt.c:16155
    6 |     static constexpr my_int my_array[1] {0};
      |                             ^~~~~~~~
0x593dca tsubst_copy
	../../src/gcc/cp/pt.c:16155
0x6c8770 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool)
	../../src/gcc/cp/pt.c:19611
0x6d0284 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool)
	../../src/gcc/cp/pt.c:18241
0x6d0284 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool)
	../../src/gcc/cp/pt.c:17917
0x6d260c tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool)
	../../src/gcc/cp/pt.c:15482
0x6d260c tsubst_init
	../../src/gcc/cp/pt.c:15486
0x6ce322 regenerate_decl_from_template
	../../src/gcc/cp/pt.c:24155
0x6ce322 instantiate_decl(tree_node*, bool, bool)
	../../src/gcc/cp/pt.c:24699
0x63be13 maybe_instantiate_decl
	../../src/gcc/cp/decl2.c:5300
0x63be13 maybe_instantiate_decl
	../../src/gcc/cp/decl2.c:5284
0x63d958 mark_used(tree_node*, int)
	../../src/gcc/cp/decl2.c:5456
0x6fa5af finish_id_expression_1
	../../src/gcc/cp/semantics.c:3777
0x6fa5af finish_id_expression(tree_node*, tree_node*, tree_node*, cp_id_kind*, bool, bool, bool*, bool, bool, bool, bool, char const**, unsigned int)
	../../src/gcc/cp/semantics.c:3925
0x6980f9 cp_parser_primary_expression
	../../src/gcc/cp/parser.c:5723
0x69becb cp_parser_postfix_expression
	../../src/gcc/cp/parser.c:7178
0x6a89f9 cp_parser_unary_expression
	../../src/gcc/cp/parser.c:8472
0x68696f cp_parser_cast_expression
	../../src/gcc/cp/parser.c:9357
0x68715a cp_parser_binary_expression
	../../src/gcc/cp/parser.c:9460
0x687ef7 cp_parser_assignment_expression
	../../src/gcc/cp/parser.c:9758
0x68821a cp_parser_expression
	../../src/gcc/cp/parser.c:9925
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.

//------ end

More information and tests:
In the original code, doing any of the following removes the internal error.
1. remove the template and make "G" a normal struct;
2. use "char" directly instead of "my_int" in the array definition;
3. replace "char" with "int" in the alias declaration;
4. remove the usage of the array in the work() function.

Moreover, I am able to reproduce the same error on a completely different version and OS and the info is as follows.

//------ start another environment

$> g++ -v
Using built-in specs.
COLLECT_GCC=g++-9
COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc/9.2.0_1/libexec/gcc/x86_64-apple-darwin18/9.2.0/lto-wrapper
Target: x86_64-apple-darwin18
Configured with: ../configure --build=x86_64-apple-darwin18 --prefix=/usr/local/Cellar/gcc/9.2.0_1 --libdir=/usr/local/Cellar/gcc/9.2.0_1/lib/gcc/9 --disable-nls --enable-checking=release --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-9 --with-gmp=/usr/local/opt/gmp --with-mpfr=/usr/local/opt/mpfr --with-mpc=/usr/local/opt/libmpc --with-isl=/usr/local/opt/isl --with-system-zlib --with-pkgversion='Homebrew GCC 9.2.0_1' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --disable-multilib --with-native-system-header-dir=/usr/include --with-sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
Thread model: posix
gcc version 9.2.0 (Homebrew GCC 9.2.0_1)

//------ end
Comment 1 Jakub Jelinek 2019-11-22 15:33:32 UTC
Started to ICE with r263511.
Comment 2 Jakub Jelinek 2019-11-22 15:53:48 UTC
Though, with a small modification it started with r221328.
template <typename T>
struct G {
  using C = char;
  static constexpr C my_array[1] = "";
};

void
work ()
{
  G<double>::my_array[1];
}

This ICEs because in tsubst_copy we do for STRING_CST:
16647		/* Instantiate any typedefs in the type.  */
16648		tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
16649		r = fold_convert (type, t);
16650		gcc_assert (TREE_CODE (r) == code);
For other codes handled by this like INTEGER_CST, REAL_CST and COMPLEX_CST, the assertion is meaningful, but for STRING_CSTs fold_convert doesn't really create a new STRING_CST with different type.  Both types are C[1], just the C is different tree between the two.
So, shall we just not do this assertion (say gcc_assert (code == STRING_CST || TREE_CODE (r) == code); and is it fine if we return a NOP_EXPR?  I guess it could change something for lvalues, with say ADDR_EXPR of a STRING_CST being valid, but ADDR_EXPR of NOP_EXPR of STRING_CST not valid.
Or shall we build a new STRING_CST with the new type if the type is different?
Something else?
Comment 3 Jason Merrill 2020-02-04 20:01:03 UTC
Fixed by the patch for 90966.

*** This bug has been marked as a duplicate of bug 90966 ***