Bug 71946 - asm in toplevel lambda function rejected
Summary: asm in toplevel lambda function rejected
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 5.4.0
: P3 normal
Target Milestone: 8.0
Assignee: Not yet assigned to anyone
URL:
Keywords: c++-lambda, rejects-valid
: 83769 (view as bug list)
Depends on:
Blocks: lambdas
  Show dependency treegraph
 
Reported: 2016-07-20 09:45 UTC by James Ruan
Modified: 2022-03-11 00:32 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-07-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description James Ruan 2016-07-20 09:45:56 UTC
#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);
  ^
Comment 1 Martin Liška 2016-07-20 10:30:49 UTC
Confirmed, all GCC releases supporting -std=c++ are affected.
ICC and clang++ accept the code snippet.
Comment 2 Andrew Pinski 2016-07-21 06:00:50 UTC
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"
                    ;
Comment 3 Andrew Pinski 2016-07-21 06:02:32 UTC
Looks like x86 has a special select.h in glibc :).
Comment 4 Andrew Pinski 2016-07-21 06:08:13 UTC
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 ...
Comment 5 Andrew Pinski 2016-07-21 06:11:05 UTC
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.
Comment 6 Andrew Pinski 2016-07-21 06:15:59 UTC
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).
Comment 7 Paolo Carlini 2017-10-04 10:32:55 UTC
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
Comment 8 paolo@gcc.gnu.org 2017-10-04 17:21:53 UTC
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
Comment 9 Paolo Carlini 2017-10-04 17:23:28 UTC
Fixed.
Comment 10 Andrew Pinski 2018-01-10 16:54:35 UTC
*** Bug 83769 has been marked as a duplicate of this bug. ***