diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index f1680820ecd6a2761939a196955ffaad003018c3..24bcd70b26cb0c4afb453b8202c29dec046edb13 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 6e96731882b02163673460b68228c724ddcf1046..9414aecc668a7d9d537c92c2a6fe5ef23c63431d 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 fe16357db85c88ea42cf00715b72c606b6079064..a0083636aed4375080526c47db7c8142ca37f5f0 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 2f535578789712c987d457cbdb319f8c9d3d8aef..26941aa2cb4cd8e881ea706b79f701f345f4b81e 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 377914cad165f5bb43cdf6a37b922301fc7d7e3f..f4c4cf7bf8f9a1e56fd1133ec625dd8cff9bf606 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 efcdce0477732f1c6412d9efa15c5c217efd58de..6b0447ea496b4659df0e517a5c41195385376144 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 420a14b66b065464af08c2dd41df8422e8c26b4a..c353eb432b961512500e1d0b7c9928b3cef342da 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 69bf1fa89dd390635b5084b049664675c179a9f5..85f7969d87f86522c4eec1599453a8970c51e9f7 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 b9ed32d51d07ea1d421d49f66dc1b0b9cc10cc1f..e4103860aae98b24745c7239d00b0124eebc7240 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 0000000000000000000000000000000000000000..84da94aa1ffe5238fbcbc889b96c9131fb81574a
--- /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 0000000000000000000000000000000000000000..f951b0de8cc14abc67691568745fddec5011927e
--- /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 0000000000000000000000000000000000000000..84da94aa1ffe5238fbcbc889b96c9131fb81574a
--- /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 0000000000000000000000000000000000000000..1f73f735761c4455a8eaabef0af2b8a61154b2be
--- /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} } */