[Objective-c] Add 'instancetype' typedef alias.

Message ID B450977C-2ED5-4844-81C0-19B405C2A3C4@sandoe.co.uk
State New
Headers show
Series
  • [Objective-c] Add 'instancetype' typedef alias.
Related show

Commit Message

Iain Sandoe May 18, 2019, 8:32 a.m.
Small part of catching up with changes made to the objective-c language.

The instancetype has been added to other objective-c implementations
as a typedef alias to id in order to allow diagnosis of cases where a class is
used or returned where an instance is expected.

This adds the typedef, and tests that we can parse it.
It doesn't alter the diagnostics yet.

tested on x86_64-darwin16, x86_64-linux-gnu
applied to mainline
Iain

gcc/objc/

2019-05-18  Iain Sandoe  <iain@sandoe.co.uk>

	* objc/objc-act.h (OCTI_INSTANCE_TYPE, OCTI_INSTANCETYPE_NAME): New.
	(objc_global_trees): Add instance type and name.
	(INSTANCE_TYPEDEF_NAME): New.
	* objc/objc-act.c (synth_module_prologue): Build decls for
	objc_instancetype_type and objc_instancetype_name.

gcc/testsuite/

2019-05-18  Iain Sandoe  <iain@sandoe.co.uk>

	* objc.dg/instancetype-0.m: New.

Patch

diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 7ee3306..2173092 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -2950,12 +2950,14 @@  synth_module_prologue (void)
   objc_class_reference = xref_tag (RECORD_TYPE, objc_class_id);
 
   objc_object_type = build_pointer_type (objc_object_reference);
+  objc_instancetype_type = build_pointer_type (objc_object_reference);
   objc_class_type = build_pointer_type (objc_class_reference);
 
   objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME);
+  objc_instancetype_name = get_identifier (INSTANCE_TYPEDEF_NAME);
   objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
 
-  /* Declare the 'id' and 'Class' typedefs.  */
+  /* Declare the 'id', 'instancetype' and 'Class' typedefs.  */
   type = lang_hooks.decls.pushdecl (build_decl (input_location,
                                                TYPE_DECL,
                                                objc_object_name,
@@ -2964,6 +2966,12 @@  synth_module_prologue (void)
 
   type = lang_hooks.decls.pushdecl (build_decl (input_location,
                                                TYPE_DECL,
+                                               objc_instancetype_name,
+                                               objc_instancetype_type));
+  TREE_NO_WARNING (type) = 1;
+
+  type = lang_hooks.decls.pushdecl (build_decl (input_location,
+                                               TYPE_DECL,
                                                objc_class_name,
                                                objc_class_type));
   TREE_NO_WARNING (type) = 1;
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 5794cdf..3b69043 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -313,6 +313,7 @@  enum objc_tree_index
     OCTI_SUPER_TYPE,
     OCTI_SEL_TYPE,
     OCTI_ID_TYPE,
+    OCTI_INSTANCE_TYPE,
     OCTI_CLS_TYPE,
     OCTI_NST_TYPE,
     OCTI_PROTO_TYPE,
@@ -368,6 +369,7 @@  enum objc_tree_index
     OCTI_OBJ_ID,
     OCTI_CLS_ID,
     OCTI_ID_NAME,
+    OCTI_INSTANCETYPE_NAME,
     OCTI_CLASS_NAME,
     OCTI_CNST_STR_ID,
     OCTI_CNST_STR_TYPE,
@@ -443,6 +445,7 @@  extern GTY(()) tree objc_global_trees[OCTI_MAX];
 #define objc_super_type                objc_global_trees[OCTI_SUPER_TYPE]
 #define objc_selector_type             objc_global_trees[OCTI_SEL_TYPE]
 #define objc_object_type       objc_global_trees[OCTI_ID_TYPE]
+#define objc_instancetype_type objc_global_trees[OCTI_INSTANCE_TYPE]
 #define objc_class_type                objc_global_trees[OCTI_CLS_TYPE]
 #define objc_instance_type     objc_global_trees[OCTI_NST_TYPE]
 #define objc_protocol_type     objc_global_trees[OCTI_PROTO_TYPE]
@@ -570,7 +573,8 @@  extern GTY(()) tree objc_global_trees[OCTI_MAX];
 
 #define objc_object_id         objc_global_trees[OCTI_OBJ_ID]
 #define objc_class_id          objc_global_trees[OCTI_CLS_ID]
-#define objc_object_name               objc_global_trees[OCTI_ID_NAME]
+#define objc_object_name        objc_global_trees[OCTI_ID_NAME]
+#define objc_instancetype_name objc_global_trees[OCTI_INSTANCETYPE_NAME]
 #define objc_class_name                objc_global_trees[OCTI_CLASS_NAME]
 
 /* Constant string classes.  */
@@ -608,6 +612,7 @@  extern GTY(()) tree objc_global_trees[OCTI_MAX];
 /* Reserved tag definitions.  */
 
 #define OBJECT_TYPEDEF_NAME            "id"
+#define INSTANCE_TYPEDEF_NAME          "instancetype"
 #define CLASS_TYPEDEF_NAME             "Class"
 
 #define TAG_OBJECT                     "objc_object"
diff --git a/gcc/testsuite/objc.dg/instancetype-0.m b/gcc/testsuite/objc.dg/instancetype-0.m
new file mode 100644
index 0000000..60e086a
--- /dev/null
+++ b/gcc/testsuite/objc.dg/instancetype-0.m
@@ -0,0 +1,30 @@ 
+/* Contributed by Iain Sandoe <iain@codesourcery.com>, December 2014.  */
+/* { dg-do compile } */
+
+/* Basic check of parsing instancetype.  */
+
+extern id class_createInstance (id, int);
+extern id class_getSuperclass (id);
+
+@interface MyObject
+{
+  Class isa;
+}
++ (instancetype)alloc;
+- (instancetype)init;
++ (instancetype)initialize;
++ (instancetype)factoryMethodA;
++ (id)factoryMethodB;
++ (Class) class;
++ (Class) superclass;
+@end
+
+@implementation MyObject
++ (instancetype)alloc { return class_createInstance (self, 0); }
+- (instancetype)init  { return self; }
++ (instancetype)initialize { return self; }
++ (instancetype)factoryMethodA { return [[[self class] alloc] init]; }
++ (id)factoryMethodB { return [[[self class] alloc] init]; }
++ (Class) class { return self; }
++ (Class) superclass { return class_getSuperclass (self); }
+@end