Bug 93314 - [10 Regression] Invalid use of non-static data member causes ICE in gimplify_expr
Summary: [10 Regression] Invalid use of non-static data member causes ICE in gimplify_...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.0
: P2 normal
Target Milestone: 10.5
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid, ice-on-invalid-code
Depends on:
Blocks: C++VLA
  Show dependency treegraph
 
Reported: 2020-01-17 18:59 UTC by Language Lawyer
Modified: 2022-11-28 19:35 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work: 11.0, 4.9.4
Known to fail: 10.0, 5.0
Last reconfirmed: 2020-01-17 00:00:00


Attachments
patch for stage 1 (1.85 KB, patch)
2021-04-14 17:49 UTC, Jason Merrill
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Language Lawyer 2020-01-17 18:59:22 UTC
int main()
{
    struct S { int m; };
    return sizeof(char[S::m]);
}

$ g++ prog.cc

prog.cc: In function 'int main()':
prog.cc:4:27: internal compiler error: in gimplify_expr, at gimplify.c:14581
    4 |     return sizeof(char[S::m]);
      |                        ~~~^
0x5c6160 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:14581
0x9a7434 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:13885
0x9a7de0 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:13702
0x9aa19f gimplify_compound_lval
	../../source/gcc/gimplify.c:3064
0x9a6c00 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:13533
0x9a7434 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:13885
0x9a7129 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:14348
0x9abfb0 internal_get_tmp_var
	../../source/gcc/gimplify.c:619
0x9ac749 get_initialized_tmp_var(tree_node*, gimple**, gimple**, bool)
	../../source/gcc/gimplify.c:674
0x9ac749 gimplify_save_expr
	../../source/gcc/gimplify.c:6072
0x9a7621 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:13881
0x9a7434 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:13885
0x9a7129 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:14348
0x9a7434 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:13885
0x9b1ecb gimplify_modify_expr
	../../source/gcc/gimplify.c:5765
0x9a73a2 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:13581
0x9acc8e gimplify_stmt(tree_node**, gimple**)
	../../source/gcc/gimplify.c:6822
0x9acc8e gimplify_and_add(tree_node*, gimple**)
	../../source/gcc/gimplify.c:486
0x9acc8e gimplify_return_expr
	../../source/gcc/gimplify.c:1667
0x9a8303 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	../../source/gcc/gimplify.c:13842
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.

(https://wandbox.org/permlink/GNNTjXAK2pQ5clUt)

I've selectively checked about some of g++ versions, from 4.4.7 to HEAD, on wandbox.org. They're all crashing, just segfaulting before 5.1.0 and ICEing in gimplify_expr starting from 5.1.0.
Comment 1 Language Lawyer 2020-01-17 19:26:13 UTC
GCC thinks that `char[S::m]` is VLA (because the lvalue-to-rvalue conversion on `S::m` lvalue doesn't look like a constant expression) and tries to move the evaluation of `sizeof(char[S::m])` to run time.

$ g++ prog.cc -pedantic

prog.cc: In function 'int main()':
prog.cc:4:28: warning: ISO C++ forbids variable length array [-Wvla]
    4 |     return sizeof(char[S::m]);
      |                            ^
prog.cc:4:27: internal compiler error: in gimplify_expr, at gimplify.c:14581
    4 |     return sizeof(char[S::m]);
      |
...
Comment 2 Martin Sebor 2020-01-20 10:47:07 UTC
Confirmed.  Bisection points to r210692 committed into 4.10.0:

gcc/
	* tree.def (VOID_CST): New.
	* tree-core.h (TI_VOID): New.
	* tree.h (void_node): New.
	* tree.c (tree_node_structure_for_code, tree_code_size)
	(iterative_hash_expr): Handle VOID_CST.
	(build_common_tree_nodes): Initialize void_node.

gcc/c-family/
	* c-common.h (CTI_VOID_ZERO, void_zero_node): Delete.
	* c-common.c (c_common_nodes_and_builtins): Don't initialize
	void_zero_node.
	* c-pretty-print.c (pp_c_void_constant): New function.
	(c_pretty_printer::constant, c_pretty_printer::primary_expression)
	(c_pretty_printer::expression): Handle VOID_CST.
	* cilk.c (extract_free_variables): Likewise.
	* c-ubsan.c (ubsan_instrument_division, ubsan_instrument_shift)
	(ubsan_instrument_vla): Use void_node instead of void_zero_node.

gcc/c/
	* c-array-notation.c (expand_array_notations): Use void_node
	instead of void_zero_node.

gcc/cp/
	* cvt.c (convert_to_void): Use void_node instead of void_zero_node.
	* cp-array-notation.c (replace_invariant_exprs): Likewise.
	(expand_array_notation): Handle VOID_CST.
	* error.c (dump_expr): Likewise.
	* cxx-pretty-print.c (cxx_pretty_printer::primary_expression)
	(cxx_pretty_printer::expression): Likewise.
	(pp_cxx_new_expression): Use void_node instead of void_zero_node.
	* decl.c (register_dtor_fn): Likewise.
	* init.c (build_raw_new_expr, build_new_1, build_vec_init)
	(build_delete, push_base_cleanups): Likewise.
	* mangle.c (write_expression): Likewise.
	* semantics.c (finish_break_stmt, empty_expr_stmt_p): Likewise.
	* pt.c (tsubst_decl, tsubst_copy_and_build): Likewise.
	(tsubst, tsubst_copy, build_non_dependent_expr): Handle VOID_CST.
	* tree.c (cp_tree_equal): Likewise.
	(build_dummy_object, is_dummy_object, stabilize_expr): Use void_node
	instead of void_zero_node.
	* typeck.c (check_return_expr): Likewise.
	* typeck2.c (build_functional_cast): Likewise.
Comment 3 rsandifo@gcc.gnu.org 2020-01-20 18:03:34 UTC
Hmm, yeah.  Before the patch we silently accepted the code
and generated an unconditional trap for a null dereference,
which doesn't sound right either.  This is because we used
to fold the dummy object pointer (represented using an
INTEGER_CST with void_type) into a normal null pointer.

Where should this be trapped?  The error for accessing
a non-static data member is suppressed for sizeof,
and obviously needs to be for sizeof(S::m):

  /* DR 613/850: Can use non-static data members without an associated
     object in sizeof/decltype/alignof.  */
  if (is_dummy_object (object) && cp_unevaluated_operand == 0
      && (!processing_template_decl || !current_class_ref))

A see-one-play-one fix would be to force cp_unevaluated_operand
to zero while parsing an array dimension, on the basis that the
dimension should either be constant (standard C++) or can be
evaluated (GNU VLAs).  That feels really hackish though...

Should we instead trap this during gimplification?  But then
that would probably make:

   sizeof(char[sizeof(char[S::m])])

valid, which doesn't sound right either.
Comment 4 Paolo Carlini 2020-02-07 10:40:35 UTC
Related to c++/84939
Comment 5 Jakub Jelinek 2020-03-04 09:44:43 UTC
GCC 8.4.0 has been released, adjusting target milestone.
Comment 6 Jakub Jelinek 2020-03-04 13:27:11 UTC
Jason, your thoughts on this?
Comment 7 CVS Commits 2021-04-14 17:48:28 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:9b53edc796d284b6adec7f2996772dbddf4c341e

commit r11-8181-g9b53edc796d284b6adec7f2996772dbddf4c341e
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Apr 14 09:30:05 2021 -0400

    c++: non-static member, array bound, sizeof [PR93314]
    
    N2253 allowed referring to non-static data members without an object in
    unevaluated operands like that of sizeof, but in a constant-expression
    context like an array bound or template argument within such an unevaluated
    operand we do actually need a value, so that permission cannot apply.
    
    gcc/cp/ChangeLog:
    
            PR c++/93314
            * semantics.c (finish_id_expression_1): Clear cp_unevaluated_operand
            for a non-static data member in a constant-expression.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/93314
            * g++.dg/parse/uneval1.C: New test.
Comment 8 Jason Merrill 2021-04-14 17:49:08 UTC
Fixed for 11 so far.
Comment 9 Jason Merrill 2021-04-14 17:49:52 UTC
Created attachment 50594 [details]
patch for stage 1

A more general, but also more risky, fix for next stage 1.
Comment 10 Jakub Jelinek 2021-05-14 09:52:36 UTC
GCC 8 branch is being closed.
Comment 11 CVS Commits 2021-05-18 21:19:17 UTC
The releases/gcc-11 branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:b786dafe9eb933f23686c68c6d7110fef5656985

commit r11-8430-gb786dafe9eb933f23686c68c6d7110fef5656985
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Apr 14 11:24:50 2021 -0400

    c++: constant expressions are evaluated [PR93314]
    
    My GCC 11 patch for PR93314 turned off cp_unevaluated_operand while
    processing an id-expression that names a non-static data member, but the
    broader issue is that in general, a constant-expression is evaluated even in
    an unevaluated operand.
    
    This also fixes 100205, introduced by the earlier patch that couldn't
    distinguish between the different allow_non_constant_p cases.
    
            PR c++/100205
            PR c++/93314
    
    gcc/cp/ChangeLog:
    
            * cp-tree.h (cp_evaluated): Add reset parm to constructor.
            * parser.c (cp_parser_constant_expression): Change
            allow_non_constant_p to int.  Use cp_evaluated.
            (cp_parser_initializer_clause): Pass 2 to allow_non_constant_p.
            * semantics.c (finish_id_expression_1): Don't mess with
            cp_unevaluated_operand here.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/decltype-nonstatic1.C: New test.
Comment 12 Richard Biener 2021-06-01 08:15:54 UTC
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
Comment 13 Richard Biener 2022-05-27 09:41:49 UTC
GCC 9 branch is being closed
Comment 14 Jakub Jelinek 2022-06-28 10:39:18 UTC
GCC 10.4 is being released, retargeting bugs to GCC 10.5.