diff options
-rw-r--r-- | gcc/c-family/c-attribs.c | 19 | ||||
-rw-r--r-- | gcc/c-family/c-objc.h | 2 | ||||
-rw-r--r-- | gcc/c-family/c.opt | 5 | ||||
-rw-r--r-- | gcc/c-family/stub-objc.c | 1 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 3 | ||||
-rw-r--r-- | gcc/cp/parser.c | 3 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 6 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 9 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/attributes/root-class-01.mm | 11 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/root-class-00.mm | 10 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/attributes/root-class-01.m | 11 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/root-class-00.m | 10 |
13 files changed, 96 insertions, 6 deletions
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index f168082..24bcd70 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -158,6 +158,7 @@ static tree handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *); static tree handle_copy_attribute (tree *, tree, tree, int, bool *); static tree handle_nsobject_attribute (tree *, tree, tree, int, bool *); +static tree handle_objc_root_class_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -513,6 +514,8 @@ const struct attribute_spec c_common_attribute_table[] = /* Attributes used by Objective-C. */ { "NSObject", 0, 0, true, false, false, false, handle_nsobject_attribute, NULL }, + { "objc_root_class", 0, 0, true, false, false, false, + handle_objc_root_class_attribute, NULL }, { NULL, 0, 0, false, false, false, false, NULL, NULL } }; @@ -5163,6 +5166,22 @@ handle_nsobject_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* Handle a "objc_root_class" attributes; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_objc_root_class_attribute (tree */*node*/, tree name, tree /*args*/, + int /*flags*/, bool *no_add_attrs) +{ + /* This has no meaning outside Objective-C. */ + if (!c_dialect_objc()) + warning (OPT_Wattributes, "%qE is only applicable to Objective-C" + " class interfaces, attribute ignored", name); + + *no_add_attrs = true; + return NULL_TREE; +} + /* Attempt to partially validate a single attribute ATTR as if it were to be applied to an entity OPER. */ diff --git a/gcc/c-family/c-objc.h b/gcc/c-family/c-objc.h index 6e96731..9414aec 100644 --- a/gcc/c-family/c-objc.h +++ b/gcc/c-family/c-objc.h @@ -124,7 +124,7 @@ extern tree objc_get_protocol_qualified_type (tree, tree); extern tree objc_get_class_reference (tree); extern tree objc_get_class_ivars (tree); extern bool objc_detect_field_duplicates (bool); -extern void objc_start_class_interface (tree, tree, tree, tree); +extern void objc_start_class_interface (tree, location_t, tree, tree, tree); extern void objc_start_category_interface (tree, tree, tree, tree); extern void objc_start_protocol (tree, tree, tree); extern void objc_continue_interface (void); diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index fe16357..a008363 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1002,6 +1002,11 @@ Enum(cpp_normalize_level) String(id) Value(normalized_identifier_C) EnumValue Enum(cpp_normalize_level) String(nfc) Value(normalized_C) +Wobjc-root-class +ObjC ObjC++ Var(warn_objc_root_class) Warning Init(1) +Warn if a class interface has no superclass. Root classes may use an attribute +to suppress this warning. + Wold-style-cast C++ ObjC++ Var(warn_old_style_cast) Warning Warn if a C-style cast is used in a program. diff --git a/gcc/c-family/stub-objc.c b/gcc/c-family/stub-objc.c index 2f53557..26941aa 100644 --- a/gcc/c-family/stub-objc.c +++ b/gcc/c-family/stub-objc.c @@ -137,6 +137,7 @@ objc_set_method_opt (bool ARG_UNUSED (optional)) void objc_start_class_interface (tree ARG_UNUSED (name), + location_t /*name_loc*/, tree ARG_UNUSED (super), tree ARG_UNUSED (protos), tree ARG_UNUSED (attribs)) diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 377914c..f4c4cf7 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -10801,6 +10801,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes) return; } id1 = c_parser_peek_token (parser)->value; + location_t loc1 = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { @@ -10860,7 +10861,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes) tree proto = NULL_TREE; if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); - objc_start_class_interface (id1, superclass, proto, attributes); + objc_start_class_interface (id1, loc1, superclass, proto, attributes); } else objc_start_class_implementation (id1, superclass); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index efcdce0..6b0447e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -33574,6 +33574,7 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes) bool is_class_extension; cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */ + location_t nam_loc = cp_lexer_peek_token (parser->lexer)->location; name = cp_parser_identifier (parser); if (name == error_mark_node) { @@ -33593,7 +33594,7 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes) objc_start_category_interface (name, categ, protos, attributes); else { - objc_start_class_interface (name, super, protos, attributes); + objc_start_class_interface (name, nam_loc, super, protos, attributes); /* Handle instance variable declarations, if any. */ cp_parser_objc_class_ivars (parser); objc_continue_interface (); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 420a14b..c353eb4 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -8518,6 +8518,12 @@ and caught in another, the class must have default visibility. Otherwise the two shared objects are unable to use the same typeinfo node and exception handling will break. +@item objc_root_class @r{(Objective-C and Objective-C++ only)} +@cindex @code{objc_root_class} type attribute +This attribute marks a class as being a root class, and thus allows +the compiler to elide any warnings about a missing superclass and to +make additional checks for mandatory methods as needed. + @end table To specify multiple attributes, separate them by commas within the diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 69bf1fa..85f7969 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -276,7 +276,7 @@ Objective-C and Objective-C++ Dialects}. -fzero-link @gol -gen-decls @gol -Wassign-intercept -Wno-property-assign-default @gol --Wno-protocol -Wselector @gol +-Wno-protocol -Wobjc-root-class -Wselector @gol -Wstrict-selector-match @gol -Wundeclared-selector} @@ -4348,6 +4348,13 @@ from the superclass. If you use the @option{-Wno-protocol} option, then methods inherited from the superclass are considered to be implemented, and no warning is issued for them. +@item -Wobjc-root-class @r{(Objective-C and Objective-C++ only)} +@opindex Wobjc-root-class +Warn if a class interface lacks a superclass. Most classes will inherit +from @code{NSObject} (or @code{Object}) for example. When declaring +classes intended to be root classes, the warning can be suppressed by +marking their interfaces with @code{__attribute__((objc_root_class))}. + @item -Wselector @r{(Objective-C and Objective-C++ only)} @opindex Wselector @opindex Wno-selector diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index b9ed32d..e410386 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -571,11 +571,11 @@ lookup_protocol_in_reflist (tree rproto_list, tree lproto) } void -objc_start_class_interface (tree klass, tree super_class, +objc_start_class_interface (tree klass, location_t name_loc, tree super_class, tree protos, tree attributes) { if (flag_objc1_only && attributes) - error_at (input_location, "class attributes are not available in Objective-C 1.0"); + error_at (name_loc, "class attributes are not available in Objective-C 1.0"); objc_interface_context = objc_ivar_context @@ -7014,6 +7014,12 @@ start_class (enum tree_code code, tree class_name, tree super_name, CLASS_SUPER_NAME (objc_implementation_context) = CLASS_SUPER_NAME (implementation_template); } + + if (!CLASS_SUPER_NAME (objc_implementation_context) + && !lookup_attribute ("objc_root_class", + TYPE_ATTRIBUTES (implementation_template))) + warning (OPT_Wobjc_root_class, "class %qE defined without" + " specifying a base class", class_name); break; case CLASS_INTERFACE_TYPE: @@ -7044,6 +7050,8 @@ start_class (enum tree_code code, tree class_name, tree super_name, TREE_DEPRECATED (klass) = 1; else if (is_attribute_p ("objc_exception", name)) CLASS_HAS_EXCEPTION_ATTR (klass) = 1; + else if (is_attribute_p ("objc_root_class", name)) + ; else if (is_attribute_p ("visibility", name)) ; else diff --git a/gcc/testsuite/obj-c++.dg/attributes/root-class-01.mm b/gcc/testsuite/obj-c++.dg/attributes/root-class-01.mm new file mode 100644 index 0000000..84da94a --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/attributes/root-class-01.mm @@ -0,0 +1,11 @@ +/* Test Wobjc-root-class warning is suppressed by the objc_root_class attr. + Note that we don't issue a warning unless the TU contains an implementation + for the class. This should compile without warning. */ +/* { dg-additional-options "-fsyntax-only " } */ + +__attribute__((objc_root_class)) +@interface ARootObject +@end + +@implementation ARootObject +@end diff --git a/gcc/testsuite/obj-c++.dg/root-class-00.mm b/gcc/testsuite/obj-c++.dg/root-class-00.mm new file mode 100644 index 0000000..f951b0d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/root-class-00.mm @@ -0,0 +1,10 @@ +/* Test Wobjc-root-class. + Note that we don't issue a warning unless the TU contains an implementation + for the class. */ +/* { dg-additional-options "-fsyntax-only " } */ + +@interface ARootObject +@end + +@implementation ARootObject /* { dg-warning {class 'ARootObject' defined without specifying a base class} } */ +@end diff --git a/gcc/testsuite/objc.dg/attributes/root-class-01.m b/gcc/testsuite/objc.dg/attributes/root-class-01.m new file mode 100644 index 0000000..84da94a --- /dev/null +++ b/gcc/testsuite/objc.dg/attributes/root-class-01.m @@ -0,0 +1,11 @@ +/* Test Wobjc-root-class warning is suppressed by the objc_root_class attr. + Note that we don't issue a warning unless the TU contains an implementation + for the class. This should compile without warning. */ +/* { dg-additional-options "-fsyntax-only " } */ + +__attribute__((objc_root_class)) +@interface ARootObject +@end + +@implementation ARootObject +@end diff --git a/gcc/testsuite/objc.dg/root-class-00.m b/gcc/testsuite/objc.dg/root-class-00.m new file mode 100644 index 0000000..1f73f73 --- /dev/null +++ b/gcc/testsuite/objc.dg/root-class-00.m @@ -0,0 +1,10 @@ +/* Test Wobjc-root-class. + Note that we don't issue a warning unless the TU contains an implementation + for the class. */ +/* { dg-additional-options "-fsyntax-only " } */ + +@interface ARootObject +@end + +@implementation ARootObject +@end /* { dg-warning {class 'ARootObject' defined without specifying a base class} } */ |