Details, including minimal reproducer, below. The Objective-C frontend crashes when I try to use -fobjc-nilcheck under the NeXT v2 ABI. If I send a message whose return type would require using objc_msgSend_stret (and a nil check), crash. Message sends not requiring stret (and thus no nil check) work fine. === macOS 10.15.7 "Catalina" / x86_64 $ gcc --version gcc (GCC) 10.2.0 $ gcc -Os -fobjc-nilcheck -xobjective-c - struct point { double x, y, z; }; @interface Foo - (struct point)bar; @end Foo *f; int main(void) { struct point p = [f bar]; } <stdin>: In function ‘main’: <stdin>:10:9: internal compiler error: Segmentation fault: 11 Here's the backtrace: (lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0) * frame #0: 0x00000001012ce428 cc1obj`recompute_constructor_flags(c=0x0000000144513f90) at tree.c:2018:12 frame #1: 0x00000001012cd45f cc1obj`build_constructor(type=0x0000000144505930, vals=0x000000014450a678) at tree.c:2059:3 frame #2: 0x000000010000c2bd cc1obj`objc_build_constructor(type=0x0000000144505930, elts=0x000000014450a678) at objc-act.c:3235:22 frame #3: 0x0000000100031b37 cc1obj`build_v2_build_objc_method_call(super_flag=0, method_prototype=0x0000000144504a18, lookup_object=0x00000001444f3720, selector=0x00000001444f36a0, method_params=0x000000014452b140, check_for_nil=true) at objc-next-runtime-abi-02.c:1637:12 frame #4: 0x000000010002d8da cc1obj`next_runtime_abi_02_build_objc_method_call(loc=62820, method_prototype=0x0000000144504a18, receiver=0x0000000142c5d240, rtype=0x0000000144527000, sel_name=0x000000014451bf00, method_params=0x0000000000000000, super=0) at objc-next-runtime-abi-02.c:1720:10 frame #5: 0x000000010000902d cc1obj`objc_finish_message_expr(receiver=0x0000000142c5d240, sel_name=0x000000014451bf00, method_params=0x0000000000000000, deprecated_method_prototype=0x0000000000000000) at objc-act.c:5679:12 frame #6: 0x000000010000ec8f cc1obj`objc_build_message_expr(receiver=0x0000000142c5d240, message_args=0x000000014451bf00) at objc-act.c:5308:10 frame #7: 0x00000001000be312 cc1obj`c_parser_postfix_expression(parser=0x0000000142c5d1b0) at c-parser.c:10163:17 frame #8: 0x00000001000b5f21 cc1obj`c_parser_unary_expression(parser=0x0000000142c5d1b0) at c-parser.c:8276:14 frame #9: 0x00000001000b3ce5 cc1obj`c_parser_cast_expression(parser=0x0000000142c5d1b0, after=0x0000000000000000) at c-parser.c:8115:12 frame #10: 0x00000001000b209b cc1obj`c_parser_binary_expression(parser=0x0000000142c5d1b0, after=0x0000000000000000, omp_atomic_lhs=0x0000000000000000) at c-parser.c:7918:19 frame #11: 0x00000001000b1800 cc1obj`c_parser_conditional_expression(parser=0x0000000142c5d1b0, after=0x0000000000000000, omp_atomic_lhs=0x0000000000000000) at c-parser.c:7652:10 frame #12: 0x00000001000b13ed cc1obj`c_parser_expr_no_commas(parser=0x0000000142c5d1b0, after=0x0000000000000000, omp_atomic_lhs=0x0000000000000000) at c-parser.c:7569:9 frame #13: 0x00000001000c6921 cc1obj`c_parser_initializer(parser=0x0000000142c5d1b0) at c-parser.c:5227:13 frame #14: 0x00000001000c34a0 cc1obj`c_parser_declaration_or_fndef(parser=0x0000000142c5d1b0, fndef_ok=false, static_assert_ok=true, empty_ok=true, nested=true, start_attr_ok=true, objc_foreach_object_declaration=0x0000000000000000, omp_declare_simd_clauses=vec<c_token, va_heap, vl_ptr> @ 0x00007ffeefbfede8, have_attrs=false, attrs=0x0000000000000000, oacc_routine_data=0x0000000000000000, fallthru_attr_p=0x00007ffeefbfeebf) at c-parser.c:2248:12 frame #15: 0x00000001000c00d4 cc1obj`c_parser_compound_statement_nostart(parser=0x0000000142c5d1b0) at c-parser.c:5718:4 frame #16: 0x00000001000c6c3d cc1obj`c_parser_compound_statement(parser=0x0000000142c5d1b0, endlocp=0x00007ffeefbff070) at c-parser.c:5617:24 frame #17: 0x00000001000c3e66 cc1obj`c_parser_declaration_or_fndef(parser=0x0000000142c5d1b0, fndef_ok=true, static_assert_ok=true, empty_ok=true, nested=false, start_attr_ok=true, objc_foreach_object_declaration=0x0000000000000000, omp_declare_simd_clauses=vec<c_token, va_heap, vl_ptr> @ 0x00007ffeefbff478, have_attrs=false, attrs=0x0000000000000000, oacc_routine_data=0x0000000000000000, fallthru_attr_p=0x0000000000000000) at c-parser.c:2505:11 frame #18: 0x00000001000ee11e cc1obj`c_parser_external_declaration(parser=0x0000000142c5d1b0) at c-parser.c:1745:7 frame #19: 0x00000001000b095d cc1obj`c_parser_translation_unit(parser=0x0000000142c5d1b0) at c-parser.c:1618:4 frame #20: 0x00000001000b066b cc1obj`c_parse_file() at c-parser.c:21745:3 frame #21: 0x0000000100178750 cc1obj`c_common_parse_file() at c-opts.c:1190:7 frame #22: 0x0000000100eaeb34 cc1obj`compile_file() at toplev.c:458:3 frame #23: 0x0000000100eaaee5 cc1obj`do_compile() at toplev.c:2278:11 frame #24: 0x0000000100eaa5b4 cc1obj`toplev::main(this=0x00007ffeefbff7f8, argc=24, argv=0x00007ffeefbff838) at toplev.c:2417:7 frame #25: 0x0000000101427c0b cc1obj`main(argc=24, argv=0x00007ffeefbff838) at main.c:39:17 frame #26: 0x00007fff6c08ecc9 libdyld.dylib`start + 1
I'm not an expert on GCC ASTs, but would this change be correct here? I'm trying to simulate something like `struct whatever ftree[8 * 3] = {0};`. diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c index e401906ed..0cc19a079 100644 --- a/gcc/objc/objc-next-runtime-abi-02.c +++ b/gcc/objc/objc-next-runtime-abi-02.c @@ -1631,9 +1631,8 @@ build_v2_build_objc_method_call (int super_flag, tree method_prototype, || TREE_CODE (ret_type) == UNION_TYPE) { vec<constructor_elt, va_gc> *rtt = NULL; - /* ??? CHECKME. hmmm..... think we need something more - here. */ - CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE); + CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, build_int_cst (integer_type_node, + 0)); ftree = objc_build_constructor (ret_type, rtt); } else
(Oops, ignore the `[8*3]` part in the explanation.)
<https://gcc.gnu.org/pipermail/gcc-patches/2021-August/577396.html>
The master branch has been updated by Iain D Sandoe <iains@gcc.gnu.org>: https://gcc.gnu.org/g:d2aa4e0b3b5053df8f5853d9ed29022ff0d3ecf6 commit r12-3006-gd2aa4e0b3b5053df8f5853d9ed29022ff0d3ecf6 Author: Iain Sandoe <iain@sandoe.co.uk> Date: Sat Aug 14 12:27:55 2021 +0100 Objective-C: fix crash with -fobjc-nilcheck When -fobjc-nilcheck is enabled, messages that result in a struct type should yield a zero-initialized struct when sent to nil. Currently, the frontend crashes when it encounters this situation. This patch fixes the crash by generating the tree for the `{}` initializer. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> Co-authored-by: Matt Jacobson <mhjacobson@me.com> PR objc/101666 gcc/objc/ChangeLog: * objc-act.c (objc_build_constructor): Handle empty constructor lists. * objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): Handle nil receivers. (build_v2_build_objc_method_call): Likewise. gcc/testsuite/ChangeLog: * obj-c++.dg/pr101666-0.mm: New test. * obj-c++.dg/pr101666-1.mm: New test. * obj-c++.dg/pr101666.inc: New. * objc.dg/pr101666-0.m: New test. * objc.dg/pr101666-1.m: New test. * objc.dg/pr101666.inc: New.
fixed on master, should be backported to open branches.
The releases/gcc-10 branch has been updated by Iain D Sandoe <iains@gcc.gnu.org>: https://gcc.gnu.org/g:acd300cfdc434f03f1b08e46bca98b963d43ebc3 commit r10-10798-gacd300cfdc434f03f1b08e46bca98b963d43ebc3 Author: Iain Sandoe <iain@sandoe.co.uk> Date: Sat Aug 14 12:27:55 2021 +0100 Objective-C: fix crash with -fobjc-nilcheck When -fobjc-nilcheck is enabled, messages that result in a struct type should yield a zero-initialized struct when sent to nil. Currently, the frontend crashes when it encounters this situation. This patch fixes the crash by generating the tree for the `{}` initializer. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> Co-authored-by: Matt Jacobson <mhjacobson@me.com> PR objc/101666 gcc/objc/ChangeLog: * objc-act.c (objc_build_constructor): Handle empty constructor lists. * objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): Handle nil receivers. (build_v2_build_objc_method_call): Likewise. gcc/testsuite/ChangeLog: * obj-c++.dg/pr101666-0.mm: New test. * obj-c++.dg/pr101666-1.mm: New test. * obj-c++.dg/pr101666.inc: New. * objc.dg/pr101666-0.m: New test. * objc.dg/pr101666-1.m: New test. * objc.dg/pr101666.inc: New. (cherry picked from commit d2aa4e0b3b5053df8f5853d9ed29022ff0d3ecf6)
fixed on open branches, needed on at least 9.x for vendor branches.
needed on 11.x too.
The releases/gcc-11 branch has been updated by Iain D Sandoe <iains@gcc.gnu.org>: https://gcc.gnu.org/g:87431b4a81e9dc5988509399704a7352800c6a77 commit r11-11339-g87431b4a81e9dc5988509399704a7352800c6a77 Author: Iain Sandoe <iain@sandoe.co.uk> Date: Sat Aug 14 12:27:55 2021 +0100 Objective-C: fix crash with -fobjc-nilcheck When -fobjc-nilcheck is enabled, messages that result in a struct type should yield a zero-initialized struct when sent to nil. Currently, the frontend crashes when it encounters this situation. This patch fixes the crash by generating the tree for the `{}` initializer. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> Co-authored-by: Matt Jacobson <mhjacobson@me.com> PR objc/101666 gcc/objc/ChangeLog: * objc-act.c (objc_build_constructor): Handle empty constructor lists. * objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): Handle nil receivers. (build_v2_build_objc_method_call): Likewise. gcc/testsuite/ChangeLog: * obj-c++.dg/pr101666-0.mm: New test. * obj-c++.dg/pr101666-1.mm: New test. * obj-c++.dg/pr101666.inc: New. * objc.dg/pr101666-0.m: New test. * objc.dg/pr101666-1.m: New test. * objc.dg/pr101666.inc: New. (cherry picked from commit d2aa4e0b3b5053df8f5853d9ed29022ff0d3ecf6)
now fixed on open branches (still needed on earlier 'vendor' branches)