Created attachment 40561 [details] Preprocessed file The following code compiles but prints garbage and then segfaults under gcc 6.3.0 on OS X: #include <iostream> #include <string> void foo(const std::string &a) { std::cout << a << std::endl; } template <typename... Args> void bar(Args &&... args) { [&]() { [&]() { foo(args...); }(); }(); } int main() { const std::string x("Hello World!"); bar(x); } Expected result: Print "Hello World!" and exit. Compiling with `-Wextra -Wall` gives this warning: param.cpp: In function 'int main()': param.cpp:11:11: warning: 'args#0' is used uninitialized in this function [-Wuninitialized] foo(args...); ^~~ param.cpp:16:5: note: 'args#0' was declared here int main() { ^~~~ Clang and VC++ do not have any issues here. People at StackOverflow seem to agree that this is valid code and appears to be a bug in GCC: http://stackoverflow.com/questions/41769851/gcc-causes-segfault-for-lambda-captured-parameter-pack Additional information: [:~/tmp] 1 $ g++-6 param.cpp && ./a.out # Garbage here Segmentation fault: 11 [:~/tmp] 139 $ g++-6 -v Using built-in specs. COLLECT_GCC=g++-6 COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc/6.3.0_1/libexec/gcc/x86_64-apple-darwin16.3.0/6.3.0/lto-wrapper Target: x86_64-apple-darwin16.3.0 Configured with: ../configure --build=x86_64-apple-darwin16.3.0 --prefix=/usr/local/Cellar/gcc/6.3.0_1 --libdir=/usr/local/Cellar/gcc/6.3.0_1/lib/gcc/6 --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-6 --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 --enable-libstdcxx-time=yes --enable-stage1-checking --enable-checking=release --enable-lto --with-build-config=bootstrap-debug --disable-werror --with-pkgversion='Homebrew GCC 6.3.0_1' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --enable-plugin --disable-nls --enable-multilib Thread model: posix gcc version 6.3.0 (Homebrew GCC 6.3.0_1) [:~/tmp] 1 $ sw_vers ProductName: Mac OS X ProductVersion: 10.12.2 BuildVersion: 16C67
P.S.: Also experienced on Wandbox's GCC 7.0.1 HEAD. Not passing the parameter pack into bar by universal reference causes an internal compiler error in gcc 7.0.1 HEAD: prog.cc: In function 'void bar(Args ...) [with Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]': prog.cc:14:4: internal compiler error: in make_decl_rtl, at varasm.c:1304 [&]() { ~~~~~~~ [&]() { ~~~~~~~ foo(args...); ~~~~~~~~~~~~~ }(); ~~~~ }(); ~^~ http://melpon.org/wandbox/permlink/mYtVweIn8zv4t74Y Thanks to AMA at StackOverflow for finding this.
Simplified testcase: void foo (int a) { if (a != 127) __builtin_abort (); } template <typename... Args> void bar (Args &&... args) { [&]() { [&]() { foo (args...); } (); } (); } int main () { int x = 127; bar (x); }
Seems there is a mismatch between what PARM_DECL is used. E.g. -fdump-tree-omplower-all dump shows: void bar(Args&& ...) [with Args = {int&}] (intD.9 & args#0D.2308) { struct __lambda0D.2311 D.2341; typedef struct __lambda0D.2311 __lambda0D.2311; D.2341.__args#0D.2317 = args#0D.2339; ... One args#0 PARM_DECL, with uid 2308 is created during: #1 0x00000000014689bf in copy_node_stat (node=<parm_decl 0x7fffefc45080 args>) at ../../gcc/tree.c:1157 #2 0x0000000000823237 in tsubst_decl (t=<parm_decl 0x7fffefc45080 args>, args=<tree_vec 0x7fffefc43c60>, complain=0) at ../../gcc/cp/pt.c:12447 #3 0x0000000000826de5 in tsubst (t=<parm_decl 0x7fffefc45080 args>, args=<tree_vec 0x7fffefc43c60>, complain=0, in_decl=<function_decl 0x7fffefc46100 bar>) at ../../gcc/cp/pt.c:13272 #4 0x000000000082150e in tsubst_decl (t=<function_decl 0x7fffefc46100 bar>, args=<tree_vec 0x7fffefc43c60>, complain=0) at ../../gcc/cp/pt.c:12273 #5 0x0000000000826de5 in tsubst (t=<function_decl 0x7fffefc46100 bar>, args=<tree_vec 0x7fffefc43c60>, complain=0, in_decl=<template_decl 0x7fffefc45100 bar>) at ../../gcc/cp/pt.c:13272 #6 0x0000000000841d23 in instantiate_template_1 (tmpl=<template_decl 0x7fffefc45100 bar>, orig_args=<tree_vec 0x7fffefc43c60>, complain=0) at ../../gcc/cp/pt.c:18089 #7 0x000000000084231d in instantiate_template (tmpl=<template_decl 0x7fffefc45100 bar>, orig_args=<tree_vec 0x7fffefc43c60>, complain=0) at ../../gcc/cp/pt.c:18145 #8 0x0000000000843683 in fn_type_unification (fn=<template_decl 0x7fffefc45100 bar>, explicit_targs=<tree 0x0>, targs=<tree_vec 0x7fffefc43c60>, args=0x7fffffffc8a0, nargs=1, return_type=<tree 0x0>, strict=DEDUCE_CALL, flags=1, explain_p=false, decltype_p=false) at ../../gcc/cp/pt.c:18525 #9 0x000000000076f4c2 in add_template_candidate_real (candidates=0x7fffffffcba0, tmpl=<template_decl 0x7fffefc45100 bar>, ctype=<tree 0x0>, explicit_targs=<tree 0x0>, first_arg=<tree 0x0>, arglist=0x7fffefc4a9d8, return_type=<tree 0x0>, access_path=<tree 0x0>, conversion_path=<tree 0x0>, flags=1, obj=<tree 0x0>, strict=DEDUCE_CALL, complain=3) at ../../gcc/cp/call.c:3164 #10 0x000000000076f91f in add_template_candidate (candidates=0x7fffffffcba0, tmpl=<template_decl 0x7fffefc45100 bar>, ctype=<tree 0x0>, explicit_targs=<tree 0x0>, first_arg=<tree 0x0>, arglist=0x7fffefc4a9d8, return_type=<tree 0x0>, access_path=<tree 0x0>, conversion_path=<tree 0x0>, flags=1, strict=DEDUCE_CALL, complain=3) at ../../gcc/cp/call.c:3246 #11 0x0000000000777c8b in add_candidates (fns=<overload 0x7fffefc436e0>, first_arg=<tree 0x0>, args=0x7fffefc4a9d8, return_type=<tree 0x0>, explicit_targs=<tree 0x0>, template_only=false, conversion_path=<tree 0x0>, access_path=<tree 0x0>, flags=1, candidates=0x7fffffffcba0, complain=3) at ../../gcc/cp/call.c:5488 #12 0x0000000000772af7 in perform_overload_resolution (fn=<overload 0x7fffefc436e0>, args=0x7fffefc4a9d8, candidates=0x7fffffffcba0, any_viable_p=0x7fffffffcb9f, complain=3) at ../../gcc/cp/call.c:4142 #13 0x0000000000772de4 in build_new_function_call (fn=<overload 0x7fffefc436e0>, args=0x7fffffffcd20 = {...}, koenig_p=true, complain=3) at ../../gcc/cp/call.c:4227 #14 0x00000000009a7943 in finish_call_expr (fn=<overload 0x7fffefc436e0>, args=0x7fffffffcd20 = {...}, disallow_virtual=false, koenig_p=true, complain=3) at ../../gcc/cp/semantics.c:2441 #15 0x00000000008e5475 in cp_parser_postfix_expression (parser=0x7ffff7ff5bd0, address_p=false, cast_p=false, member_access_only_p=false, decltype_p=false, pidk_return=0x0) at ../../gcc/cp/parser.c:7019 i.e. on: 12273 DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, 12274 complain, t); The other args#0 PARM_DECL is created during: #1 0x00000000014689bf in copy_node_stat (node=<parm_decl 0x7fffefc45080 args>) at ../../gcc/tree.c:1157 #2 0x0000000000823237 in tsubst_decl (t=<parm_decl 0x7fffefc45080 args>, args=<tree_vec 0x7fffefc54020>, complain=3) at ../../gcc/cp/pt.c:12447 #3 0x000000000081c3aa in tsubst_pack_expansion (t=<expr_pack_expansion 0x7fffefabedb0>, args=<tree_vec 0x7fffefc54020>, complain=3, in_decl=<tree 0x0>) at ../../gcc/cp/pt.c:11313 #4 0x000000000083df90 in tsubst_copy_and_build (t=<tree_list 0x7fffefc4a988>, args=<tree_vec 0x7fffefc54020>, complain=3, in_decl=<tree 0x0>, function_p=false, integral_constant_expression_p=false) at ../../gcc/cp/pt.c:17384 #5 0x000000000081a380 in instantiate_class_template_1 (type=<record_type 0x7fffefc533f0 __lambda0>) at ../../gcc/cp/pt.c:10691 #6 0x000000000081a685 in instantiate_class_template (type=<record_type 0x7fffefc533f0 __lambda0>) at ../../gcc/cp/pt.c:10749 #7 0x000000000093ebad in complete_type (type=<record_type 0x7fffefc533f0 __lambda0>) at ../../gcc/cp/typeck.c:133 #8 0x000000000084068f in tsubst_copy_and_build (t=<lambda_expr 0x7fffefaea050>, args=<tree_vec 0x7fffefc43c60>, complain=3, in_decl=<template_decl 0x7fffefc45100 bar>, function_p=true, integral_constant_expression_p=false) at ../../gcc/cp/pt.c:17800 #9 0x000000000083c0d0 in tsubst_copy_and_build (t=<call_expr 0x7fffefc51000>, args=<tree_vec 0x7fffefc43c60>, complain=3, in_decl=<template_decl 0x7fffefc45100 bar>, function_p=false, integral_constant_expression_p=false) at ../../gcc/cp/pt.c:17077 #10 0x0000000000838e48 in tsubst_expr (t=<call_expr 0x7fffefc51000>, args=<tree_vec 0x7fffefc43c60>, complain=3, in_decl=<template_decl 0x7fffefc45100 bar>, integral_constant_expression_p=false) at ../../gcc/cp/pt.c:16403 #11 0x0000000000833445 in tsubst_expr (t=<expr_stmt 0x7fffefc43c00>, args=<tree_vec 0x7fffefc43c60>, complain=3, in_decl=<template_decl 0x7fffefc45100 bar>, integral_constant_expression_p=false) at ../../gcc/cp/pt.c:15671 #12 0x000000000083332a in tsubst_expr (t=<statement_list 0x7fffefc43580>, args=<tree_vec 0x7fffefc43c60>, complain=3, in_decl=<template_decl 0x7fffefc45100 bar>, integral_constant_expression_p=false) at ../../gcc/cp/pt.c:15657 #13 0x0000000000834f77 in tsubst_expr (t=<bind_expr 0x7fffefabeb70>, args=<tree_vec 0x7fffefc43c60>, complain=3, in_decl=<template_decl 0x7fffefc45100 bar>, integral_constant_expression_p=false) at ../../gcc/cp/pt.c:15881 #14 0x0000000000856ecc in instantiate_decl (d=<function_decl 0x7fffefc46500 bar>, defer_ok=0, expl_inst_class_mem_p=false) at ../../gcc/cp/pt.c:22812 So when we use a PARM_DECL in the initialization of the lambda struct that is actually not tha containing function's PARM_DECL, it is uninitialized use.
Experienced this bug today. Another example + information available here: https://stackoverflow.com/questions/45117719 Possibly related: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71386
Author: paolo Date: Mon Oct 2 12:40:26 2017 New Revision: 253350 URL: https://gcc.gnu.org/viewcvs?rev=253350&root=gcc&view=rev Log: 2017-10-02 Paolo Carlini <paolo.carlini@oracle.com> PR c++/79180 * g++.dg/cpp0x/lambda/lambda-nested8.C: New. * g++.dg/torture/pr79180.C: Likewise. PR c++/71386 * g++.dg/cpp1y/lambda-generic-nested1.C: New. Added: trunk/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested8.C trunk/gcc/testsuite/g++.dg/cpp1y/lambda-generic-nested1.C trunk/gcc/testsuite/g++.dg/torture/pr79180.C Modified: trunk/gcc/testsuite/ChangeLog
Fixed in trunk, I added testcases.