Patchwork ObjC/ObjC++ - fix Objective-C 2.0 dotsyntax with class names

login
register
mail settings
Submitter Nicola Pero
Date Nov. 3, 2010, 11:53 p.m.
Message ID <1288828380.056432389@192.168.2.229>
Download mbox | patch
Permalink /patch/70091/
State New
Headers show

Comments

Nicola Pero - Nov. 3, 2010, 11:53 p.m.
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  <nicola.pero@meta-innovation.com>

        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  <nicola.pero@meta-innovation.com>

        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  <nicola.pero@meta-innovation.com>

        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  <nicola.pero@meta-innovation.com>

        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  <nicola.pero@meta-innovation.com>

        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.
Mike Stump - Nov. 4, 2010, 11:45 a.m.
On Nov 3, 2010, at 4:53 PM, Nicola Pero wrote:
> Ok to commit ?

Ok.

Patch

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  <nicola.pero@meta-innovation.com>
+
+	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  <nicola.pero@meta-innovation.com>
 
 	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  <nicola.pero@meta-innovation.com>
+
+	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  <nicola.pero@meta-innovation.com>
 
 	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  <nicola.pero@meta-innovation.com>
+
+	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  <jakub@redhat.com>
 
 	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  <nicola.pero@meta-innovation.com>
+
+	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  <rguenther@suse.de>
 
 	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 <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+
+/* Test the 'dot syntax' without a declarated property.  This tests the case where
+   the object is a Class.  */
+
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+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 <nicola.pero@meta-innovation.com>, 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 <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+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  <nicola.pero@meta-innovation.com>
+
+	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  <dodji@redhat.com>
 
 	* cp-tree.h (enum tsubst_flags)<tf_no_class_instantiations>:
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