In gcc/: 2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/: 2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com> * c-parser.c (c_parser_objc_class_definition): Recognize Objective-C 2.0 class extensions. In gcc/cp/: 2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com> * parser.c (cp_parser_objc_superclass_or_category): Recognize Objective-C 2.0 class extensions. Added iface_p and is_class_extension arguments. (cp_parser_objc_class_interface): Updated call to cp_parser_objc_superclass_or_category. (cp_parser_objc_class_implementation): Same change. In gcc/objc/: 2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com> * objc-act.c (objc_in_class_extension): New. (objc_start_category_interface): If -fobjc-std=objc1 was specified, produce an error if a class extension is used. (objc_finish_interface): Reset objc_in_class_extension to false. (objc_add_property_declaration): Allow a class extension to extend readonly properties in the main @interface to be readwrite. (start_class): Added code to deal with class extensions. In that case, return the existing interface after adding any additional protocols to it and setting objc_in_class_extension to true. (continue_class): If in a class extension, do not generate the instance variable template. In gcc/testsuite/: 2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com> * objc.dg/class-extension-1.m: New. * objc.dg/class-extension-2.m: New. * objc.dg/class-extension-3.m: New. * objc.dg/property/at-property-26.m: New. * objc.dg/property/at-property-27.m: New. * objc.dg/property/at-property-28.m: New. * obj-c++.dg/class-extension-1.mm: New. * obj-c++.dg/class-extension-2.mm: New. * obj-c++.dg/class-extension-3.mm: New. * obj-c++.dg/property/at-property-26.mm: New. * obj-c++.dg/property/at-property-27.mm: New. * obj-c++.dg/property/at-property-28.mm: New. From-SVN: r167680
This commit is contained in:
parent
aff7f4c416
commit
ec3e9f8267
19 changed files with 812 additions and 76 deletions
|
@ -1,3 +1,8 @@
|
|||
2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* c-parser.c (c_parser_objc_class_definition): Recognize
|
||||
Objective-C 2.0 class extensions.
|
||||
|
||||
2010-12-10 Iain Sandoe <iains@gcc.gnu.org>
|
||||
|
||||
* config/darwin.c: Remove c-tree.h and c-lang.h
|
||||
|
|
|
@ -6743,6 +6743,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
|
|||
objc-class-instance-variables[opt]
|
||||
@interface identifier ( identifier ) objc-protocol-refs[opt]
|
||||
objc-methodprotolist @end
|
||||
@interface identifier ( ) objc-protocol-refs[opt]
|
||||
objc-methodprotolist @end
|
||||
@implementation identifier ( identifier )
|
||||
|
||||
objc-superclass:
|
||||
|
@ -6777,17 +6779,29 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes)
|
|||
c_parser_consume_token (parser);
|
||||
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
|
||||
{
|
||||
/* We have a category or class extension. */
|
||||
tree id2;
|
||||
tree proto = NULL_TREE;
|
||||
c_parser_consume_token (parser);
|
||||
if (c_parser_next_token_is_not (parser, CPP_NAME))
|
||||
{
|
||||
c_parser_error (parser, "expected identifier");
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
return;
|
||||
if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
|
||||
{
|
||||
/* We have a class extension. */
|
||||
id2 = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_parser_error (parser, "expected identifier or %<)%>");
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id2 = c_parser_peek_token (parser)->value;
|
||||
c_parser_consume_token (parser);
|
||||
}
|
||||
id2 = c_parser_peek_token (parser)->value;
|
||||
c_parser_consume_token (parser);
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
|
||||
if (!iface_p)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* parser.c (cp_parser_objc_superclass_or_category): Recognize
|
||||
Objective-C 2.0 class extensions. Added iface_p and
|
||||
is_class_extension arguments.
|
||||
(cp_parser_objc_class_interface): Updated call to
|
||||
cp_parser_objc_superclass_or_category.
|
||||
(cp_parser_objc_class_implementation): Same change.
|
||||
|
||||
2010-12-09 Nathan Froyd <froydnj@codesourcery.com>
|
||||
|
||||
* call.c (print_conversion_rejection): Indent messages two spaces.
|
||||
|
|
|
@ -22435,12 +22435,15 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
|
|||
/* Parse an Objective-C superclass or category. */
|
||||
|
||||
static void
|
||||
cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
|
||||
tree *categ)
|
||||
cp_parser_objc_superclass_or_category (cp_parser *parser,
|
||||
bool iface_p,
|
||||
tree *super,
|
||||
tree *categ, bool *is_class_extension)
|
||||
{
|
||||
cp_token *next = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
*super = *categ = NULL_TREE;
|
||||
*is_class_extension = false;
|
||||
if (next->type == CPP_COLON)
|
||||
{
|
||||
cp_lexer_consume_token (parser->lexer); /* Eat ':'. */
|
||||
|
@ -22449,7 +22452,17 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
|
|||
else if (next->type == CPP_OPEN_PAREN)
|
||||
{
|
||||
cp_lexer_consume_token (parser->lexer); /* Eat '('. */
|
||||
*categ = cp_parser_identifier (parser);
|
||||
|
||||
/* If there is no category name, and this is an @interface, we
|
||||
have a class extension. */
|
||||
if (iface_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
|
||||
{
|
||||
*categ = NULL_TREE;
|
||||
*is_class_extension = true;
|
||||
}
|
||||
else
|
||||
*categ = cp_parser_identifier (parser);
|
||||
|
||||
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
||||
}
|
||||
}
|
||||
|
@ -22460,6 +22473,7 @@ static void
|
|||
cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
|
||||
{
|
||||
tree name, super, categ, protos;
|
||||
bool is_class_extension;
|
||||
|
||||
cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
|
||||
name = cp_parser_identifier (parser);
|
||||
|
@ -22472,11 +22486,12 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
|
|||
*/
|
||||
return;
|
||||
}
|
||||
cp_parser_objc_superclass_or_category (parser, &super, &categ);
|
||||
cp_parser_objc_superclass_or_category (parser, true, &super, &categ,
|
||||
&is_class_extension);
|
||||
protos = cp_parser_objc_protocol_refs_opt (parser);
|
||||
|
||||
/* We have either a class or a category on our hands. */
|
||||
if (categ)
|
||||
if (categ || is_class_extension)
|
||||
objc_start_category_interface (name, categ, protos, attributes);
|
||||
else
|
||||
{
|
||||
|
@ -22495,6 +22510,7 @@ static void
|
|||
cp_parser_objc_class_implementation (cp_parser* parser)
|
||||
{
|
||||
tree name, super, categ;
|
||||
bool is_class_extension;
|
||||
|
||||
cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */
|
||||
name = cp_parser_identifier (parser);
|
||||
|
@ -22508,7 +22524,8 @@ cp_parser_objc_class_implementation (cp_parser* parser)
|
|||
*/
|
||||
return;
|
||||
}
|
||||
cp_parser_objc_superclass_or_category (parser, &super, &categ);
|
||||
cp_parser_objc_superclass_or_category (parser, false, &super, &categ,
|
||||
&is_class_extension);
|
||||
|
||||
/* We have either a class or a category on our hands. */
|
||||
if (categ)
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* objc-act.c (objc_in_class_extension): New.
|
||||
(objc_start_category_interface): If -fobjc-std=objc1
|
||||
was specified, produce an error if a class extension is used.
|
||||
(objc_finish_interface): Reset objc_in_class_extension to false.
|
||||
(objc_add_property_declaration): Allow a class extension to extend
|
||||
readonly properties in the main @interface to be readwrite.
|
||||
(start_class): Added code to deal with class extensions. In that
|
||||
case, return the existing interface after adding any additional
|
||||
protocols to it and setting objc_in_class_extension to true.
|
||||
(continue_class): If in a class extension, do not generate the
|
||||
instance variable template.
|
||||
|
||||
2010-12-08 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* objc-act.c (objc_build_throw_stmt): Check that the argument of
|
||||
|
|
|
@ -402,6 +402,12 @@ static bool objc_method_optional_flag = false;
|
|||
|
||||
static int objc_collecting_ivars = 0;
|
||||
|
||||
/* Flag that is set to 'true' while we are processing a class
|
||||
extension. Since a class extension just "reopens" the main
|
||||
@interface, this can be used to determine if we are in the main
|
||||
@interface, or in a class extension. */
|
||||
static bool objc_in_class_extension = false;
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
static char *errbuf; /* Buffer for error diagnostics */
|
||||
|
@ -748,6 +754,11 @@ objc_start_category_interface (tree klass, tree categ,
|
|||
"category attributes are not available in this version"
|
||||
" of the compiler, (ignored)");
|
||||
}
|
||||
if (categ == NULL_TREE)
|
||||
{
|
||||
if (flag_objc1_only)
|
||||
error_at (input_location, "class extensions are not available in Objective-C 1.0");
|
||||
}
|
||||
objc_interface_context
|
||||
= start_class (CATEGORY_INTERFACE_TYPE, klass, categ, protos, NULL_TREE);
|
||||
objc_ivar_chain
|
||||
|
@ -778,6 +789,7 @@ objc_finish_interface (void)
|
|||
finish_class (objc_interface_context);
|
||||
objc_interface_context = NULL_TREE;
|
||||
objc_method_optional_flag = false;
|
||||
objc_in_class_extension = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -952,6 +964,7 @@ objc_add_property_declaration (location_t location, tree decl,
|
|||
is readwrite). */
|
||||
bool property_readonly = false;
|
||||
objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
|
||||
bool property_extension_in_class_extension = false;
|
||||
|
||||
if (flag_objc1_only)
|
||||
error_at (input_location, "%<@property%> is not available in Objective-C 1.0");
|
||||
|
@ -1125,60 +1138,80 @@ objc_add_property_declaration (location_t location, tree decl,
|
|||
|
||||
/* Check for duplicate property declarations. We first check the
|
||||
immediate context for a property with the same name. Any such
|
||||
declarations are an error. */
|
||||
declarations are an error, unless this is a class extension and
|
||||
we are extending a property from readonly to readwrite. */
|
||||
for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
|
||||
{
|
||||
if (PROPERTY_NAME (x) == DECL_NAME (decl))
|
||||
{
|
||||
location_t original_location = DECL_SOURCE_LOCATION (x);
|
||||
|
||||
error_at (location, "redeclaration of property %qD", decl);
|
||||
|
||||
if (original_location != UNKNOWN_LOCATION)
|
||||
inform (original_location, "originally specified here");
|
||||
return;
|
||||
}
|
||||
if (objc_in_class_extension
|
||||
&& property_readonly == 0
|
||||
&& PROPERTY_READONLY (x) == 1)
|
||||
{
|
||||
/* This is a class extension, and we are extending an
|
||||
existing readonly property to a readwrite one.
|
||||
That's fine. :-) */
|
||||
property_extension_in_class_extension = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
location_t original_location = DECL_SOURCE_LOCATION (x);
|
||||
|
||||
error_at (location, "redeclaration of property %qD", decl);
|
||||
|
||||
if (original_location != UNKNOWN_LOCATION)
|
||||
inform (original_location, "originally specified here");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We now need to check for existing property declarations (in the
|
||||
superclass, other categories or protocols) and check that the new
|
||||
declaration is not in conflict with existing ones. */
|
||||
|
||||
/* Search for a previous, existing declaration of a property with
|
||||
the same name in superclasses, protocols etc. If one is found,
|
||||
it will be in the 'x' variable. */
|
||||
x = NULL_TREE;
|
||||
|
||||
/* Note that, for simplicity, the following may search again the
|
||||
local context. That's Ok as nothing will be found (else we'd
|
||||
have thrown an error above); it's only a little inefficient, but
|
||||
the code is simpler. */
|
||||
switch (TREE_CODE (objc_interface_context))
|
||||
/* If x is not NULL_TREE, we must be in a class extension and we're
|
||||
extending a readonly property. In that case, no point in
|
||||
searching for another declaration. */
|
||||
if (x == NULL_TREE)
|
||||
{
|
||||
case CLASS_INTERFACE_TYPE:
|
||||
/* Look up the property in the current @interface (which will
|
||||
find nothing), then its protocols and categories and
|
||||
superclasses. */
|
||||
x = lookup_property (objc_interface_context, DECL_NAME (decl));
|
||||
break;
|
||||
case CATEGORY_INTERFACE_TYPE:
|
||||
/* Look up the property in the main @interface, then protocols
|
||||
and categories (one of them is ours, and will find nothing)
|
||||
and superclasses. */
|
||||
x = lookup_property (lookup_interface (CLASS_NAME (objc_interface_context)),
|
||||
DECL_NAME (decl));
|
||||
break;
|
||||
case PROTOCOL_INTERFACE_TYPE:
|
||||
/* Looks up the property in any protocols attached to the
|
||||
current protocol. */
|
||||
if (PROTOCOL_LIST (objc_interface_context))
|
||||
/* We now need to check for existing property declarations (in
|
||||
the superclass, other categories or protocols) and check that
|
||||
the new declaration is not in conflict with existing
|
||||
ones. */
|
||||
|
||||
/* Search for a previous, existing declaration of a property
|
||||
with the same name in superclasses, protocols etc. If one is
|
||||
found, it will be in the 'x' variable. */
|
||||
|
||||
/* Note that, for simplicity, the following may search again the
|
||||
local context. That's Ok as nothing will be found (else we'd
|
||||
have thrown an error above); it's only a little inefficient,
|
||||
but the code is simpler. */
|
||||
switch (TREE_CODE (objc_interface_context))
|
||||
{
|
||||
x = lookup_property_in_protocol_list (PROTOCOL_LIST (objc_interface_context),
|
||||
DECL_NAME (decl));
|
||||
case CLASS_INTERFACE_TYPE:
|
||||
/* Look up the property in the current @interface (which
|
||||
will find nothing), then its protocols and categories and
|
||||
superclasses. */
|
||||
x = lookup_property (objc_interface_context, DECL_NAME (decl));
|
||||
break;
|
||||
case CATEGORY_INTERFACE_TYPE:
|
||||
/* Look up the property in the main @interface, then
|
||||
protocols and categories (one of them is ours, and will
|
||||
find nothing) and superclasses. */
|
||||
x = lookup_property (lookup_interface (CLASS_NAME (objc_interface_context)),
|
||||
DECL_NAME (decl));
|
||||
break;
|
||||
case PROTOCOL_INTERFACE_TYPE:
|
||||
/* Looks up the property in any protocols attached to the
|
||||
current protocol. */
|
||||
if (PROTOCOL_LIST (objc_interface_context))
|
||||
{
|
||||
x = lookup_property_in_protocol_list (PROTOCOL_LIST (objc_interface_context),
|
||||
DECL_NAME (decl));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
if (x != NULL_TREE)
|
||||
|
@ -1278,6 +1311,17 @@ objc_add_property_declaration (location_t location, tree decl,
|
|||
inform (original_location, "originally specified here");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we are in a class extension and we're extending a readonly
|
||||
property in the main @interface, we'll just update the
|
||||
existing property with the readwrite flag and potentially the
|
||||
new setter name. */
|
||||
if (property_extension_in_class_extension)
|
||||
{
|
||||
PROPERTY_READONLY (x) = 0;
|
||||
PROPERTY_SETTER_NAME (x) = parsed_property_setter_ident;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a PROPERTY_DECL node. */
|
||||
|
@ -9417,21 +9461,24 @@ check_protocols (tree proto_list, const char *type, tree name)
|
|||
}
|
||||
}
|
||||
|
||||
/* Make sure that the class CLASS_NAME is defined
|
||||
CODE says which kind of thing CLASS_NAME ought to be.
|
||||
It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
|
||||
CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. */
|
||||
|
||||
/* Make sure that the class CLASS_NAME is defined CODE says which kind
|
||||
of thing CLASS_NAME ought to be. It can be CLASS_INTERFACE_TYPE,
|
||||
CLASS_IMPLEMENTATION_TYPE, CATEGORY_INTERFACE_TYPE, or
|
||||
CATEGORY_IMPLEMENTATION_TYPE. For a CATEGORY_INTERFACE_TYPE,
|
||||
SUPER_NAME is the name of the category. For a class extension,
|
||||
CODE is CATEGORY_INTERFACE_TYPE and SUPER_NAME is NULL_TREE. */
|
||||
static tree
|
||||
start_class (enum tree_code code, tree class_name, tree super_name,
|
||||
tree protocol_list, tree attributes)
|
||||
{
|
||||
tree klass, decl;
|
||||
tree klass = NULL_TREE;
|
||||
tree decl;
|
||||
|
||||
#ifdef OBJCPLUS
|
||||
if (current_namespace != global_namespace) {
|
||||
error ("Objective-C declarations may only appear in global scope");
|
||||
}
|
||||
if (current_namespace != global_namespace)
|
||||
{
|
||||
error ("Objective-C declarations may only appear in global scope");
|
||||
}
|
||||
#endif /* OBJCPLUS */
|
||||
|
||||
if (objc_implementation_context)
|
||||
|
@ -9442,8 +9489,14 @@ start_class (enum tree_code code, tree class_name, tree super_name,
|
|||
objc_implementation_context = NULL_TREE;
|
||||
}
|
||||
|
||||
klass = make_node (code);
|
||||
TYPE_LANG_SLOT_1 (klass) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
|
||||
/* If this is a class extension, we'll be "reopening" the existing
|
||||
CLASS_INTERFACE_TYPE, so in that case there is no need to create
|
||||
a new node. */
|
||||
if (code != CATEGORY_INTERFACE_TYPE || super_name != NULL_TREE)
|
||||
{
|
||||
klass = make_node (code);
|
||||
TYPE_LANG_SLOT_1 (klass) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
|
||||
}
|
||||
|
||||
/* Check for existence of the super class, if one was specified. Note
|
||||
that we must have seen an @interface, not just a @class. If we
|
||||
|
@ -9473,9 +9526,12 @@ start_class (enum tree_code code, tree class_name, tree super_name,
|
|||
}
|
||||
}
|
||||
|
||||
CLASS_NAME (klass) = class_name;
|
||||
CLASS_SUPER_NAME (klass) = super_name;
|
||||
CLASS_CLS_METHODS (klass) = NULL_TREE;
|
||||
if (code != CATEGORY_INTERFACE_TYPE || super_name != NULL_TREE)
|
||||
{
|
||||
CLASS_NAME (klass) = class_name;
|
||||
CLASS_SUPER_NAME (klass) = super_name;
|
||||
CLASS_CLS_METHODS (klass) = NULL_TREE;
|
||||
}
|
||||
|
||||
if (! objc_is_class_name (class_name)
|
||||
&& (decl = lookup_name (class_name)))
|
||||
|
@ -9592,15 +9648,35 @@ start_class (enum tree_code code, tree class_name, tree super_name,
|
|||
if (TREE_DEPRECATED (class_category_is_assoc_with))
|
||||
warning (OPT_Wdeprecated_declarations, "class %qE is deprecated",
|
||||
class_name);
|
||||
add_category (class_category_is_assoc_with, klass);
|
||||
}
|
||||
|
||||
if (protocol_list)
|
||||
CLASS_PROTOCOL_LIST (klass)
|
||||
= lookup_and_install_protocols (protocol_list);
|
||||
if (super_name == NULL_TREE)
|
||||
{
|
||||
/* This is a class extension. Get the original
|
||||
interface, and continue working on it. */
|
||||
objc_in_class_extension = true;
|
||||
klass = class_category_is_assoc_with;
|
||||
|
||||
if (protocol_list)
|
||||
{
|
||||
/* Append protocols to the original protocol
|
||||
list. */
|
||||
CLASS_PROTOCOL_LIST (klass)
|
||||
= chainon (CLASS_PROTOCOL_LIST (klass),
|
||||
lookup_and_install_protocols (protocol_list));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
add_category (class_category_is_assoc_with, klass);
|
||||
|
||||
if (protocol_list)
|
||||
CLASS_PROTOCOL_LIST (klass)
|
||||
= lookup_and_install_protocols (protocol_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case CATEGORY_IMPLEMENTATION_TYPE:
|
||||
/* Reset for multiple classes per file. */
|
||||
method_slot = 0;
|
||||
|
@ -9673,6 +9749,8 @@ continue_class (tree klass)
|
|||
}
|
||||
case CLASS_INTERFACE_TYPE:
|
||||
{
|
||||
if (objc_in_class_extension)
|
||||
return NULL_TREE;
|
||||
#ifdef OBJCPLUS
|
||||
push_lang_context (lang_name_c);
|
||||
#endif /* OBJCPLUS */
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* objc.dg/class-extension-1.m: New.
|
||||
* objc.dg/class-extension-2.m: New.
|
||||
* objc.dg/class-extension-3.m: New.
|
||||
* objc.dg/property/at-property-26.m: New.
|
||||
* objc.dg/property/at-property-27.m: New.
|
||||
* objc.dg/property/at-property-28.m: New.
|
||||
* obj-c++.dg/class-extension-1.mm: New.
|
||||
* obj-c++.dg/class-extension-2.mm: New.
|
||||
* obj-c++.dg/class-extension-3.mm: New.
|
||||
* obj-c++.dg/property/at-property-26.mm: New.
|
||||
* obj-c++.dg/property/at-property-27.mm: New.
|
||||
* obj-c++.dg/property/at-property-28.mm: New.
|
||||
|
||||
2010-12-09 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||
|
||||
PR target/46057
|
||||
|
|
30
gcc/testsuite/obj-c++.dg/class-extension-1.mm
Normal file
30
gcc/testsuite/obj-c++.dg/class-extension-1.mm
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* This test tests the basic of class extensions. */
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
@interface MyObject
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
- (int) test;
|
||||
@end
|
||||
|
||||
@interface MyObject ()
|
||||
- (int) test2;
|
||||
- (int) test3;
|
||||
@end
|
||||
|
||||
@implementation MyObject
|
||||
- (int) test
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
- (int) test2
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
@end /* { dg-warning "incomplete implementation of class .MyObject." } */
|
||||
/* { dg-warning "method definition for .-test3. not found" "" { target *-*-* } 29 } */
|
56
gcc/testsuite/obj-c++.dg/class-extension-2.mm
Normal file
56
gcc/testsuite/obj-c++.dg/class-extension-2.mm
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* This test tests class extensions and protocols. */
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
/* First, a simple test where a plain class has a protocol attached to
|
||||
it in a class extension. */
|
||||
@interface MyObject
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
@end
|
||||
|
||||
@protocol MyProtocol
|
||||
- (void) test;
|
||||
@end
|
||||
|
||||
@interface MyObject () <MyProtocol>
|
||||
@end
|
||||
|
||||
@implementation MyObject
|
||||
@end /* { dg-warning "incomplete implementation of class .MyObject." } */
|
||||
/* { dg-warning "method definition for .-test. not found" "" { target *-*-* } 24 } */
|
||||
/* { dg-warning "class .MyObject. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 24 } */
|
||||
|
||||
|
||||
|
||||
/* Second, a more interesting test where protocols are added from the
|
||||
main class and from two different class extensions. */
|
||||
@interface MyObject2 : MyObject <MyProtocol>
|
||||
@end
|
||||
|
||||
@protocol MyProtocol2
|
||||
- (void) test2;
|
||||
@end
|
||||
|
||||
@protocol MyProtocol3
|
||||
- (void) test3;
|
||||
@end
|
||||
|
||||
@interface MyObject2 () <MyProtocol2>
|
||||
@end
|
||||
|
||||
@interface MyObject2 () <MyProtocol3>
|
||||
@end
|
||||
|
||||
@implementation MyObject2
|
||||
@end /* { dg-warning "incomplete implementation of class .MyObject2." } */
|
||||
/* { dg-warning "method definition for .-test. not found" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "method definition for .-test2. not found" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol2. protocol" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "method definition for .-test3. not found" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol3. protocol" "" { target *-*-* } 50 } */
|
26
gcc/testsuite/obj-c++.dg/class-extension-3.mm
Normal file
26
gcc/testsuite/obj-c++.dg/class-extension-3.mm
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* This test tests warnings on class extensions. */
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
@interface MyObject
|
||||
{
|
||||
Class isa;
|
||||
int count;
|
||||
}
|
||||
- (int) test;
|
||||
@property int count; /* { dg-warning "originally specified here" } */
|
||||
@end
|
||||
|
||||
@interface MyObject ()
|
||||
- (void) test; /* { dg-error "duplicate declaration of method .-test." } */
|
||||
@end
|
||||
|
||||
@interface MyObject ()
|
||||
@end
|
||||
|
||||
@interface MyObject ()
|
||||
@property int count; /* { dg-error "redeclaration of property .count." } */
|
||||
@end
|
85
gcc/testsuite/obj-c++.dg/property/at-property-26.mm
Normal file
85
gcc/testsuite/obj-c++.dg/property/at-property-26.mm
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
|
||||
|
||||
/* Test @properties in class extensions. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
+ (id) initialize;
|
||||
+ (id) alloc;
|
||||
- (id) init;
|
||||
@end
|
||||
|
||||
@implementation MyRootClass
|
||||
+ (id) initialize { return self; }
|
||||
+ (id) alloc { return class_createInstance (self, 0); }
|
||||
- (id) init { return self; }
|
||||
@end
|
||||
|
||||
@protocol count4
|
||||
/* Use a different getters/setters, so that the only way to compile
|
||||
object.countX is to find the actual @property. */
|
||||
@property (getter=number4, setter=setNumber4:) int count4;
|
||||
@end
|
||||
|
||||
@interface MySubClass : MyRootClass
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
int count3;
|
||||
int count4;
|
||||
}
|
||||
@property (getter=number1, setter=setNumber1:) int count1;
|
||||
@end
|
||||
|
||||
@interface MySubClass ()
|
||||
@property (getter=number2, setter=setNumber2:) int count2;
|
||||
@end
|
||||
|
||||
@interface MySubClass () <count4>
|
||||
@property (getter=number3, setter=setNumber3:) int count3;
|
||||
@end
|
||||
|
||||
@implementation MySubClass
|
||||
@synthesize count1;
|
||||
@synthesize count2;
|
||||
- (int) number3
|
||||
{
|
||||
return count3;
|
||||
}
|
||||
- (void) setNumber3: (int)value
|
||||
{
|
||||
count3 = value;
|
||||
}
|
||||
@synthesize count4;
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MySubClass *object = [[MySubClass alloc] init];
|
||||
|
||||
object.count1 = 20;
|
||||
if (object.count1 != 20)
|
||||
abort ();
|
||||
|
||||
object.count2 = 11;
|
||||
if (object.count2 != 11)
|
||||
abort ();
|
||||
|
||||
object.count3 = 19;
|
||||
if (object.count3 != 19)
|
||||
abort ();
|
||||
|
||||
object.count4 = 74;
|
||||
if (object.count4 != 74)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
66
gcc/testsuite/obj-c++.dg/property/at-property-27.mm
Normal file
66
gcc/testsuite/obj-c++.dg/property/at-property-27.mm
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
|
||||
|
||||
/* Test overriding a readonly @property with a readwrite one in a class extension. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
+ (id) initialize;
|
||||
+ (id) alloc;
|
||||
- (id) init;
|
||||
@end
|
||||
|
||||
@implementation MyRootClass
|
||||
+ (id) initialize { return self; }
|
||||
+ (id) alloc { return class_createInstance (self, 0); }
|
||||
- (id) init { return self; }
|
||||
@end
|
||||
|
||||
@protocol count2
|
||||
/* Use a different getters/setters, so that the only way to compile
|
||||
object.countX is to find the actual @property. */
|
||||
@property (readonly, getter=number2) int count2;
|
||||
@end
|
||||
|
||||
@interface MySubClass : MyRootClass
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
}
|
||||
@property (readonly, getter=number1) int count1;
|
||||
@end
|
||||
|
||||
@interface MySubClass ()
|
||||
@property (readwrite, getter=number1, setter=setNumber1:) int count1;
|
||||
@end
|
||||
|
||||
@interface MySubClass () <count2>
|
||||
@property (readwrite, getter=number2, setter=setNumber2:) int count2;
|
||||
@end
|
||||
|
||||
@implementation MySubClass
|
||||
@synthesize count1;
|
||||
@synthesize count2;
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MySubClass *object = [[MySubClass alloc] init];
|
||||
|
||||
object.count1 = 20;
|
||||
if (object.count1 != 20)
|
||||
abort ();
|
||||
|
||||
object.count2 = 11;
|
||||
if (object.count2 != 11)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
29
gcc/testsuite/obj-c++.dg/property/at-property-28.mm
Normal file
29
gcc/testsuite/obj-c++.dg/property/at-property-28.mm
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* Test errors when extending a property in a class extension. */
|
||||
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
@property (readonly, retain) id property1; /* { dg-warning "originally specified here" } */
|
||||
@property (readonly) int property2; /* { dg-warning "originally specified here" } */
|
||||
@property (readonly, getter=y) int property3; /* { dg-warning "originally specified here" } */
|
||||
@property (readonly) int property4; /* Ok */
|
||||
@property (readonly) int property5; /* { dg-warning "originally specified here" } */
|
||||
@end
|
||||
|
||||
@interface MyRootClass ()
|
||||
@property (readwrite, copy) id property1; /* { dg-warning "assign semantics attributes of property .property1. conflict with previous declaration" } */
|
||||
@property (readwrite, nonatomic) int property2; /* { dg-warning ".nonatomic. attribute of property .property2. conflicts with previous declaration" } */
|
||||
@property (readwrite, getter=x) int property3; /* { dg-warning ".getter. attribute of property .property3. conflicts with previous declaration" } */
|
||||
@property (readwrite) int property4; /* Ok */
|
||||
@property (readwrite) float property5; /* { dg-warning "type of property .property5. conflicts with previous declaration" } */
|
||||
@end
|
||||
|
||||
|
||||
|
30
gcc/testsuite/objc.dg/class-extension-1.m
Normal file
30
gcc/testsuite/objc.dg/class-extension-1.m
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* This test tests the basic of class extensions. */
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
@interface MyObject
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
- (int) test;
|
||||
@end
|
||||
|
||||
@interface MyObject ()
|
||||
- (int) test2;
|
||||
- (int) test3;
|
||||
@end
|
||||
|
||||
@implementation MyObject
|
||||
- (int) test
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
- (int) test2
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
@end /* { dg-warning "incomplete implementation of class .MyObject." } */
|
||||
/* { dg-warning "method definition for .-test3. not found" "" { target *-*-* } 29 } */
|
56
gcc/testsuite/objc.dg/class-extension-2.m
Normal file
56
gcc/testsuite/objc.dg/class-extension-2.m
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* This test tests class extensions and protocols. */
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
/* First, a simple test where a plain class has a protocol attached to
|
||||
it in a class extension. */
|
||||
@interface MyObject
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
@end
|
||||
|
||||
@protocol MyProtocol
|
||||
- (void) test;
|
||||
@end
|
||||
|
||||
@interface MyObject () <MyProtocol>
|
||||
@end
|
||||
|
||||
@implementation MyObject
|
||||
@end /* { dg-warning "incomplete implementation of class .MyObject." } */
|
||||
/* { dg-warning "method definition for .-test. not found" "" { target *-*-* } 24 } */
|
||||
/* { dg-warning "class .MyObject. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 24 } */
|
||||
|
||||
|
||||
|
||||
/* Second, a more interesting test where protocols are added from the
|
||||
main class and from two different class extensions. */
|
||||
@interface MyObject2 : MyObject <MyProtocol>
|
||||
@end
|
||||
|
||||
@protocol MyProtocol2
|
||||
- (void) test2;
|
||||
@end
|
||||
|
||||
@protocol MyProtocol3
|
||||
- (void) test3;
|
||||
@end
|
||||
|
||||
@interface MyObject2 () <MyProtocol2>
|
||||
@end
|
||||
|
||||
@interface MyObject2 () <MyProtocol3>
|
||||
@end
|
||||
|
||||
@implementation MyObject2
|
||||
@end /* { dg-warning "incomplete implementation of class .MyObject2." } */
|
||||
/* { dg-warning "method definition for .-test. not found" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "method definition for .-test2. not found" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol2. protocol" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "method definition for .-test3. not found" "" { target *-*-* } 50 } */
|
||||
/* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol3. protocol" "" { target *-*-* } 50 } */
|
26
gcc/testsuite/objc.dg/class-extension-3.m
Normal file
26
gcc/testsuite/objc.dg/class-extension-3.m
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* This test tests warnings on class extensions. */
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
@interface MyObject
|
||||
{
|
||||
Class isa;
|
||||
int count;
|
||||
}
|
||||
- (int) test;
|
||||
@property int count; /* { dg-message "originally specified here" } */
|
||||
@end
|
||||
|
||||
@interface MyObject ()
|
||||
- (void) test; /* { dg-error "duplicate declaration of method .-test." } */
|
||||
@end
|
||||
|
||||
@interface MyObject ()
|
||||
@end
|
||||
|
||||
@interface MyObject ()
|
||||
@property int count; /* { dg-error "redeclaration of property .count." } */
|
||||
@end
|
85
gcc/testsuite/objc.dg/property/at-property-26.m
Normal file
85
gcc/testsuite/objc.dg/property/at-property-26.m
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
|
||||
|
||||
/* Test @properties in class extensions. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
+ (id) initialize;
|
||||
+ (id) alloc;
|
||||
- (id) init;
|
||||
@end
|
||||
|
||||
@implementation MyRootClass
|
||||
+ (id) initialize { return self; }
|
||||
+ (id) alloc { return class_createInstance (self, 0); }
|
||||
- (id) init { return self; }
|
||||
@end
|
||||
|
||||
@protocol count4
|
||||
/* Use a different getters/setters, so that the only way to compile
|
||||
object.countX is to find the actual @property. */
|
||||
@property (getter=number4, setter=setNumber4:) int count4;
|
||||
@end
|
||||
|
||||
@interface MySubClass : MyRootClass
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
int count3;
|
||||
int count4;
|
||||
}
|
||||
@property (getter=number1, setter=setNumber1:) int count1;
|
||||
@end
|
||||
|
||||
@interface MySubClass ()
|
||||
@property (getter=number2, setter=setNumber2:) int count2;
|
||||
@end
|
||||
|
||||
@interface MySubClass () <count4>
|
||||
@property (getter=number3, setter=setNumber3:) int count3;
|
||||
@end
|
||||
|
||||
@implementation MySubClass
|
||||
@synthesize count1;
|
||||
@synthesize count2;
|
||||
- (int) number3
|
||||
{
|
||||
return count3;
|
||||
}
|
||||
- (void) setNumber3: (int)value
|
||||
{
|
||||
count3 = value;
|
||||
}
|
||||
@synthesize count4;
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MySubClass *object = [[MySubClass alloc] init];
|
||||
|
||||
object.count1 = 20;
|
||||
if (object.count1 != 20)
|
||||
abort ();
|
||||
|
||||
object.count2 = 11;
|
||||
if (object.count2 != 11)
|
||||
abort ();
|
||||
|
||||
object.count3 = 19;
|
||||
if (object.count3 != 19)
|
||||
abort ();
|
||||
|
||||
object.count4 = 74;
|
||||
if (object.count4 != 74)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
66
gcc/testsuite/objc.dg/property/at-property-27.m
Normal file
66
gcc/testsuite/objc.dg/property/at-property-27.m
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
|
||||
|
||||
/* Test overriding a readonly @property with a readwrite one in a class extension. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
+ (id) initialize;
|
||||
+ (id) alloc;
|
||||
- (id) init;
|
||||
@end
|
||||
|
||||
@implementation MyRootClass
|
||||
+ (id) initialize { return self; }
|
||||
+ (id) alloc { return class_createInstance (self, 0); }
|
||||
- (id) init { return self; }
|
||||
@end
|
||||
|
||||
@protocol count2
|
||||
/* Use a different getters/setters, so that the only way to compile
|
||||
object.countX is to find the actual @property. */
|
||||
@property (readonly, getter=number2) int count2;
|
||||
@end
|
||||
|
||||
@interface MySubClass : MyRootClass
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
}
|
||||
@property (readonly, getter=number1) int count1;
|
||||
@end
|
||||
|
||||
@interface MySubClass ()
|
||||
@property (readwrite, getter=number1, setter=setNumber1:) int count1;
|
||||
@end
|
||||
|
||||
@interface MySubClass () <count2>
|
||||
@property (readwrite, getter=number2, setter=setNumber2:) int count2;
|
||||
@end
|
||||
|
||||
@implementation MySubClass
|
||||
@synthesize count1;
|
||||
@synthesize count2;
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MySubClass *object = [[MySubClass alloc] init];
|
||||
|
||||
object.count1 = 20;
|
||||
if (object.count1 != 20)
|
||||
abort ();
|
||||
|
||||
object.count2 = 11;
|
||||
if (object.count2 != 11)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
29
gcc/testsuite/objc.dg/property/at-property-28.m
Normal file
29
gcc/testsuite/objc.dg/property/at-property-28.m
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* Test errors when extending a property in a class extension. */
|
||||
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
}
|
||||
@property (readonly, retain) id property1; /* { dg-message "originally specified here" } */
|
||||
@property (readonly) int property2; /* { dg-message "originally specified here" } */
|
||||
@property (readonly, getter=y) int property3; /* { dg-message "originally specified here" } */
|
||||
@property (readonly) int property4; /* Ok */
|
||||
@property (readonly) int property5; /* { dg-message "originally specified here" } */
|
||||
@end
|
||||
|
||||
@interface MyRootClass ()
|
||||
@property (readwrite, copy) id property1; /* { dg-warning "assign semantics attributes of property .property1. conflict with previous declaration" } */
|
||||
@property (readwrite, nonatomic) int property2; /* { dg-warning ".nonatomic. attribute of property .property2. conflicts with previous declaration" } */
|
||||
@property (readwrite, getter=x) int property3; /* { dg-warning ".getter. attribute of property .property3. conflicts with previous declaration" } */
|
||||
@property (readwrite) int property4; /* Ok */
|
||||
@property (readwrite) float property5; /* { dg-warning "type of property .property5. conflicts with previous declaration" } */
|
||||
@end
|
||||
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue