aboutsummaryrefslogtreecommitdiff
path: root/gcc/objc
diff options
context:
space:
mode:
authorNicola Pero <nicola.pero@meta-innovation.com>2010-11-29 03:15:40 +0000
committerNicola Pero <nicola@gcc.gnu.org>2010-11-29 03:15:40 +0000
commit437c23222436111f80b29ec24d2fb863b567e589 (patch)
tree44406a903b8b5e0d042b1c9cd87592f05480f94d /gcc/objc
parent45f9cadb2a94bbb57bfd0a3f68afe42346c79c57 (diff)
downloadgcc-437c23222436111f80b29ec24d2fb863b567e589.zip
gcc-437c23222436111f80b29ec24d2fb863b567e589.tar.gz
gcc-437c23222436111f80b29ec24d2fb863b567e589.tar.bz2
In gcc/objc/: 2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/objc/: 2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com> * objc-act.c (objc_eh_runtime_type): Avoid ICE if error_mark_node is passed as argument. (objc_begin_catch_clause): Added code to deal with an error_mark_node or NULL_TREE argument. Improved checks for invalid arguments. Added code to traverse typedefs. In gcc/testsuite/: 2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com> * objc.dg/exceptions-1.m: New. * objc.dg/exceptions-2.m: New. * objc.dg/exceptions-3.m: New. * objc.dg/exceptions-4.m: New. * objc.dg/exceptions-5.m: New. * obj-c++.dg/exceptions-1.mm: New. * obj-c++.dg/exceptions-2.mm: New. * obj-c++.dg/exceptions-3.mm: New. * obj-c++.dg/exceptions-4.mm: New. * obj-c++.dg/exceptions-5.mm: New. In gcc/cp/: 2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com> * parser.c (cp_parser_objc_try_catch_finally_statement): Parse @catch(...) and pass NULL_TREE to objc_begin_catch_clause() in that case. Improved error recovery. Reorganized code to be almost identical to c_parser_objc_try_catch_finally_statement. In gcc/: 2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com> * c-parser.c (c_parser_objc_try_catch_statement): Renamed to c_parser_objc_try_catch_finally_statement for consistency with the C++ parser. Parse @catch(...) and pass NULL_TREE to objc_begin_catch_clause() in that case. Improved error recovery. Reorganized code to be almost identical to cp_parser_objc_try_catch_finally_statement. From-SVN: r167233
Diffstat (limited to 'gcc/objc')
-rw-r--r--gcc/objc/ChangeLog8
-rw-r--r--gcc/objc/objc-act.c126
2 files changed, 102 insertions, 32 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index ca2833c..644129b 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,5 +1,13 @@
2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com>
+ * objc-act.c (objc_eh_runtime_type): Avoid ICE if error_mark_node
+ is passed as argument.
+ (objc_begin_catch_clause): Added code to deal with an
+ error_mark_node or NULL_TREE argument. Improved checks for
+ invalid arguments. Added code to traverse typedefs.
+
+2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com>
+
* objc-act.c (objc_demangle): Return immediately if the string is
too short. Detect names that do not need demangling, and return
them unchanged.
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 09f4e6f..810a53a 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -5024,7 +5024,14 @@ static GTY(()) tree objc_eh_personality_decl;
tree
objc_eh_runtime_type (tree type)
{
- return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
+ /* Use 'ErrorMarkNode' as class name when error_mark_node is found
+ to prevent an ICE. Note that we know that the compiler will
+ terminate with an error and this 'ErrorMarkNode' class name will
+ never be actually used. */
+ if (type == error_mark_node)
+ return add_objc_string (get_identifier ("ErrorMarkNode"), class_names);
+ else
+ return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
}
tree
@@ -5355,7 +5362,9 @@ objc_begin_try_stmt (location_t try_locus, tree body)
/* Called just after parsing "@catch (parm)". Open a binding level,
enter DECL into the binding level, and initialize it. Leave the
- binding level open while the body of the compound statement is parsed. */
+ binding level open while the body of the compound statement is
+ parsed. If DECL is NULL_TREE, then we are compiling "@catch(...)"
+ which we compile as "@catch(id tmp_variable)". */
void
objc_begin_catch_clause (tree decl)
@@ -5365,46 +5374,99 @@ objc_begin_catch_clause (tree decl)
/* Begin a new scope that the entire catch clause will live in. */
compound = c_begin_compound_stmt (true);
- /* The parser passed in a PARM_DECL, but what we really want is a VAR_DECL. */
- decl = build_decl (input_location,
- VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
- lang_hooks.decls.pushdecl (decl);
+ /* Create the appropriate declaration for the argument. */
+ if (decl == error_mark_node)
+ type = error_mark_node;
+ else
+ {
+ if (decl == NULL_TREE)
+ {
+ /* If @catch(...) was specified, create a temporary variable of
+ type 'id' and use it. */
+ decl = objc_create_temporary_var (objc_object_type, "__objc_generic_catch_var");
+ DECL_SOURCE_LOCATION (decl) = input_location;
+ }
+ else
+ {
+ /* The parser passed in a PARM_DECL, but what we really want is a VAR_DECL. */
+ decl = build_decl (input_location,
+ VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
+ }
+ lang_hooks.decls.pushdecl (decl);
- /* Since a decl is required here by syntax, don't warn if its unused. */
- /* ??? As opposed to __attribute__((unused))? Anyway, this appears to
- be what the previous objc implementation did. */
- TREE_USED (decl) = 1;
- DECL_READ_P (decl) = 1;
+ /* Mark the declaration as used so you never any warnings whether
+ you use the exception argument or not. TODO: Implement a
+ -Wunused-exception-parameter flag, which would cause warnings
+ if exception parameter is not used. */
+ TREE_USED (decl) = 1;
+ DECL_READ_P (decl) = 1;
- /* Verify that the type of the catch is valid. It must be a pointer
- to an Objective-C class, or "id" (which is catch-all). */
- type = TREE_TYPE (decl);
+ type = TREE_TYPE (decl);
+ }
- if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
- type = NULL;
- else if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
+ /* Verify that the type of the catch is valid. It must be a pointer
+ to an Objective-C class, or "id" (which is catch-all). */
+ if (type == error_mark_node)
+ {
+ ;/* Just keep going. */
+ }
+ else if (!objc_type_valid_for_messaging (type, false))
{
error ("@catch parameter is not a known Objective-C class type");
type = error_mark_node;
}
- else if (cur_try_context->catch_list)
+ else if (TYPE_HAS_OBJC_INFO (TREE_TYPE (type))
+ && TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (type)))
{
- /* Examine previous @catch clauses and see if we've already
- caught the type in question. */
- tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
- for (; !tsi_end_p (i); tsi_next (&i))
+ error ("@catch parameter can not be protocol-qualified");
+ type = error_mark_node;
+ }
+ else if (objc_is_object_id (TREE_TYPE (type)))
+ type = NULL;
+ else
+ {
+ /* If 'type' was built using typedefs, we need to get rid of
+ them and get a simple pointer to the class. */
+ bool is_typedef = false;
+ tree x = TYPE_MAIN_VARIANT (type);
+
+ /* Skip from the pointer to the pointee. */
+ if (TREE_CODE (x) == POINTER_TYPE)
+ x = TREE_TYPE (x);
+
+ /* Traverse typedef aliases */
+ while (TREE_CODE (x) == RECORD_TYPE && OBJC_TYPE_NAME (x)
+ && TREE_CODE (OBJC_TYPE_NAME (x)) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (x)))
{
- tree stmt = tsi_stmt (i);
- t = CATCH_TYPES (stmt);
- if (t == error_mark_node)
- continue;
- if (!t || DERIVED_FROM_P (TREE_TYPE (t), TREE_TYPE (type)))
+ is_typedef = true;
+ x = DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (x));
+ }
+
+ /* If it was a typedef, build a pointer to the final, original
+ class. */
+ if (is_typedef)
+ type = build_pointer_type (x);
+
+ if (cur_try_context->catch_list)
+ {
+ /* Examine previous @catch clauses and see if we've already
+ caught the type in question. */
+ tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
+ for (; !tsi_end_p (i); tsi_next (&i))
{
- warning (0, "exception of type %<%T%> will be caught",
- TREE_TYPE (type));
- warning_at (EXPR_LOCATION (stmt), 0, " by earlier handler for %<%T%>",
- TREE_TYPE (t ? t : objc_object_type));
- break;
+ tree stmt = tsi_stmt (i);
+ t = CATCH_TYPES (stmt);
+ if (t == error_mark_node)
+ continue;
+ if (!t || DERIVED_FROM_P (TREE_TYPE (t), TREE_TYPE (type)))
+ {
+ warning (0, "exception of type %<%T%> will be caught",
+ TREE_TYPE (type));
+ warning_at (EXPR_LOCATION (stmt), 0, " by earlier handler for %<%T%>",
+ TREE_TYPE (t ? t : objc_object_type));
+ break;
+ }
}
}
}