summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshebs <shebs@138bc75d-0d04-0410-961f-82ee72b054a4>2001-08-01 08:10:00 +0000
committershebs <shebs@138bc75d-0d04-0410-961f-82ee72b054a4>2001-08-01 08:10:00 +0000
commitb11c01151739961c0ed6cc811ae3af14fa83821a (patch)
tree648dd272baeb69450a07f51b1c4e7565b12eafb1
parent50cf64b79d5e01b075aaa2baf4c731b02aea0249 (diff)
downloadgcc-b11c01151739961c0ed6cc811ae3af14fa83821a.tar.gz
2001-08-01 Ziemowit Laski <zlaski@apple.com>
* c-parse.in (OBJC_NEED_RAW_IDENTIFIER): Define macro and flag for contextualizing Objective-C class name lookup by the lexer. (typespec_reserved_nonattr): Disable ObjC class name lookup after seeing a TYPESPEC. (protocoldef): Add support for forward @protocol declarations. (yylexname): Suppress ObjC class name lookup in certain contexts; re-enable after lookup is complete. (_yylex): Re-enable ObjC class name lookup when certain punctuation marks are seen. * objc/objc-act.c (check_protocol_recursively): New function used for finding circular dependencies in protocols. (objc_declare_protocols): New function for handling forward @protocol declarations. (receiver_is_class_object): Detect the case when 'self' is used inside of a class method. (build_message_expr): Issue a warning if class method is desired but instance method is found instead. (conforms_to_protocol): Streamline. (objc_comptypes): Detect the fact that 'Bar<Foo> foo' conforms to protocol Foo, even if 'Bar foo' does not. (check_protocols): Streamline. (start_protocol): Add checks for circular and duplicate protocol definitions. (encode_aggregate_within): For typedefs of structs, encode the underlying struct. * objc/objc-act.h (PROTOCOL_DEFINED): New tree accessor. (objc_declare_protocols): New prototype. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44536 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog31
-rw-r--r--gcc/c-parse.in70
-rw-r--r--gcc/objc/objc-act.c234
-rw-r--r--gcc/objc/objc-act.h4
4 files changed, 263 insertions, 76 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 857a75db7d5..01ef78a5bef 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,34 @@
+2001-08-01 Ziemowit Laski <zlaski@apple.com>
+
+ * c-parse.in (OBJC_NEED_RAW_IDENTIFIER): Define macro and flag for
+ contextualizing Objective-C class name lookup by the lexer.
+ (typespec_reserved_nonattr): Disable ObjC class name lookup after
+ seeing a TYPESPEC.
+ (protocoldef): Add support for forward @protocol declarations.
+ (yylexname): Suppress ObjC class name lookup in certain contexts;
+ re-enable after lookup is complete.
+ (_yylex): Re-enable ObjC class name lookup when certain
+ punctuation marks are seen.
+
+ * objc/objc-act.c (check_protocol_recursively): New function used
+ for finding circular dependencies in protocols.
+ (objc_declare_protocols): New function for handling forward
+ @protocol declarations.
+ (receiver_is_class_object): Detect the case when 'self' is used
+ inside of a class method.
+ (build_message_expr): Issue a warning if class method is desired
+ but instance method is found instead.
+ (conforms_to_protocol): Streamline.
+ (objc_comptypes): Detect the fact that 'Bar<Foo> foo' conforms to
+ protocol Foo, even if 'Bar foo' does not.
+ (check_protocols): Streamline.
+ (start_protocol): Add checks for circular and duplicate protocol
+ definitions.
+ (encode_aggregate_within): For typedefs of structs, encode the
+ underlying struct.
+ * objc/objc-act.h (PROTOCOL_DEFINED): New tree accessor.
+ (objc_declare_protocols): New prototype.
+
2001-08-01 Neil Booth <neil@cat.daikokuya.demon.co.uk>
* cpphash.h (struct cpp_reader): New members line, pseudo_newlines.
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index 7d87e2004fd..d1320565bfc 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -29,10 +29,10 @@ Boston, MA 02111-1307, USA. */
written by AT&T, but I have never seen it. */
ifobjc
-%expect 31
+%expect 31 /* shift/reduce conflicts, and 1 reduce/reduce conflict. */
end ifobjc
ifc
-%expect 10
+%expect 10 /* shift/reduce conflicts, and no reduce/reduce conflicts. */
end ifc
%{
@@ -295,8 +295,18 @@ int objc_receiver_context;
int objc_public_flag;
int objc_pq_context;
+/* The following flag is needed to contextualize ObjC lexical analysis.
+ In some cases (e.g., 'int NSObject;'), it is undesirable to bind
+ an identifier to an ObjC class, even if a class with that name
+ exists. */
+int objc_need_raw_identifier;
+#define OBJC_NEED_RAW_IDENTIFIER(VAL) objc_need_raw_identifier = VAL
end ifobjc
+ifc
+#define OBJC_NEED_RAW_IDENTIFIER(VAL) /* nothing */
+end ifc
+
/* Tell yyparse how to print a token's value, if yydebug is set. */
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
@@ -444,7 +454,7 @@ identifier:
| TYPENAME
ifobjc
| OBJECTNAME
- | CLASSNAME
+ | CLASSNAME
end ifobjc
;
@@ -1384,6 +1394,7 @@ typespec_attr:
typespec_reserved_nonattr:
TYPESPEC
+ { OBJC_NEED_RAW_IDENTIFIER (1); }
| structsp_nonattr
;
@@ -1694,6 +1705,9 @@ parm_declarator_starttypename:
| parm_declarator_starttypename array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| TYPENAME
+ifobjc
+ | OBJECTNAME
+end ifobjc
;
parm_declarator_nostarttypename:
@@ -2836,6 +2850,13 @@ protocoldef:
finish_protocol(objc_interface_context);
objc_interface_context = NULL_TREE;
}
+ /* The @protocol forward-declaration production introduces a
+ reduce/reduce conflict on ';', which should be resolved in
+ favor of the production 'identifier_list -> identifier'. */
+ | PROTOCOL identifier_list ';'
+ {
+ objc_declare_protocols ($2);
+ }
;
protocolrefs:
@@ -3119,8 +3140,9 @@ keywordselector:
selector:
IDENTIFIER
- | TYPENAME
- | OBJECTNAME
+ | TYPENAME
+ | CLASSNAME
+ | OBJECTNAME
| reservedwords
;
@@ -3615,12 +3637,26 @@ static int
yylexname ()
{
tree decl;
-
+
+ifobjc
+ int objc_force_identifier = objc_need_raw_identifier;
+ OBJC_NEED_RAW_IDENTIFIER (0);
+end ifobjc
+
if (C_IS_RESERVED_WORD (yylval.ttype))
{
enum rid rid_code = C_RID_CODE (yylval.ttype);
ifobjc
+ /* Turn non-typedefed refs to "id" into plain identifiers; this
+ allows constructs like "void foo(id id);" to work. */
+ if (rid_code == RID_ID)
+ {
+ decl = lookup_name (yylval.ttype);
+ if (decl == NULL_TREE || TREE_CODE (decl) != TYPE_DECL)
+ return IDENTIFIER;
+ }
+
if (!OBJC_IS_AT_KEYWORD (rid_code)
&& (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
end ifobjc
@@ -3653,8 +3689,11 @@ ifobjc
else
{
tree objc_interface_decl = is_class_name (yylval.ttype);
-
- if (objc_interface_decl)
+ /* ObjC class names are in the same namespace as variables and
+ typedefs, and hence are shadowed by local declarations. */
+ if (objc_interface_decl
+ && (global_bindings_p ()
+ || (!objc_force_identifier && !decl)))
{
yylval.ttype = objc_interface_decl;
return CLASSNAME;
@@ -3692,10 +3731,7 @@ _yylex ()
case CPP_AND_AND: return ANDAND;
case CPP_OR_OR: return OROR;
case CPP_QUERY: return '?';
- case CPP_COLON: return ':';
- case CPP_COMMA: return ',';
case CPP_OPEN_PAREN: return '(';
- case CPP_CLOSE_PAREN: return ')';
case CPP_EQ_EQ: yylval.code = EQ_EXPR; return EQCOMPARE;
case CPP_NOT_EQ: yylval.code = NE_EXPR; return EQCOMPARE;
case CPP_GREATER_EQ:yylval.code = GE_EXPR; return ARITHCOMPARE;
@@ -3716,7 +3752,6 @@ _yylex ()
case CPP_CLOSE_SQUARE: return ']';
case CPP_OPEN_BRACE: return '{';
case CPP_CLOSE_BRACE: return '}';
- case CPP_SEMICOLON: return ';';
case CPP_ELLIPSIS: return ELLIPSIS;
case CPP_PLUS_PLUS: return PLUSPLUS;
@@ -3724,6 +3759,13 @@ _yylex ()
case CPP_DEREF: return POINTSAT;
case CPP_DOT: return '.';
+ /* The following tokens may affect the interpretation of any
+ identifiers following, if doing Objective-C. */
+ case CPP_COLON: OBJC_NEED_RAW_IDENTIFIER (0); return ':';
+ case CPP_COMMA: OBJC_NEED_RAW_IDENTIFIER (0); return ',';
+ case CPP_CLOSE_PAREN: OBJC_NEED_RAW_IDENTIFIER (0); return ')';
+ case CPP_SEMICOLON: OBJC_NEED_RAW_IDENTIFIER (0); return ';';
+
case CPP_EOF:
if (cpp_pop_buffer (parse_in) == 0)
return 0;
@@ -3741,8 +3783,8 @@ _yylex ()
case CPP_WSTRING:
return STRING;
- /* This token is Objective-C specific. It gives the next
- token special significance. */
+ /* This token is Objective-C specific. It gives the next token
+ special significance. */
case CPP_ATSIGN:
ifobjc
{
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 0b99ece7fea..03c3ae4f262 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -253,6 +253,7 @@ static tree build_selector_reference_decl PARAMS ((void));
static tree add_protocol PARAMS ((tree));
static tree lookup_protocol PARAMS ((tree));
+static void check_protocol_recursively PARAMS ((tree, tree));
static tree lookup_and_install_protocols PARAMS ((tree));
/* Type encoding. */
@@ -336,6 +337,8 @@ static tree check_duplicates PARAMS ((hash));
static tree receiver_is_class_object PARAMS ((tree));
static int check_methods PARAMS ((tree, tree, int));
static int conforms_to_protocol PARAMS ((tree, tree));
+static void check_protocol PARAMS ((tree, const char *,
+ const char *));
static void check_protocols PARAMS ((tree, const char *,
const char *));
static tree encode_method_def PARAMS ((tree));
@@ -1010,6 +1013,12 @@ objc_comptypes (lhs, rhs, reflexive)
tree cat;
rproto_list = CLASS_PROTOCOL_LIST (rinter);
+ /* If the underlying ObjC class does not have
+ protocols attached to it, perhaps there are
+ "one-off" protocols attached to the rhs?
+ E.g., 'id<MyProt> foo;'. */
+ if (!rproto_list)
+ rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
rproto = lookup_protocol_in_reflist (rproto_list, p);
/* Check for protocols adopted by categories. */
@@ -1202,6 +1211,32 @@ get_object_reference (protocols)
return type;
}
+/* Check for circular dependencies in protocols. The arguments are
+ PROTO, the protocol to check, and LIST, a list of protocol it
+ conforms to. */
+
+static void
+check_protocol_recursively (proto, list)
+ tree proto;
+ tree list;
+{
+ tree p;
+
+ for (p = list; p; p = TREE_CHAIN (p))
+ {
+ tree pp = TREE_VALUE (p);
+
+ if (TREE_CODE (pp) == IDENTIFIER_NODE)
+ pp = lookup_protocol (pp);
+
+ if (pp == proto)
+ fatal_error ("protocol `%s' has circular dependency",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
+ if (pp)
+ check_protocol_recursively (proto, PROTOCOL_LIST (pp));
+ }
+}
+
static tree
lookup_and_install_protocols (protocols)
tree protocols;
@@ -4871,18 +4906,27 @@ check_duplicates (hsh)
return meth;
}
-/* If RECEIVER is a class reference, return the identifier node for the
- referenced class. RECEIVER is created by get_class_reference, so we
- check the exact form created depending on which runtimes are used. */
+/* If RECEIVER is a class reference, return the identifier node for
+ the referenced class. RECEIVER is created by get_class_reference,
+ so we check the exact form created depending on which runtimes are
+ used. */
static tree
receiver_is_class_object (receiver)
tree receiver;
{
tree chain, exp, arg;
+
if (flag_next_runtime)
{
- /* The receiver is a variable created by build_class_reference_decl. */
+ /* The receiver is 'self' in the context of a class method. */
+ if (objc_method_context
+ && receiver == self_decl
+ && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
+ return CLASS_NAME (objc_implementation_context);
+
+ /* The receiver is a variable created by
+ build_class_reference_decl. */
if (TREE_CODE (receiver) == VAR_DECL
&& TREE_TYPE (receiver) == objc_class_type)
/* Look up the identifier. */
@@ -4899,7 +4943,7 @@ receiver_is_class_object (receiver)
&& (exp = TREE_OPERAND (exp, 0))
&& TREE_CODE (exp) == FUNCTION_DECL
&& exp == objc_get_class_decl
- /* we have a call to objc_getClass! */
+ /* We have a call to objc_getClass! */
&& (arg = TREE_OPERAND (receiver, 1))
&& TREE_CODE (arg) == TREE_LIST
&& (arg = TREE_VALUE (arg)))
@@ -5143,7 +5187,8 @@ build_message_expr (mess)
method_prototype = lookup_class_method_static (iface, sel_name);
}
- if (!method_prototype)
+ if (!method_prototype
+ || TREE_CODE (method_prototype) != CLASS_METHOD_DECL)
{
warning ("cannot find class (factory) method.");
warning ("return type for `%s' defaults to id",
@@ -5960,16 +6005,17 @@ check_methods (chain, list, mtype)
return first;
}
+/* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL. */
+
static int
conforms_to_protocol (class, protocol)
tree class;
tree protocol;
{
- while (protocol)
+ if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
{
tree p = CLASS_PROTOCOL_LIST (class);
-
- while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
+ while (p && TREE_VALUE (p) != protocol)
p = TREE_CHAIN (p);
if (!p)
@@ -5981,8 +6027,6 @@ conforms_to_protocol (class, protocol)
if (!tmp)
return 0;
}
-
- protocol = TREE_CHAIN (protocol);
}
return 1;
@@ -6054,57 +6098,81 @@ check_methods_accessible (chain, context, mtype)
return first;
}
+/* Check whether the current interface (accessible via
+ 'implementation_context') actually implements protocol P, along
+ with any protocols that P inherits. */
+
static void
-check_protocols (proto_list, type, name)
- tree proto_list;
+check_protocol (p, type, name)
+ tree p;
const char *type;
const char *name;
{
- for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
+ if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
{
- tree p = TREE_VALUE (proto_list);
+ int f1, f2;
- if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
+ /* Ensure that all protocols have bodies! */
+ if (flag_warn_protocol)
{
- int f1, f2;
-
- /* Ensure that all protocols have bodies. */
- if (flag_warn_protocol) {
- f1 = check_methods (PROTOCOL_CLS_METHODS (p),
- CLASS_CLS_METHODS (implementation_context),
- '+');
- f2 = check_methods (PROTOCOL_NST_METHODS (p),
- CLASS_NST_METHODS (implementation_context),
- '-');
- } else {
- f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
- implementation_context,
- '+');
- f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
- implementation_context,
- '-');
- }
-
- if (!f1 || !f2)
- warning ("%s `%s' does not fully implement the `%s' protocol",
- type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
-
+ f1 = check_methods (PROTOCOL_CLS_METHODS (p),
+ CLASS_CLS_METHODS (implementation_context),
+ '+');
+ f2 = check_methods (PROTOCOL_NST_METHODS (p),
+ CLASS_NST_METHODS (implementation_context),
+ '-');
}
else
- {
- ; /* An identifier if we could not find a protocol. */
- }
+ {
+ f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
+ implementation_context,
+ '+');
+ f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
+ implementation_context,
+ '-');
+ }
- /* Check protocols recursively. */
- if (PROTOCOL_LIST (p))
+ if (!f1 || !f2)
+ warning ("%s `%s' does not fully implement the `%s' protocol",
+ type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+ }
+
+ /* Check protocols recursively. */
+ if (PROTOCOL_LIST (p))
+ {
+ tree subs = PROTOCOL_LIST (p);
+ tree super_class =
+ lookup_interface (CLASS_SUPER_NAME (implementation_template));
+ while (subs)
{
- tree super_class
- = lookup_interface (CLASS_SUPER_NAME (implementation_template));
- if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
- check_protocols (PROTOCOL_LIST (p), type, name);
+ tree sub = TREE_VALUE (subs);
+
+ /* If the superclass does not conform to the protocols
+ inherited by P, then we must! */
+ if (!super_class || !conforms_to_protocol (super_class, sub))
+ check_protocol (sub, type, name);
+ subs = TREE_CHAIN (subs);
}
}
}
+
+/* Check whether the current interface (accessible via
+ 'implementation_context') actually implements the protocols listed
+ in PROTO_LIST. */
+
+static void
+check_protocols (proto_list, type, name)
+ tree proto_list;
+ const char *type;
+ const char *name;
+{
+ for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
+ {
+ tree p = TREE_VALUE (proto_list);
+
+ check_protocol (p, type, name);
+ }
+}
/* Make sure that the class CLASS_NAME is defined
CODE says which kind of thing CLASS_NAME ought to be.
@@ -6430,6 +6498,33 @@ lookup_protocol (ident)
return NULL_TREE;
}
+/* This function forward declares the protocols named by NAMES. If
+ they are already declared or defined, the function has no effect. */
+
+void
+objc_declare_protocols (names)
+ tree names;
+{
+ tree list;
+
+ for (list = names; list; list = TREE_CHAIN (list))
+ {
+ tree name = TREE_VALUE (list);
+
+ if (lookup_protocol (name) == NULL_TREE)
+ {
+ tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
+
+ TYPE_BINFO (protocol) = make_tree_vec (2);
+ PROTOCOL_NAME (protocol) = name;
+ PROTOCOL_LIST (protocol) = NULL_TREE;
+ add_protocol (protocol);
+ PROTOCOL_DEFINED (protocol) = 0;
+ PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
+ }
+ }
+}
+
tree
start_protocol (code, name, list)
enum tree_code code;
@@ -6438,26 +6533,38 @@ start_protocol (code, name, list)
{
tree protocol;
- /* This is as good a place as any. Need to invoke push_tag_toplevel. */
+ /* This is as good a place as any. Need to invoke
+ push_tag_toplevel. */
if (!objc_protocol_template)
objc_protocol_template = build_protocol_template ();
- protocol = make_node (code);
- TYPE_BINFO (protocol) = make_tree_vec (2);
+ protocol = lookup_protocol (name);
- PROTOCOL_NAME (protocol) = name;
- PROTOCOL_LIST (protocol) = list;
+ if (!protocol)
+ {
+ protocol = make_node (code);
+ TYPE_BINFO (protocol) = make_tree_vec (2);
- lookup_and_install_protocols (list);
+ PROTOCOL_NAME (protocol) = name;
+ PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
+ add_protocol (protocol);
+ PROTOCOL_DEFINED (protocol) = 1;
+ PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
- if (lookup_protocol (name))
- warning ("duplicate declaration for protocol `%s'",
- IDENTIFIER_POINTER (name));
- else
- add_protocol (protocol);
-
- PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
+ check_protocol_recursively (protocol, list);
+ }
+ else if (! PROTOCOL_DEFINED (protocol))
+ {
+ PROTOCOL_DEFINED (protocol) = 1;
+ PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
+ check_protocol_recursively (protocol, list);
+ }
+ else
+ {
+ warning ("duplicate declaration for protocol `%s'",
+ IDENTIFIER_POINTER (name));
+ }
return protocol;
}
@@ -6595,6 +6702,11 @@ encode_aggregate_within (type, curtype, format, left, right)
int left;
int right;
{
+ /* The RECORD_TYPE may in fact be a typedef! For purposes
+ of encoding, we need the real underlying enchilada. */
+ if (TYPE_MAIN_VARIANT (type))
+ type = TYPE_MAIN_VARIANT (type);
+
if (obstack_object_size (&util_obstack) > 0
&& *(obstack_next_free (&util_obstack) - 1) == '^')
{
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index f13acc8f192..e659f916525 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -1,5 +1,5 @@
/* Declarations for objc-act.c.
- Copyright (C) 1990, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1990, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -59,6 +59,7 @@ extern tree objc_ellipsis_node;
void objc_declare_alias PARAMS ((tree, tree));
void objc_declare_class PARAMS ((tree));
+void objc_declare_protocols PARAMS ((tree));
extern int objc_receiver_context;
@@ -101,6 +102,7 @@ tree build_encode_expr PARAMS ((tree));
#define PROTOCOL_NST_METHODS(CLASS) ((CLASS)->type.minval)
#define PROTOCOL_CLS_METHODS(CLASS) ((CLASS)->type.maxval)
#define PROTOCOL_FORWARD_DECL(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 1)
+#define PROTOCOL_DEFINED(CLASS) TREE_USED (CLASS)
#define TYPE_PROTOCOL_LIST(TYPE) ((TYPE)->type.context)
/* Define the Objective-C or Objective-C++ language-specific tree codes. */