diff mbox series

Ping: Add a simulate_enum_decl langhook

Message ID mpty2xnw3ns.fsf@arm.com
State New
Headers show
Series Ping: Add a simulate_enum_decl langhook | expand

Commit Message

Richard Sandiford Oct. 14, 2019, 7:03 p.m. UTC
Ping

To give a bit more rationale: some of the functions handled by
https://gcc.gnu.org/ml/gcc-patches/2019-10/msg01002.html operate
on structs and enums.  There are already langhooks for creating the
necessary struct types, but there's no direct way of creating a
language-level enum.

One option would have been to define the enum in the header file
and have the pragma search for it by name.  But then we have to be
wary of cases in which that definition lost out to an incompatible
user-defined one.  (That would be an error, but not one that would
stop the pragma from being processed.)  And searching for an existing
enum would be a new hook anyway.

Having no hooks for enums didn't feel like a deliberate omission.
It looked more like a case of noone needing such a hook until now.

Richard Sandiford <richard.sandiford@arm.com> writes:
> Similarly to the simulate_builtin_function_decl patch, this one
> adds a hook for simulating an enum declaration in the source
> language.  Again, the main SVE ACLE patch has tests for various
> error conditions.
>
> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?
>
> Richard

2019-09-26  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* coretypes.h (string_int_pair): New typedef.
	* langhooks-def.h (LANG_HOOKS_SIMULATE_ENUM_DECL): Define.
	(LANG_HOOKS_FOR_TYPES_INITIALIZER): Include it.
	* langhooks.h (lang_hooks_for_types::simulate_enum_decl): New hook.

gcc/c/
	* c-tree.h (c_simulate_enum_decl): Declare.
	* c-decl.c (c_simulate_enum_decl): New function.
	* c-objc-common.h (LANG_HOOKS_SIMULATE_ENUM_DECL): Define to the above.

gcc/cp/
	* cp-objcp-common.h (cxx_simulate_enum_decl): Declare.
	(LANG_HOOKS_SIMULATE_ENUM_DECL): Define to the above.
	* decl.c (cxx_simulate_enum_decl): New function.
diff mbox series

Patch

Index: gcc/coretypes.h
===================================================================
--- gcc/coretypes.h	2019-09-21 13:56:08.843935101 +0100
+++ gcc/coretypes.h	2019-09-26 13:02:48.907474244 +0100
@@ -341,6 +341,7 @@  typedef int reg_class_t;
 }
 
 typedef std::pair <tree, tree> tree_pair;
+typedef std::pair <const char *, int> string_int_pair;
 
 /* Define a name->value mapping.  */
 template <typename ValueType>
Index: gcc/langhooks-def.h
===================================================================
--- gcc/langhooks-def.h	2019-09-26 13:02:42.543520465 +0100
+++ gcc/langhooks-def.h	2019-09-26 13:02:48.911474214 +0100
@@ -171,6 +171,7 @@  #define LANG_HOOKS_TREE_DUMP_INITIALIZER
 extern tree lhd_unit_size_without_reusable_padding (tree);
 
 #define LANG_HOOKS_MAKE_TYPE lhd_make_node
+#define LANG_HOOKS_SIMULATE_ENUM_DECL	NULL
 #define LANG_HOOKS_CLASSIFY_RECORD	NULL
 #define LANG_HOOKS_TYPE_FOR_SIZE	lhd_type_for_size
 #define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error
@@ -204,6 +205,7 @@  #define LANG_HOOKS_UNIT_SIZE_WITHOUT_REU
 
 #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
   LANG_HOOKS_MAKE_TYPE, \
+  LANG_HOOKS_SIMULATE_ENUM_DECL, \
   LANG_HOOKS_CLASSIFY_RECORD, \
   LANG_HOOKS_TYPE_FOR_MODE, \
   LANG_HOOKS_TYPE_FOR_SIZE, \
Index: gcc/langhooks.h
===================================================================
--- gcc/langhooks.h	2019-09-26 13:02:42.543520465 +0100
+++ gcc/langhooks.h	2019-09-26 13:02:48.911474214 +0100
@@ -64,6 +64,10 @@  struct lang_hooks_for_types
      language-specific processing is required.  */
   tree (*make_type) (enum tree_code);
 
+  /* Make an enum type with the given name and values, associating
+     them all with the given source location.  */
+  tree (*simulate_enum_decl) (location_t, const char *, vec<string_int_pair>);
+
   /* Return what kind of RECORD_TYPE this is, mainly for purposes of
      debug information.  If not defined, record types are assumed to
      be structures.  */
Index: gcc/c/c-tree.h
===================================================================
--- gcc/c/c-tree.h	2019-09-26 13:02:42.539520492 +0100
+++ gcc/c/c-tree.h	2019-09-26 13:02:48.907474244 +0100
@@ -563,6 +563,8 @@  extern tree finish_enum (tree, tree, tre
 extern void finish_function (void);
 extern tree finish_struct (location_t, tree, tree, tree,
 			   class c_struct_parse_info *);
+extern tree c_simulate_enum_decl (location_t, const char *,
+				  vec<string_int_pair>);
 extern struct c_arg_info *build_arg_info (void);
 extern struct c_arg_info *get_parm_info (bool, tree);
 extern tree grokfield (location_t, struct c_declarator *,
Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	2019-09-26 13:02:42.539520492 +0100
+++ gcc/c/c-decl.c	2019-09-26 13:02:48.907474244 +0100
@@ -8903,6 +8903,36 @@  build_enumerator (location_t decl_loc, l
   return tree_cons (decl, value, NULL_TREE);
 }
 
+/* Implement LANG_HOOKS_SIMULATE_ENUM_DECL.  */
+
+tree
+c_simulate_enum_decl (location_t loc, const char *name,
+		      vec<string_int_pair> values)
+{
+  location_t saved_loc = input_location;
+  input_location = loc;
+
+  struct c_enum_contents the_enum;
+  tree enumtype = start_enum (loc, &the_enum, get_identifier (name));
+
+  tree value_chain = NULL_TREE;
+  string_int_pair *value;
+  unsigned int i;
+  FOR_EACH_VEC_ELT (values, i, value)
+    {
+      tree decl = build_enumerator (loc, loc, &the_enum,
+				    get_identifier (value->first),
+				    build_int_cst (integer_type_node,
+						   value->second));
+      TREE_CHAIN (decl) = value_chain;
+      value_chain = decl;
+    }
+
+  finish_enum (enumtype, nreverse (value_chain), NULL_TREE);
+
+  input_location = saved_loc;
+  return enumtype;
+}
 
 /* Create the FUNCTION_DECL for a function definition.
    DECLSPECS, DECLARATOR and ATTRIBUTES are the parts of
Index: gcc/c/c-objc-common.h
===================================================================
--- gcc/c/c-objc-common.h	2019-09-26 13:02:42.539520492 +0100
+++ gcc/c/c-objc-common.h	2019-09-26 13:02:48.907474244 +0100
@@ -75,6 +75,8 @@  #define LANG_HOOKS_FORMAT_ATTRIBUTE_TABL
 #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
 #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
 
+#undef LANG_HOOKS_SIMULATE_ENUM_DECL
+#define LANG_HOOKS_SIMULATE_ENUM_DECL c_simulate_enum_decl
 #undef LANG_HOOKS_TYPE_FOR_MODE
 #define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
 #undef LANG_HOOKS_TYPE_FOR_SIZE
Index: gcc/cp/cp-objcp-common.h
===================================================================
--- gcc/cp/cp-objcp-common.h	2019-09-26 13:02:42.539520492 +0100
+++ gcc/cp/cp-objcp-common.h	2019-09-26 13:02:48.907474244 +0100
@@ -35,6 +35,8 @@  extern tree cp_get_global_decls ();
 extern tree cp_pushdecl (tree);
 extern void cp_register_dumps (gcc::dump_manager *);
 extern tree cxx_make_type_hook			(tree_code);
+extern tree cxx_simulate_enum_decl (location_t, const char *,
+				    vec<string_int_pair>);
 
 /* Lang hooks that are shared between C++ and ObjC++ are defined here.  Hooks
    specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c,
@@ -131,6 +133,8 @@  #define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_
 
 #undef LANG_HOOKS_MAKE_TYPE
 #define LANG_HOOKS_MAKE_TYPE cxx_make_type_hook
+#undef LANG_HOOKS_SIMULATE_ENUM_DECL
+#define LANG_HOOKS_SIMULATE_ENUM_DECL cxx_simulate_enum_decl
 #undef LANG_HOOKS_TYPE_FOR_MODE
 #define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
 #undef LANG_HOOKS_TYPE_FOR_SIZE
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	2019-09-26 13:02:42.543520465 +0100
+++ gcc/cp/decl.c	2019-09-26 13:02:48.911474214 +0100
@@ -15383,6 +15383,40 @@  lookup_enumerator (tree enumtype, tree n
   return e? TREE_VALUE (e) : NULL_TREE;
 }
 
+/* Implement LANG_HOOKS_SIMULATE_ENUM_DECL.  */
+
+tree
+cxx_simulate_enum_decl (location_t loc, const char *name,
+			vec<string_int_pair> values)
+{
+  location_t saved_loc = input_location;
+  input_location = loc;
+
+  tree enumtype = start_enum (get_identifier (name), NULL_TREE, NULL_TREE,
+			      NULL_TREE, false, NULL);
+  if (!OPAQUE_ENUM_P (enumtype))
+    {
+      error_at (loc, "multiple definition of %q#T", enumtype);
+      inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)),
+	      "previous definition here");
+      return enumtype;
+    }
+  SET_OPAQUE_ENUM_P (enumtype, false);
+  DECL_SOURCE_LOCATION (TYPE_NAME (enumtype)) = loc;
+
+  string_int_pair *value;
+  unsigned int i;
+  FOR_EACH_VEC_ELT (values, i, value)
+    build_enumerator (get_identifier (value->first),
+		      build_int_cst (integer_type_node, value->second),
+		      enumtype, NULL_TREE, loc);
+
+  finish_enum_value_list (enumtype);
+  finish_enum (enumtype);
+
+  input_location = saved_loc;
+  return enumtype;
+}
 
 /* We're defining DECL.  Make sure that its type is OK.  */