aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/c-parser.c90
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/parser.c78
-rw-r--r--gcc/objc/ChangeLog8
-rw-r--r--gcc/objc/objc-act.c126
-rw-r--r--gcc/testsuite/ChangeLog13
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-1.mm42
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-2.mm54
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-3.mm114
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-4.mm64
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-5.mm114
-rw-r--r--gcc/testsuite/objc.dg/exceptions-1.m42
-rw-r--r--gcc/testsuite/objc.dg/exceptions-2.m52
-rw-r--r--gcc/testsuite/objc.dg/exceptions-3.m114
-rw-r--r--gcc/testsuite/objc.dg/exceptions-4.m64
-rw-r--r--gcc/testsuite/objc.dg/exceptions-5.m114
17 files changed, 1035 insertions, 70 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bf82ac9..c20e57e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+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.
+
2010-11-29 Joern Rennecke <amylaar@spamcop.net>
PR tree-optimization/46621
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index c63f001..879e106 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -1155,7 +1155,7 @@ static void c_parser_objc_methodproto (c_parser *);
static tree c_parser_objc_method_decl (c_parser *, bool, tree *);
static tree c_parser_objc_type_name (c_parser *);
static tree c_parser_objc_protocol_refs (c_parser *);
-static void c_parser_objc_try_catch_statement (c_parser *);
+static void c_parser_objc_try_catch_finally_statement (c_parser *);
static void c_parser_objc_synchronized_statement (c_parser *);
static tree c_parser_objc_selector (c_parser *);
static tree c_parser_objc_selector_arg (c_parser *);
@@ -4371,7 +4371,7 @@ c_parser_statement_after_labels (c_parser *parser)
break;
case RID_AT_TRY:
gcc_assert (c_dialect_objc ());
- c_parser_objc_try_catch_statement (parser);
+ c_parser_objc_try_catch_finally_statement (parser);
break;
case RID_AT_SYNCHRONIZED:
gcc_assert (c_dialect_objc ());
@@ -7468,53 +7468,97 @@ c_parser_objc_protocol_refs (c_parser *parser)
return list;
}
-/* Parse an objc-try-catch-statement.
+/* Parse an objc-try-catch-finally-statement.
- objc-try-catch-statement:
+ objc-try-catch-finally-statement:
@try compound-statement objc-catch-list[opt]
@try compound-statement objc-catch-list[opt] @finally compound-statement
objc-catch-list:
- @catch ( parameter-declaration ) compound-statement
- objc-catch-list @catch ( parameter-declaration ) compound-statement
-*/
+ @catch ( objc-catch-parameter-declaration ) compound-statement
+ objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
+
+ objc-catch-parameter-declaration:
+ parameter-declaration
+ '...'
+
+ where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
+
+ PS: This function is identical to cp_parser_objc_try_catch_finally_statement
+ for C++. Keep them in sync. */
static void
-c_parser_objc_try_catch_statement (c_parser *parser)
+c_parser_objc_try_catch_finally_statement (c_parser *parser)
{
- location_t loc;
+ location_t location;
tree stmt;
+
gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
c_parser_consume_token (parser);
- loc = c_parser_peek_token (parser)->location;
+ location = c_parser_peek_token (parser)->location;
stmt = c_parser_compound_statement (parser);
- objc_begin_try_stmt (loc, stmt);
+ objc_begin_try_stmt (location, stmt);
+
while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
{
struct c_parm *parm;
+ tree parameter_declaration = error_mark_node;
+ bool seen_open_paren = false;
+
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- break;
- parm = c_parser_parameter_declaration (parser, NULL_TREE);
- if (parm == NULL)
+ seen_open_paren = true;
+ if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
{
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- break;
+ /* We have "@catch (...)" (where the '...' are literally
+ what is in the code). Skip the '...'.
+ parameter_declaration is set to NULL_TREE, and
+ objc_being_catch_clauses() knows that that means
+ '...'. */
+ c_parser_consume_token (parser);
+ parameter_declaration = NULL_TREE;
}
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
- objc_begin_catch_clause (grokparm (parm));
+ else
+ {
+ /* We have "@catch (NSException *exception)" or something
+ like that. Parse the parameter declaration. */
+ parm = c_parser_parameter_declaration (parser, NULL_TREE);
+ if (parm == NULL)
+ parameter_declaration = error_mark_node;
+ else
+ parameter_declaration = grokparm (parm);
+ }
+ if (seen_open_paren)
+ c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ else
+ {
+ /* If there was no open parenthesis, we are recovering from
+ an error, and we are trying to figure out what mistake
+ the user has made. */
+
+ /* If there is an immediate closing parenthesis, the user
+ probably forgot the opening one (ie, they typed "@catch
+ NSException *e)". Parse the closing parenthesis and keep
+ going. */
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ c_parser_consume_token (parser);
+
+ /* If these is no immediate closing parenthesis, the user
+ probably doesn't know that parenthesis are required at
+ all (ie, they typed "@catch NSException *e"). So, just
+ forget about the closing parenthesis and keep going. */
+ }
+ objc_begin_catch_clause (parameter_declaration);
if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
c_parser_compound_statement_nostart (parser);
objc_finish_catch_clause ();
}
if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
{
- location_t finloc;
- tree finstmt;
c_parser_consume_token (parser);
- finloc = c_parser_peek_token (parser)->location;
- finstmt = c_parser_compound_statement (parser);
- objc_build_finally_clause (finloc, finstmt);
+ location = c_parser_peek_token (parser)->location;
+ stmt = c_parser_compound_statement (parser);
+ objc_build_finally_clause (location, stmt);
}
objc_finish_try_stmt ();
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6422401..6e3bbbe 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+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.
+
2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
PR objc++/46222
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3ed0579..917f750 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -22598,15 +22598,25 @@ cp_parser_objc_declaration (cp_parser* parser, tree attributes)
objc-catch-clause objc-catch-clause-seq [opt]
objc-catch-clause:
- @catch ( exception-declaration ) compound-statement
+ @catch ( objc-exception-declaration ) compound-statement
- objc-finally-clause
+ objc-finally-clause:
@finally compound-statement
- Returns NULL_TREE. */
+ objc-exception-declaration:
+ parameter-declaration
+ '...'
+
+ where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
+
+ Returns NULL_TREE.
+
+ PS: This function is identical to c_parser_objc_try_catch_finally_statement
+ for C. Keep them in sync. */
static tree
-cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
+cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
+{
location_t location;
tree stmt;
@@ -22620,22 +22630,60 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH))
{
- cp_parameter_declarator *parmdecl;
- tree parm;
+ cp_parameter_declarator *parm;
+ tree parameter_declaration = error_mark_node;
+ bool seen_open_paren = false;
cp_lexer_consume_token (parser->lexer);
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
- parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
- parm = grokdeclarator (parmdecl->declarator,
- &parmdecl->decl_specifiers,
- PARM, /*initialized=*/0,
- /*attrlist=*/NULL);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
- objc_begin_catch_clause (parm);
+ if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ seen_open_paren = true;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+ {
+ /* We have "@catch (...)" (where the '...' are literally
+ what is in the code). Skip the '...'.
+ parameter_declaration is set to NULL_TREE, and
+ objc_being_catch_clauses() knows that that means
+ '...'. */
+ cp_lexer_consume_token (parser->lexer);
+ parameter_declaration = NULL_TREE;
+ }
+ else
+ {
+ /* We have "@catch (NSException *exception)" or something
+ like that. Parse the parameter declaration. */
+ parm = cp_parser_parameter_declaration (parser, false, NULL);
+ if (parm == NULL)
+ parameter_declaration = error_mark_node;
+ else
+ parameter_declaration = grokdeclarator (parm->declarator,
+ &parm->decl_specifiers,
+ PARM, /*initialized=*/0,
+ /*attrlist=*/NULL);
+ }
+ if (seen_open_paren)
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ else
+ {
+ /* If there was no open parenthesis, we are recovering from
+ an error, and we are trying to figure out what mistake
+ the user has made. */
+
+ /* If there is an immediate closing parenthesis, the user
+ probably forgot the opening one (ie, they typed "@catch
+ NSException *e)". Parse the closing parenthesis and keep
+ going. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ cp_lexer_consume_token (parser->lexer);
+
+ /* If these is no immediate closing parenthesis, the user
+ probably doesn't know that parenthesis are required at
+ all (ie, they typed "@catch NSException *e"). So, just
+ forget about the closing parenthesis and keep going. */
+ }
+ objc_begin_catch_clause (parameter_declaration);
cp_parser_compound_statement (parser, NULL, false);
objc_finish_catch_clause ();
}
-
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY))
{
cp_lexer_consume_token (parser->lexer);
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;
+ }
}
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c7830eb..6185f59 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,18 @@
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.
+
+2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com>
+
* obj-c++.dg/property/at-property-1.mm: Fixed testcase.
* obj-c++.dg/property/at-property-16.mm: Fixed testcase.
* obj-c++.dg/property/at-property-20.mm: Fixed testcase.
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-1.mm b/gcc/testsuite/obj-c++.dg/exceptions-1.mm
new file mode 100644
index 0000000..0f3b7e8
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/exceptions-1.mm
@@ -0,0 +1,42 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* This test checks the syntax @catch (...) which catches any
+ exceptions. At the moment, @catch (...) is identical to @catch (id
+ exception). */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+int test (id object)
+{
+ int i = 0;
+
+ @try
+ {
+ @throw object;
+ }
+ @catch (MyObject *o)
+ {
+ i += 1;
+ }
+ @catch (...)
+ {
+ i += 2;
+ }
+ @finally
+ {
+ i += 4;
+ }
+
+ return i;
+}
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-2.mm b/gcc/testsuite/obj-c++.dg/exceptions-2.mm
new file mode 100644
index 0000000..ce85b73
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/exceptions-2.mm
@@ -0,0 +1,54 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-options "-fobjc-exceptions" } */
+
+/* FIXME: This does not test running the code, because Objective-C exceptions at the moment
+ do not execute correctly in Objective-C++. See PR objc++/23616. Once that is fixed,
+ this test should be changed to use 'dg-run' instead of just 'dg-compile'. */
+/* { dg-compile } */
+
+/* This test checks the syntax @catch (...) which catches any
+ exceptions. Check that code using it runs correctly. */
+
+#include "../objc-obj-c++-shared/Object1.h"
+#include <stdlib.h>
+
+@interface MyObject : Object
+@end
+
+@implementation MyObject
+@end
+
+int test (id object)
+{
+ int i = 0;
+
+ @try
+ {
+ @throw object;
+ }
+ @catch (MyObject *o)
+ {
+ i += 1;
+ }
+ @catch (...)
+ {
+ i += 2;
+ }
+ @finally
+ {
+ i += 4;
+ }
+
+ return i;
+}
+
+int main (void)
+{
+ if (test ([MyObject new]) != 5)
+ abort ();
+
+ if (test ([Object new]) != 6)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-3.mm b/gcc/testsuite/obj-c++.dg/exceptions-3.mm
new file mode 100644
index 0000000..b1ba185
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/exceptions-3.mm
@@ -0,0 +1,114 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* Test that the compiler is checking the argument of @catch(), and
+ produce errors when invalid types are used. */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+@protocol MyProtocol;
+
+typedef MyObject MyObjectTypedef;
+typedef MyObject *MyObjectPtrTypedef;
+typedef int intTypedef;
+
+int test (id object)
+{
+ int dummy = 0;
+
+ @try { @throw object; }
+ @catch (int x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (intTypedef x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (int *x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (id x) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (id <MyProtocol> x) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject *x) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject <MyProtocol> *x) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ { /* { dg-error "no matching function" "" { target *-*-* } 72 } */
+ dummy++; /* { dg-warning "MyObject" "" { target *-*-* } 13 } */
+ }
+
+ @try { @throw object; }
+ @catch (static MyObject *x) /* { dg-error "storage class" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectTypedef *x) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectTypedef <MyProtocol> *x) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectPtrTypedef x) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (Class x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (...) /* Ok */
+ {
+ dummy++;
+ }
+
+ return dummy;
+}
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-4.mm b/gcc/testsuite/obj-c++.dg/exceptions-4.mm
new file mode 100644
index 0000000..85debe4
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/exceptions-4.mm
@@ -0,0 +1,64 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* Test warnings when parsing syntax errors in @catch(). */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+@interface MyObject2
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject2
+@end
+
+@protocol MyProtocol;
+
+int test (id object)
+{
+ int dummy = 0;
+
+ @try { @throw object; }
+ @catch
+ { /* { dg-error "expected" } */
+ dummy++; /* { dg-error "@catch parameter is not a known Objective-C class type" "" { target *-*-* } 35 } */
+ }
+ @catch () /* { dg-error "expected identifier before" } */
+ { /* { dg-error "@catch parameter is not a known Objective-C class type" "" { target *-*-* } 38 } */
+ dummy++;
+ }
+ @catch (i) /* { dg-error ".i. has not been declared" } */
+ { /* { dg-error "@catch parameter is not a known Objective-C class type" "" { target *-*-* } 42 } */
+ dummy++;
+ }
+ @catch (id <MyProtocol x) /* { dg-error "expected ... before .x." } */
+ { /* { dg-error "@catch parameter can not be protocol-qualified" "" { target *-*-* } 46 } */
+ dummy++;
+ }
+ @catch MyObject *x /* { dg-error "expected ... before .MyObject." } */
+ {
+ dummy++;
+ }
+ @catch MyObject2 *x) /* { dg-error "expected ... before .MyObject2." } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject *x)
+ @catch (MyObject2 *y) /* { dg-error "expected ... before .catch." } */
+
+ return dummy; /* { dg-error "expected ... before .return." } */
+}
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-5.mm b/gcc/testsuite/obj-c++.dg/exceptions-5.mm
new file mode 100644
index 0000000..f740496
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/exceptions-5.mm
@@ -0,0 +1,114 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* Test that you can use an unnamed argument with @catch. This test is the same
+ as exceptions-3.mm, but with no name for @catch arguments. */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+@protocol MyProtocol;
+
+typedef MyObject MyObjectTypedef;
+typedef MyObject *MyObjectPtrTypedef;
+typedef int intTypedef;
+
+int test (id object)
+{
+ int dummy = 0;
+
+ @try { @throw object; }
+ @catch (int) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (intTypedef) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (int *) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (id) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (id <MyProtocol>) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject *) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject <MyProtocol> *) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ { /* { dg-error "no matching function" "" { target *-*-* } 72 } */
+ dummy++; /* { dg-warning "MyObject" "" { target *-*-* } 13 } */
+ }
+
+ @try { @throw object; }
+ @catch (static MyObject *) /* { dg-error "storage class" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectTypedef *) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectTypedef <MyProtocol> *) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectPtrTypedef) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (Class) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (...) /* Ok */
+ {
+ dummy++;
+ }
+
+ return dummy;
+}
diff --git a/gcc/testsuite/objc.dg/exceptions-1.m b/gcc/testsuite/objc.dg/exceptions-1.m
new file mode 100644
index 0000000..0f3b7e8
--- /dev/null
+++ b/gcc/testsuite/objc.dg/exceptions-1.m
@@ -0,0 +1,42 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* This test checks the syntax @catch (...) which catches any
+ exceptions. At the moment, @catch (...) is identical to @catch (id
+ exception). */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+int test (id object)
+{
+ int i = 0;
+
+ @try
+ {
+ @throw object;
+ }
+ @catch (MyObject *o)
+ {
+ i += 1;
+ }
+ @catch (...)
+ {
+ i += 2;
+ }
+ @finally
+ {
+ i += 4;
+ }
+
+ return i;
+}
diff --git a/gcc/testsuite/objc.dg/exceptions-2.m b/gcc/testsuite/objc.dg/exceptions-2.m
new file mode 100644
index 0000000..3e4227c
--- /dev/null
+++ b/gcc/testsuite/objc.dg/exceptions-2.m
@@ -0,0 +1,52 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-do run } */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-sources "../objc-obj-c++-shared/Object1.m" } */
+
+/* This test checks the syntax @catch (...) which catches any
+ exceptions. Check that code using it runs correctly. */
+
+#include "../objc-obj-c++-shared/Object1.h"
+#include <stdlib.h>
+
+@interface MyObject : Object
+@end
+
+@implementation MyObject
+@end
+
+int test (id object)
+{
+ int i = 0;
+
+ @try
+ {
+ @throw object;
+ }
+ @catch (MyObject *o)
+ {
+ i += 1;
+ }
+ @catch (...)
+ {
+ i += 2;
+ }
+ @finally
+ {
+ i += 4;
+ }
+
+ return i;
+}
+
+int main (void)
+{
+ if (test ([MyObject new]) != 5)
+ abort ();
+
+ if (test ([Object new]) != 6)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/exceptions-3.m b/gcc/testsuite/objc.dg/exceptions-3.m
new file mode 100644
index 0000000..fe9dbfb
--- /dev/null
+++ b/gcc/testsuite/objc.dg/exceptions-3.m
@@ -0,0 +1,114 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* Test that the compiler is checking the argument of @catch(), and
+ produce errors when invalid types are used. */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+@protocol MyProtocol;
+
+typedef MyObject MyObjectTypedef;
+typedef MyObject *MyObjectPtrTypedef;
+typedef int intTypedef;
+
+int test (id object)
+{
+ int dummy = 0;
+
+ @try { @throw object; }
+ @catch (int x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (intTypedef x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (int *x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (id x) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (id <MyProtocol> x) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject *x) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject <MyProtocol> *x) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ { /* { dg-error "conversion to non-scalar type requested" "" { target *-*-* } 72 } */
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (static MyObject *x) /* { dg-error "storage class specified for" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectTypedef *x) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectTypedef <MyProtocol> *x) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectPtrTypedef x) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (Class x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (...) /* Ok */
+ {
+ dummy++;
+ }
+
+ return dummy;
+}
diff --git a/gcc/testsuite/objc.dg/exceptions-4.m b/gcc/testsuite/objc.dg/exceptions-4.m
new file mode 100644
index 0000000..a8a26ec
--- /dev/null
+++ b/gcc/testsuite/objc.dg/exceptions-4.m
@@ -0,0 +1,64 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* Test warnings when parsing syntax errors in @catch(). */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+@interface MyObject2
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject2
+@end
+
+@protocol MyProtocol;
+
+int test (id object)
+{
+ int dummy = 0;
+
+ @try { @throw object; }
+ @catch
+ { /* { dg-error "expected ... before ... token" } */
+ dummy++;
+ }
+ @catch () /* { dg-error "expected declaration specifiers or ..... before ..." } */
+ {
+ dummy++;
+ }
+ @catch (i) /* { dg-error "expected declaration specifiers or ..... before .i." } */
+ {
+ dummy++;
+ }
+ @catch (id <MyProtocol x) /* { dg-error "expected ... before .x." } */
+ { /* { dg-error "@catch parameter can not be protocol-qualified" "" { target *-*-* } 46 } */
+ dummy++;
+ }
+ @catch MyObject *x /* { dg-error "expected ... before .MyObject." } */
+ {
+ dummy++;
+ }
+ @catch MyObject2 *x) /* { dg-error "expected ... before .MyObject2." } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject *x)
+ @catch (MyObject2 *y) /* { dg-error "expected ... before .catch." } */
+
+ return dummy;
+}
diff --git a/gcc/testsuite/objc.dg/exceptions-5.m b/gcc/testsuite/objc.dg/exceptions-5.m
new file mode 100644
index 0000000..d89ad29
--- /dev/null
+++ b/gcc/testsuite/objc.dg/exceptions-5.m
@@ -0,0 +1,114 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* Test that you can use an unnamed argument with @catch. This test is the same
+ as exceptions-3.m, but with no name for @catch arguments. */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+ Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+@protocol MyProtocol;
+
+typedef MyObject MyObjectTypedef;
+typedef MyObject *MyObjectPtrTypedef;
+typedef int intTypedef;
+
+int test (id object)
+{
+ int dummy = 0;
+
+ @try { @throw object; }
+ @catch (int) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (intTypedef) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (int *) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (id) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (id <MyProtocol>) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject *) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject <MyProtocol> *) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObject) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ { /* { dg-error "conversion to non-scalar type requested" "" { target *-*-* } 72 } */
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (static MyObject *) /* { dg-error "storage class specified for" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectTypedef *) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectTypedef <MyProtocol> *) /* { dg-error "@catch parameter can not be protocol-qualified" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (MyObjectPtrTypedef) /* Ok */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (Class) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ {
+ dummy++;
+ }
+
+ @try { @throw object; }
+ @catch (...) /* Ok */
+ {
+ dummy++;
+ }
+
+ return dummy;
+}