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
This commit is contained in:
Nicola Pero 2010-11-29 03:15:40 +00:00 committed by Nicola Pero
parent 45f9cadb2a
commit 437c232224
17 changed files with 1035 additions and 70 deletions

View File

@ -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

View File

@ -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 ();
}

View File

@ -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

View File

@ -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);

View File

@ -1,3 +1,11 @@
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

View File

@ -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;
}
}
}
}

View File

@ -1,3 +1,16 @@
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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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." } */
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}