===================================================================
@@ -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.
===================================================================
@@ -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);
===================================================================
@@ -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;
===================================================================
@@ -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
===================================================================
@@ -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.
===================================================================
@@ -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
===================================================================
@@ -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
===================================================================
@@ -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;
+}
===================================================================
@@ -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;
+}
===================================================================
@@ -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" } */
+}
===================================================================
@@ -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
===================================================================
@@ -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>:
===================================================================
@@ -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)
===================================================================
@@ -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