Hi,

The principle of Objective-c/c++ is that they should be supersets of the parent 
language.  Thus, it is intended that valid c++ (or c) should be parsed by the 
relevant objective-c/c++ FE.

While trying to build some external code, I found that lambdas confuse things 
at present for objcp.

When we find "[" and we're in objcp mode, and the "[" introduces a lambda, we 
try to parse a message expression and if that fails we punt (thus we are unable 
to recognise lambdas).

The attached patch tries "[" as a message expression introducer, if that fails 
it drops through to try for a lambda (no change intended for the 
non-objective-c++ path).

I guess it's a bit of a nuisance that the diagnostics from a failed message 
expression are likely to end up as mentioning a lambda.  Perhaps we might 
decide to punt early if we are both ObjC and < c++11.

This allows me to parse some necessary lldb headers with gcc objcp.

Thoughts / OK for trunk?
(I can raise a formal PR if you like).

Iain

gcc/cp:
        * parser.c (cp_parser_primary_expression): If parsing an objective-c++ 
message
        expression fails, see if a lambda is present.
        (cp_parser_objc_message_reciever): Don't assume that if a message 
reciever expression
        fails it is a hard error.

gcc/testsuite:
        * obj-c++.dg/lambda-0.mm New file.
        * obj-c++.dg/lambda-1.mm New file.

From e8038ba3cb16095e53d09e23ff15f4682cb5bd0c Mon Sep 17 00:00:00 2001
From: Iain Sandoe <i...@codesourcery.com>
Date: Mon, 22 Dec 2014 10:50:45 +0000
Subject: [PATCH] Modify objective-c++ parse to check for lambdas when a
 message construct isn't matched after a [

---
 gcc/cp/parser.c                            | 21 +++++++++++++++++----
 gcc/testsuite/obj-c++.dg/lambda-0.mm       | 22 ++++++++++++++++++++++
 gcc/testsuite/obj-c++.dg/lambda-1.mm       | 13 +++++++++++++
 gcc/testsuite/obj-c++.dg/syntax-error-6.mm |  5 ++++-
 4 files changed, 56 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/obj-c++.dg/lambda-0.mm
 create mode 100644 gcc/testsuite/obj-c++.dg/lambda-1.mm

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8ff16ed..1409bef 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4441,10 +4441,17 @@ cp_parser_primary_expression (cp_parser *parser,
       }
 
     case CPP_OPEN_SQUARE:
-      if (c_dialect_objc ())
-        /* We have an Objective-C++ message. */
-        return cp_parser_objc_expression (parser);
       {
+       if (c_dialect_objc ())
+         {
+           /* We might have an Objective-C++ message. */
+           cp_parser_parse_tentatively (parser);
+           tree msg = cp_parser_objc_message_expression (parser);
+           /* If that works out, we're done ... */
+           if (cp_parser_parse_definitely (parser))
+             return msg;
+           /* ... else, fall though to see if it's a lambda.  */
+         }
        tree lam = cp_parser_lambda_expression (parser);
        /* Don't warn about a failed tentative parse.  */
        if (cp_parser_error_occurred (parser))
@@ -25630,14 +25637,20 @@ cp_parser_objc_message_receiver (cp_parser* parser)
   cp_parser_parse_tentatively (parser);
   rcv = cp_parser_expression (parser);
 
+  /* If that worked out, fine.  */
   if (cp_parser_parse_definitely (parser))
     return rcv;
 
+  cp_parser_parse_tentatively (parser);
   rcv = cp_parser_simple_type_specifier (parser,
                                         /*decl_specs=*/NULL,
                                         CP_PARSER_FLAGS_NONE);
 
-  return objc_get_class_reference (rcv);
+  if (cp_parser_parse_definitely (parser))
+    return objc_get_class_reference (rcv);
+  
+  cp_parser_error (parser, "objective-c++ message receiver expected");
+  return error_mark_node;
 }
 
 /* Parse the arguments and selectors comprising an Objective-C message.
diff --git a/gcc/testsuite/obj-c++.dg/lambda-0.mm 
b/gcc/testsuite/obj-c++.dg/lambda-0.mm
new file mode 100644
index 0000000..41482fd
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/lambda-0.mm
@@ -0,0 +1,22 @@
+// Contributed by Iain Sandoe <i...@codesourcery.com>, December 2014.  */
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+
+template<class Function>
+Function thing(Function fn, int a)
+{
+  fn(a);
+  return fn;
+}
+
+int
+test (int *arr, unsigned n)
+{
+  int total = 0;
+  for (unsigned i=0; i<n; i++) {
+    int a = arr[i];
+    thing ([&total] (int a) { total += a; }, a);
+  }
+  return total;
+}
diff --git a/gcc/testsuite/obj-c++.dg/lambda-1.mm 
b/gcc/testsuite/obj-c++.dg/lambda-1.mm
new file mode 100644
index 0000000..050d68d
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/lambda-1.mm
@@ -0,0 +1,13 @@
+// Contributed by Iain Sandoe <i...@codesourcery.com>, December 2014.  */
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+extern "C" {
+  int printf (const char *,...);
+}
+
+int main () 
+{
+  auto f = [] (const char *msg) -> int { printf("%s", msg); return 0; };
+  return f("Some test\n");
+}
diff --git a/gcc/testsuite/obj-c++.dg/syntax-error-6.mm 
b/gcc/testsuite/obj-c++.dg/syntax-error-6.mm
index 21423ec..36a444f 100644
--- a/gcc/testsuite/obj-c++.dg/syntax-error-6.mm
+++ b/gcc/testsuite/obj-c++.dg/syntax-error-6.mm
@@ -8,5 +8,8 @@ void FOO()
 {
   NSButton * mCopyAcrobatCB; 
        
-  [ [ mCopyAcrobatCB state ] == 0 ] != 1;  /* { dg-error "objective\\-c\\+\\+" 
} */
+  [ [ mCopyAcrobatCB state ] == 0 ] != 1;  /* { dg-error "expected identifier 
before ... token" } */
+/* { dg-error "expected \\\'\\\{\\\' before \\\'!=\\\' token" "" { target 
*-*-* } 11 } */
+/* { dg-error "lambda expressions only available with" "" { target *-*-* } 11 
} */
+/* { dg-error "no match for \\\'operator!=\\\' in" "" { target *-*-* } 11 } */
 }
-- 
1.8.4.2


Reply via email to