From 437c23222436111f80b29ec24d2fb863b567e589 Mon Sep 17 00:00:00 2001 From: Nicola Pero Date: Mon, 29 Nov 2010 03:15:40 +0000 Subject: [PATCH] In gcc/objc/: 2010-11-29 Nicola Pero In gcc/objc/: 2010-11-29 Nicola Pero * 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 * 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 * 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 * 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 --- gcc/ChangeLog | 9 +++ gcc/c-parser.c | 90 ++++++++++++++++------ gcc/cp/ChangeLog | 7 ++ gcc/cp/parser.c | 78 +++++++++++++++---- gcc/objc/ChangeLog | 8 ++ gcc/objc/objc-act.c | 126 +++++++++++++++++++++++-------- gcc/testsuite/ChangeLog | 13 ++++ gcc/testsuite/obj-c++.dg/exceptions-1.mm | 42 +++++++++++ gcc/testsuite/obj-c++.dg/exceptions-2.mm | 54 +++++++++++++ gcc/testsuite/obj-c++.dg/exceptions-3.mm | 114 ++++++++++++++++++++++++++++ gcc/testsuite/obj-c++.dg/exceptions-4.mm | 64 ++++++++++++++++ gcc/testsuite/obj-c++.dg/exceptions-5.mm | 114 ++++++++++++++++++++++++++++ gcc/testsuite/objc.dg/exceptions-1.m | 42 +++++++++++ gcc/testsuite/objc.dg/exceptions-2.m | 52 +++++++++++++ gcc/testsuite/objc.dg/exceptions-3.m | 114 ++++++++++++++++++++++++++++ gcc/testsuite/objc.dg/exceptions-4.m | 64 ++++++++++++++++ gcc/testsuite/objc.dg/exceptions-5.m | 114 ++++++++++++++++++++++++++++ 17 files changed, 1035 insertions(+), 70 deletions(-) create mode 100644 gcc/testsuite/obj-c++.dg/exceptions-1.mm create mode 100644 gcc/testsuite/obj-c++.dg/exceptions-2.mm create mode 100644 gcc/testsuite/obj-c++.dg/exceptions-3.mm create mode 100644 gcc/testsuite/obj-c++.dg/exceptions-4.mm create mode 100644 gcc/testsuite/obj-c++.dg/exceptions-5.mm create mode 100644 gcc/testsuite/objc.dg/exceptions-1.m create mode 100644 gcc/testsuite/objc.dg/exceptions-2.m create mode 100644 gcc/testsuite/objc.dg/exceptions-3.m create mode 100644 gcc/testsuite/objc.dg/exceptions-4.m create mode 100644 gcc/testsuite/objc.dg/exceptions-5.m diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bf82ac9e3b3..c20e57e9928 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2010-11-29 Nicola Pero + + * 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 PR tree-optimization/46621 diff --git a/gcc/c-parser.c b/gcc/c-parser.c index c63f001ad4d..879e106ff4d 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 64224016eea..6e3bbbe7eb0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2010-11-29 Nicola Pero + + * 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 PR objc++/46222 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3ed0579538a..917f75043b3 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 ca2833c8800..644129bbc16 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,5 +1,13 @@ 2010-11-29 Nicola Pero + * 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 + * 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 09f4e6f2d1a..810a53af953 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 c7830ebc2b9..6185f595b4d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,18 @@ 2010-11-29 Nicola Pero + * 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 + * 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 00000000000..0f3b7e8ae14 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/exceptions-1.mm @@ -0,0 +1,42 @@ +/* Contributed by Nicola Pero , 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 + +@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 00000000000..ce85b731325 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/exceptions-2.mm @@ -0,0 +1,54 @@ +/* Contributed by Nicola Pero , 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 + +@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 00000000000..b1ba1852725 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/exceptions-3.mm @@ -0,0 +1,114 @@ +/* Contributed by Nicola Pero , 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 + +@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 x) /* { dg-error "@catch parameter can not be protocol-qualified" } */ + { + dummy++; + } + + @try { @throw object; } + @catch (MyObject *x) /* Ok */ + { + dummy++; + } + + @try { @throw object; } + @catch (MyObject *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 *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 00000000000..85debe444b6 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/exceptions-4.mm @@ -0,0 +1,64 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-options "-fobjc-exceptions" } */ +/* { dg-do compile } */ + +/* Test warnings when parsing syntax errors in @catch(). */ + +#include + +@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 , 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 + +@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 ) /* { dg-error "@catch parameter can not be protocol-qualified" } */ + { + dummy++; + } + + @try { @throw object; } + @catch (MyObject *) /* Ok */ + { + dummy++; + } + + @try { @throw object; } + @catch (MyObject *) /* { 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 *) /* { 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 00000000000..0f3b7e8ae14 --- /dev/null +++ b/gcc/testsuite/objc.dg/exceptions-1.m @@ -0,0 +1,42 @@ +/* Contributed by Nicola Pero , 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 + +@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 00000000000..3e4227cb965 --- /dev/null +++ b/gcc/testsuite/objc.dg/exceptions-2.m @@ -0,0 +1,52 @@ +/* Contributed by Nicola Pero , 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 + +@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 00000000000..fe9dbfbfa06 --- /dev/null +++ b/gcc/testsuite/objc.dg/exceptions-3.m @@ -0,0 +1,114 @@ +/* Contributed by Nicola Pero , 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 + +@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 x) /* { dg-error "@catch parameter can not be protocol-qualified" } */ + { + dummy++; + } + + @try { @throw object; } + @catch (MyObject *x) /* Ok */ + { + dummy++; + } + + @try { @throw object; } + @catch (MyObject *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 *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 00000000000..a8a26ecebb2 --- /dev/null +++ b/gcc/testsuite/objc.dg/exceptions-4.m @@ -0,0 +1,64 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-options "-fobjc-exceptions" } */ +/* { dg-do compile } */ + +/* Test warnings when parsing syntax errors in @catch(). */ + +#include + +@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 , 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 + +@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 ) /* { dg-error "@catch parameter can not be protocol-qualified" } */ + { + dummy++; + } + + @try { @throw object; } + @catch (MyObject *) /* Ok */ + { + dummy++; + } + + @try { @throw object; } + @catch (MyObject *) /* { 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 *) /* { 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; +} -- 2.11.4.GIT