#include <sys/select.h> #include <functional> std::function<void(void)> test = []{ fd_set set; FD_ZERO(&set); }; g++ -std=c++11 a.cpp In file included from /usr/include/x86_64-linux-gnu/sys/select.h:30:0, from a.cpp:1: a.cpp: In lambda function: a.cpp:6:2: error: expected ‘)’ before ‘:’ token FD_ZERO(&set); ^
Confirmed, all GCC releases supporting -std=c++ are affected. ICC and clang++ accept the code snippet.
Works for me on aarch64-linux-gnu with: GNU C++14 (GCC) version 7.0.0 20160717 (experimental) (aarch64-unknown-linux-gnu) Maybe provide a preprocessed source which fails. For me it expands to: # 6 "t.c" 3 4 do { unsigned int __i; fd_set *__arr = ( # 6 "t.c" &set # 6 "t.c" 3 4 ); for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr)->fds_bits)[__i] = 0; } while (0) # 6 "t.c" ;
Looks like x86 has a special select.h in glibc :).
Yep # if __WORDSIZE == 64 # define __FD_ZERO_STOS "stosq" # else # define __FD_ZERO_STOS "stosl" # endif # define __FD_ZERO(fdsp) \ do { \ int __d0, __d1; \ __asm__ __volatile__ ("cld; rep; " __FD_ZERO_STOS \ : "=c" (__d0), "=D" (__d1) \ : "a" (0), "0" (sizeof (fd_set) \ / sizeof (__fd_mask)), \ "1" (&__FDS_BITS (fdsp)[0]) \ : "memory"); \ } while (0) Reducing now ...
Reduced testcase: auto test = []{ __asm__ __volatile__ ("" : : "r" (0) ); }; Looks like the C++ front-end is parsing the inline-asm as a toplevel inline-asm and rejecting extended inline-asm.
I suspect parser->in_function_body is not being set in lambda functions. Most likely because statement expressions are also rejected for the same reason: auto test = []{ int t = ({ int t1; t1 = 0; t1; }); } (I found the testcase above by reading the C++ front-end parser code).
I believe Andrew is right, it's just matter of setting the flag. The below passes all my tests so far: Index: parser.c =================================================================== --- parser.c (revision 253396) +++ parser.c (working copy) @@ -10557,6 +10557,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lam { bool nested = (current_function_decl != NULL_TREE); bool local_variables_forbidden_p = parser->local_variables_forbidden_p; + bool in_function_body = parser->in_function_body; if (nested) push_function_context (); else @@ -10567,6 +10568,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lam save_omp_privatization_clauses (omp_privatization_save); /* Clear this in case we're in the middle of a default argument. */ parser->local_variables_forbidden_p = false; + parser->in_function_body = true; /* Finish the function call operator - class_specifier @@ -10653,6 +10655,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lam restore_omp_privatization_clauses (omp_privatization_save); parser->local_variables_forbidden_p = local_variables_forbidden_p; + parser->in_function_body = in_function_body; if (nested) pop_function_context(); else
Author: paolo Date: Wed Oct 4 17:21:21 2017 New Revision: 253423 URL: https://gcc.gnu.org/viewcvs?rev=253423&root=gcc&view=rev Log: /cp 2017-10-04 Paolo Carlini <paolo.carlini@oracle.com> Andrew Pinski <apinski@cavium.com> PR c++/71946 * parser.c (cp_parser_lambda_body): Set parser->in_function_body. /testsuite 2017-10-04 Paolo Carlini <paolo.carlini@oracle.com> Andrew Pinski <apinski@cavium.com> PR c++/71946 * g++.dg/cpp0x/lambda/lambda-asm1.C: New. * g++.dg/cpp0x/lambda/lambda-stmtexpr1.C: Likewise. Added: trunk/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-asm1.C trunk/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-stmtexpr1.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/parser.c trunk/gcc/testsuite/ChangeLog
Fixed.
*** Bug 83769 has been marked as a duplicate of this bug. ***