From patchwork Wed Nov 3 23:53:00 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 70091 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 43BBAB70A9 for ; Thu, 4 Nov 2010 10:53:19 +1100 (EST) Received: (qmail 11203 invoked by alias); 3 Nov 2010 23:53:16 -0000 Received: (qmail 11193 invoked by uid 22791); 3 Nov 2010 23:53:14 -0000 X-SWARE-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL, BAYES_00, TW_BJ, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (140.186.70.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 03 Nov 2010 23:53:07 +0000 Received: from eggs.gnu.org ([140.186.70.92]:60256) by fencepost.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1PDn8Z-0000ln-R0 for gcc-patches@gnu.org; Wed, 03 Nov 2010 19:53:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PDn8X-0006lu-TD for gcc-patches@gnu.org; Wed, 03 Nov 2010 19:53:04 -0400 Received: from smtp201.iad.emailsrvr.com ([207.97.245.201]:51467) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PDn8X-0006lq-P5 for gcc-patches@gnu.org; Wed, 03 Nov 2010 19:53:01 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp40.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 0D9303503FF for ; Wed, 3 Nov 2010 19:53:01 -0400 (EDT) Received: from dynamic5.wm-web.iad.mlsrvr.com (dynamic5.wm-web.iad1a.rsapps.net [192.168.2.146]) by smtp40.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 29EEE3501E1 for ; Wed, 3 Nov 2010 19:53:00 -0400 (EDT) Received: from meta-innovation.com (localhost [127.0.0.1]) by dynamic5.wm-web.iad.mlsrvr.com (Postfix) with ESMTP id 0E7D08D0505 for ; Wed, 3 Nov 2010 19:53:00 -0400 (EDT) Received: by www2.webmail.us (Authenticated sender: nicola.pero@meta-innovation.com, from: nicola.pero@meta-innovation.com) with HTTP; Thu, 4 Nov 2010 00:53:00 +0100 (CET) Date: Thu, 4 Nov 2010 00:53:00 +0100 (CET) Subject: ObjC/ObjC++ - fix Objective-C 2.0 dotsyntax with class names From: "Nicola Pero" To: "gcc-patches@gnu.org" MIME-Version: 1.0 X-Type: plain Message-ID: <1288828380.056432389@192.168.2.229> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org It was brought to my attention our Objective-C 2.0 dot-syntax implementation for accessors didn't work with class names (eg, NSObject.class). :-( Class names are tricky because they normally start a declaration, but in this context we need to accept them as starting the Objective-C 2.0 dot-syntax, which we didn't. This patches fixes this for both Objective-C and Objective-C++. 4 testcases are included. Ok to commit ? Thanks In gcc/: 2010-11-04 Nicola Pero Fixed using the Objective-C 2.0 dot-syntax with class names. * c-parser.c (c_parser_next_token_starts_declspecs): In Objective-C, detect Objective-C 2.0 dot-syntax with a class name. (c_parser_next_token_starts_declaration): Same. (c_parser_postfix_expression): Parse the Objective-C 2.0 dot-syntax with a class name. In gcc/cp/: 2010-11-04 Nicola Pero Fixed using the Objective-C 2.0 dot-syntax with class names. * parser.c (cp_parser_primary_expression): Recognize Objective-C 2.0 dot-syntax with class names and process it. (cp_parser_nonclass_name): Recognize Objective-C 2.0 dot-syntax with class names. (cp_parser_class_name): Same change. (cp_parser_simple_type_specifier): Tidied comments. In gcc/c-family/: 2010-11-04 Nicola Pero Fixed using the Objective-C 2.0 dot-syntax with class names. * c-common.h (objc_build_class_component_ref): New. * stub-objc.c (objc_build_class_component_ref): New. In gcc/objc/: 2010-11-04 Nicola Pero Fixed using the Objective-C 2.0 dot-syntax with class names. * objc-act.c (objc_build_class_component_ref): New. In gcc/testsuite/: 2010-11-04 Nicola Pero Fixed using the Objective-C 2.0 dot-syntax with class names. * objc.dg/property/dotsyntax-3.m: New. * objc.dg/property/dotsyntax-4.m: New. * obj-c++.dg/property/dotsyntax-3.mm: New. * obj-c++.dg/property/dotsyntax-4.mm: New. * objc.dg/fobjc-std-1.m: Added test for warnings when the Objective-C 2.0 dot-syntax is used with class names. * obj-c++.dg/fobjc-std-1.mm: Same change. Index: gcc/c-family/ChangeLog =================================================================== --- gcc/c-family/ChangeLog (revision 166257) +++ gcc/c-family/ChangeLog (working copy) @@ -1,3 +1,9 @@ +2010-11-04 Nicola Pero + + Fixed using the Objective-C 2.0 dot-syntax with class names. + * c-common.h (objc_build_class_component_ref): New. + * stub-objc.c (objc_build_class_component_ref): New. + 2010-11-03 Nicola Pero Implemented -fobjc-std=objc1 flag. Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 166257) +++ gcc/c-family/c-common.h (working copy) @@ -1037,6 +1037,7 @@ extern bool objc_method_decl (enum tree_code); extern void objc_add_property_declaration (location_t, tree, bool, bool, bool, bool, bool, bool, tree, tree); extern tree objc_maybe_build_component_ref (tree, tree); +extern tree objc_build_class_component_ref (tree, tree); extern tree objc_maybe_build_modify_expr (tree, tree); extern void objc_add_synthesize_declaration (location_t, tree); extern void objc_add_dynamic_declaration (location_t, tree); Index: gcc/c-family/stub-objc.c =================================================================== --- gcc/c-family/stub-objc.c (revision 166257) +++ gcc/c-family/stub-objc.c (working copy) @@ -350,6 +350,12 @@ objc_maybe_build_component_ref (tree ARG_UNUSED (d } tree +objc_build_class_component_ref (tree ARG_UNUSED (datum), tree ARG_UNUSED (component)) +{ + return 0; +} + +tree objc_maybe_build_modify_expr (tree ARG_UNUSED (lhs), tree ARG_UNUSED (rhs)) { return 0; Index: gcc/objc/objc-act.c =================================================================== --- gcc/objc/objc-act.c (revision 166257) +++ gcc/objc/objc-act.c (working copy) @@ -1297,6 +1297,79 @@ objc_maybe_build_component_ref (tree object, tree return NULL_TREE; } +/* This hook routine is invoked by the parser when an expression such + as 'xxx.yyy' is parsed, and 'xxx' is a class name. This is the + Objective-C 2.0 dot-syntax applied to classes, so we need to + convert it into a setter/getter call on the class. */ +tree +objc_build_class_component_ref (tree class_name, tree property_ident) +{ + tree x = NULL_TREE; + tree object, rtype; + + if (flag_objc1_only) + error_at (input_location, "the dot syntax is not available in Objective-C 1.0"); + + if (class_name == NULL_TREE || class_name == error_mark_node + || TREE_CODE (class_name) != IDENTIFIER_NODE) + return error_mark_node; + + if (property_ident == NULL_TREE || property_ident == error_mark_node + || TREE_CODE (property_ident) != IDENTIFIER_NODE) + return NULL_TREE; + + object = objc_get_class_reference (class_name); + if (!object) + { + /* We know that 'class_name' is an Objective-C class name as the + parser won't call this function if it is not. This is only a + double-check for safety. */ + error_at (input_location, "could not find class %qE", class_name); + return error_mark_node; + } + + rtype = lookup_interface (class_name); + if (!rtype) + { + /* Again, this should never happen, but we do check. */ + error_at (input_location, "could not find interface for class %qE", class_name); + return error_mark_node; + } + + x = maybe_make_artificial_property_decl (rtype, NULL_TREE, + property_ident, + true); + + if (x) + { + tree expression; + + if (TREE_DEPRECATED (x)) + warn_deprecated_use (x, NULL_TREE); + + expression = build2 (PROPERTY_REF, TREE_TYPE(x), object, x); + SET_EXPR_LOCATION (expression, input_location); + TREE_SIDE_EFFECTS (expression) = 1; + /* See above for why we do this. */ + if (!PROPERTY_HAS_NO_GETTER (x)) + objc_finish_message_expr (object, + PROPERTY_GETTER_NAME (x), + NULL_TREE); + + return expression; + } + else + { + error_at (input_location, "could not find setter/getter for %qE in class %qE", + property_ident, class_name); + return error_mark_node; + } + + return NULL_TREE; +} + + + /* This is used because we don't want to expose PROPERTY_REF to the C/C++ frontends. Maybe we should! */ bool Index: gcc/objc/ChangeLog =================================================================== --- gcc/objc/ChangeLog (revision 166257) +++ gcc/objc/ChangeLog (working copy) @@ -1,3 +1,8 @@ +2010-11-04 Nicola Pero + + Fixed using the Objective-C 2.0 dot-syntax with class names. + * objc-act.c (objc_build_class_component_ref): New. + 2010-11-03 Nicola Pero Implemented -fobjc-std=objc1 flag. Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (revision 166257) +++ gcc/ChangeLog (working copy) @@ -1,3 +1,12 @@ +2010-11-04 Nicola Pero + + Fixed using the Objective-C 2.0 dot-syntax with class names. + * c-parser.c (c_parser_next_token_starts_declspecs): In + Objective-C, detect Objective-C 2.0 dot-syntax with a class name. + (c_parser_next_token_starts_declaration): Same. + (c_parser_postfix_expression): Parse the Objective-C 2.0 + dot-syntax with a class name. + 2010-11-03 Jakub Jelinek PR tree-optimization/46009 Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (revision 166257) +++ gcc/testsuite/ChangeLog (working copy) @@ -1,3 +1,15 @@ +2010-11-04 Nicola Pero + + Fixed using the Objective-C 2.0 dot-syntax with class names. + * objc.dg/property/dotsyntax-3.m: New. + * objc.dg/property/dotsyntax-4.m: New. + * obj-c++.dg/property/dotsyntax-3.mm: New. + * obj-c++.dg/property/dotsyntax-4.mm: New. + + * objc.dg/fobjc-std-1.m: Added test for warnings when the + Objective-C 2.0 dot-syntax is used with class names. + * obj-c++.dg/fobjc-std-1.mm: Same change. + 2010-11-03 Richard Guenther PR tree-optimization/44807 Index: gcc/testsuite/objc.dg/property/dotsyntax-3.m =================================================================== --- gcc/testsuite/objc.dg/property/dotsyntax-3.m (revision 0) +++ gcc/testsuite/objc.dg/property/dotsyntax-3.m (revision 0) @@ -0,0 +1,63 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ + +/* Test the 'dot syntax' without a declarated property. This tests the case where + the object is a Class. */ + + +#include +#include +#include + +static int a; +static id b; + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; ++ (int) count; ++ (void) setCount: (int)value; ++ (id) next; ++ (void) setNext: (id)value; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } ++ (int) count +{ + return a; +} ++ (void) setCount: (int)value +{ + a = value; +} ++ (id) next +{ + return b; +} ++ (void) setNext: (id)value +{ + b = value; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + MyRootClass.count = 40; + if (MyRootClass.count != 40) + abort (); + + MyRootClass.next = object; + if (MyRootClass.next != object) + abort (); + + return 0; +} Index: gcc/testsuite/objc.dg/property/dotsyntax-4.m =================================================================== --- gcc/testsuite/objc.dg/property/dotsyntax-4.m (revision 0) +++ gcc/testsuite/objc.dg/property/dotsyntax-4.m (revision 0) @@ -0,0 +1,67 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test the 'dot syntax' without a declarated property. This tests + syntax errors in the case where the object is a Class. */ + + +#include +#include +#include + +static int a; +static id b; + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; ++ (int) count; ++ (void) setCount: (int)value; ++ (id) next; ++ (void) setNext: (id)value; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } ++ (int) count +{ + return a; +} ++ (void) setCount: (int)value +{ + a = value; +} ++ (id) next +{ + return b; +} ++ (void) setNext: (id)value +{ + b = value; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + MyRootClass.invalid = 40; /* { dg-error "could not find setter.getter" } */ + if (MyRootClass.invalid != 40) /* { dg-error "could not find setter.getter" } */ + abort (); + + MyRootClass.; /* { dg-error "expected identifier" } */ + if (MyRootClass.) /* { dg-error "expected identifier" } */ + abort (); + + MyRootClass.int; /* { dg-error "expected identifier" } */ + if (MyRootClass.int) /* { dg-error "expected identifier" } */ + abort (); + + return 0; +} Index: gcc/testsuite/objc.dg/fobjc-std-1.m =================================================================== --- gcc/testsuite/objc.dg/fobjc-std-1.m (revision 166257) +++ gcc/testsuite/objc.dg/fobjc-std-1.m (working copy) @@ -13,6 +13,7 @@ __attribute__ ((deprecated)) int b; } + (id) alloc __attribute__ ((deprecated)); /* { dg-error "not available in Objective.C 1.0" } */ ++ (id) name; - (id) init; - (id) testMe: (id) __attribute__((unused)) argument; /* { dg-error "not available in Objective.C 1.0" } */ @property (nonatomic) int a; /* { dg-error "not available in Objective.C 1.0" } */ @@ -21,6 +22,7 @@ __attribute__ ((deprecated)) @implementation MyRootClass + (id) alloc { return self; } ++ (id) name { return self; } - (id) init { return self; } - (id) testMe: (id) __attribute__((unused)) argument { return self; } /* { dg-error "not available in Objective.C 1.0" } */ @synthesize a; /* { dg-error "not available in Objective.C 1.0" } */ @@ -52,3 +54,8 @@ int array_length (NSArray *array) return i; } + +id test (void) +{ + return MyRootClass.name; /* { dg-error "not available in Objective.C 1.0" } */ +} Index: gcc/testsuite/obj-c++.dg/fobjc-std-1.mm =================================================================== --- gcc/testsuite/obj-c++.dg/fobjc-std-1.mm (revision 166257) +++ gcc/testsuite/obj-c++.dg/fobjc-std-1.mm (working copy) @@ -13,6 +13,7 @@ __attribute__ ((deprecated)) int b; } + (id) alloc __attribute__ ((deprecated)); /* { dg-error "not available in Objective.C 1.0" } */ ++ (id) name; - (id) init; - (id) testMe: (id) __attribute__((unused)) argument; /* { dg-error "not available in Objective.C 1.0" } */ @property (nonatomic) int a; /* { dg-error "not available in Objective.C 1.0" } */ @@ -21,6 +22,7 @@ __attribute__ ((deprecated)) @implementation MyRootClass + (id) alloc { return self; } ++ (id) name { return self; } - (id) init { return self; } - (id) testMe: (id) __attribute__((unused)) argument { return self; } /* { dg-error "not available in Objective.C 1.0" } */ @synthesize a; /* { dg-error "not available in Objective.C 1.0" } */ @@ -52,4 +54,9 @@ int array_length (NSArray *array) return i; } -#endif \ No newline at end of file +#endif + +id test (void) +{ + return MyRootClass.name; /* { dg-error "not available in Objective.C 1.0" } */ +} \ No newline at end of file Index: gcc/cp/ChangeLog =================================================================== --- gcc/cp/ChangeLog (revision 166257) +++ gcc/cp/ChangeLog (working copy) @@ -1,3 +1,13 @@ +2010-11-04 Nicola Pero + + Fixed using the Objective-C 2.0 dot-syntax with class names. + * parser.c (cp_parser_primary_expression): Recognize Objective-C + 2.0 dot-syntax with class names and process it. + (cp_parser_nonclass_name): Recognize Objective-C 2.0 dot-syntax + with class names. + (cp_parser_class_name): Same change. + (cp_parser_simple_type_specifier): Tidied comments. + 2010-11-02 Dodji Seketeli * cp-tree.h (enum tsubst_flags): Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 166257) +++ gcc/cp/parser.c (working copy) @@ -3908,6 +3908,22 @@ cp_parser_primary_expression (cp_parser *parser, if (ambiguous_decls) return error_mark_node; + /* In Objective-C++, we may have an Objective-C 2.0 + dot-syntax for classes here. */ + if (c_dialect_objc () + && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT + && TREE_CODE (decl) == TYPE_DECL + && objc_is_class_name (decl)) + { + tree component; + cp_lexer_consume_token (parser->lexer); + component = cp_parser_identifier (parser); + if (component == error_mark_node) + return error_mark_node; + + return objc_build_class_component_ref (id_expression, component); + } + /* In Objective-C++, an instance variable (ivar) may be preferred to whatever cp_parser_lookup_name() found. */ decl = objc_lookup_ivar (decl, id_expression); @@ -12786,14 +12802,14 @@ cp_parser_simple_type_specifier (cp_parser* parser return error_mark_node; } - /* There is no valid C++ program where a non-template type is - followed by a "<". That usually indicates that the user thought - that the type was a template. */ if (type && type != error_mark_node) { - /* As a last-ditch effort, see if TYPE is an Objective-C type. - If it is, then the '<'...'>' enclose protocol names rather than - template arguments, and so everything is fine. */ + /* See if TYPE is an Objective-C type, and if so, parse and + accept any protocol references following it. Do this before + the cp_parser_check_for_invalid_template_id() call, because + Objective-C types can be followed by '<...>' which would + enclose protocol names rather than template arguments, and so + everything is fine. */ if (c_dialect_objc () && !parser->scope && (objc_is_id (type) || objc_is_class_name (type))) { @@ -12808,6 +12824,9 @@ cp_parser_simple_type_specifier (cp_parser* parser return qual_type; } + /* There is no valid C++ program where a non-template type is + followed by a "<". That usually indicates that the user + thought that the type was a template. */ cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type), token->location); } @@ -12888,9 +12907,17 @@ cp_parser_nonclass_name (cp_parser* parser) if (type) type_decl = TYPE_NAME (type); } - + /* Issue an error if we did not find a type-name. */ - if (TREE_CODE (type_decl) != TYPE_DECL) + if (TREE_CODE (type_decl) != TYPE_DECL + /* In Objective-C, we have the complication that class names are + normally type names and start declarations (eg, the + "NSObject" in "NSObject *object;"), but can be used in an + Objective-C 2.0 dot-syntax (as in "NSObject.version") which + is an expression. So, a classname followed by a dot is not a + valid type-name. */ + || (objc_is_class_name (TREE_TYPE (type_decl)) + && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT)) { if (!cp_parser_simulate_error (parser)) cp_parser_name_lookup_error (parser, identifier, type_decl, @@ -16714,7 +16741,12 @@ cp_parser_class_name (cp_parser *parser, } else if (TREE_CODE (decl) != TYPE_DECL || TREE_TYPE (decl) == error_mark_node - || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))) + || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl)) + /* In Objective-C 2.0, a classname followed by '.' starts a + dot-syntax expression, and it's not a type-name. */ + || (c_dialect_objc () + && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT + && objc_is_class_name (decl))) decl = error_mark_node; if (decl == error_mark_node) Index: gcc/c-parser.c =================================================================== --- gcc/c-parser.c (revision 166257) +++ gcc/c-parser.c (working copy) @@ -598,6 +598,19 @@ static inline bool c_parser_next_token_starts_declspecs (c_parser *parser) { c_token *token = c_parser_peek_token (parser); + + /* In Objective-C, a classname normally starts a declspecs unless it + is immediately followed by a dot. In that case, it is the + Objective-C 2.0 "dot-syntax" for class objects, ie, calls the + setter/getter on the class. c_token_starts_declspecs() can't + differentiate between the two cases because it only checks the + current token, so we have a special check here. */ + if (c_dialect_objc () + && token->type == CPP_NAME + && token->id_kind == C_ID_CLASSNAME + && c_parser_peek_2nd_token (parser)->type == CPP_DOT) + return false; + return c_token_starts_declspecs (token); } @@ -607,6 +620,14 @@ static inline bool c_parser_next_token_starts_declaration (c_parser *parser) { c_token *token = c_parser_peek_token (parser); + + /* Same as above. */ + if (c_dialect_objc () + && token->type == CPP_NAME + && token->id_kind == C_ID_CLASSNAME + && c_parser_peek_2nd_token (parser)->type == CPP_DOT) + return false; + return c_token_starts_declaration (token); } @@ -5821,6 +5842,7 @@ c_parser_alignof_expression (c_parser *parser) @protocol ( identifier ) @encode ( type-name ) objc-string-literal + Classname . identifier */ static struct c_expr @@ -5867,20 +5889,48 @@ c_parser_postfix_expression (c_parser *parser) c_parser_consume_token (parser); break; case CPP_NAME: - if (c_parser_peek_token (parser)->id_kind != C_ID_ID) + switch (c_parser_peek_token (parser)->id_kind) { + case C_ID_ID: + { + tree id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + expr.value = build_external_ref (loc, id, + (c_parser_peek_token (parser)->type + == CPP_OPEN_PAREN), + &expr.original_type); + break; + } + case C_ID_CLASSNAME: + { + /* Here we parse the Objective-C 2.0 Class.name dot + syntax. */ + tree class_name = c_parser_peek_token (parser)->value; + tree component; + c_parser_consume_token (parser); + gcc_assert (c_dialect_objc ()); + if (!c_parser_require (parser, CPP_DOT, "expected %<.%>")) + { + expr.value = error_mark_node; + break; + } + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + expr.value = error_mark_node; + break; + } + component = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + expr.value = objc_build_class_component_ref (class_name, + component); + break; + } + default: c_parser_error (parser, "expected expression"); expr.value = error_mark_node; break; } - { - tree id = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - expr.value = build_external_ref (loc, id, - (c_parser_peek_token (parser)->type - == CPP_OPEN_PAREN), - &expr.original_type); - } break; case CPP_OPEN_PAREN: /* A parenthesized expression, statement expression or compound