cp-tree.h (lang_decl_slector): New enum.
authorNathan Sidwell <nathan@acm.org>
Wed, 31 May 2017 16:46:58 +0000 (16:46 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 31 May 2017 16:46:58 +0000 (16:46 +0000)
* cp-tree.h (lang_decl_slector): New enum.
(lang_decl_base): Make selector an enum.  Drop decomposition_p
field.
(lang_decl): Use enum for discrimination.
(LANG_DECL_FN_CHECK, LANG_DECL_NS_CHECK, LANG_DECL_PARM_CHECK,
LANG_DECL_DEOMP_CHECK): Use enum.
(DECL_DECOMPOSITION_P): Use selector value.
(SET_DECL_DECOMPOSITION_P): Delete.
(retrofit_lang_decl): Lose SEL parm.
(fit_decomposition_lang_decl): Declare.
* decl.c (cp_finish_decomp, grokdeclarator): Use
fit_decomposition_lang_decl.
* lex.c (maybe_add_lang_decl_raw): New. Broken out of
retrofit_lang_decl.
(set_decl_linkage): New.  Broken out of retrofit_lang_decl.  Use
enum.
(fit_decomposition_lang_decl): Likewise.
(retrofit_lang_decl): Use worker functions.
(cxx_dup_lang_specific_decl): Use selector enum.
(maybe_add_lang_type_raw): New.  Broken out of ...
(cxx_make_type_name): ... here.  Call it.

From-SVN: r248748

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/lex.c

index 8cc3ca3..72a56f7 100644 (file)
@@ -1,3 +1,26 @@
+2017-05-31  Nathan Sidwell  <nathan@acm.org>
+
+       * cp-tree.h (lang_decl_slector): New enum.
+       (lang_decl_base): Make selector an enum.  Drop decomposition_p
+       field.
+       (lang_decl): Use enum for discrimination.
+       (LANG_DECL_FN_CHECK, LANG_DECL_NS_CHECK, LANG_DECL_PARM_CHECK,
+       LANG_DECL_DEOMP_CHECK): Use enum.
+       (DECL_DECOMPOSITION_P): Use selector value.
+       (SET_DECL_DECOMPOSITION_P): Delete.
+       (retrofit_lang_decl): Lose SEL parm.
+       (fit_decomposition_lang_decl): Declare.
+       * decl.c (cp_finish_decomp, grokdeclarator): Use
+       fit_decomposition_lang_decl.
+       * lex.c (maybe_add_lang_decl_raw): New. Broken out of
+       retrofit_lang_decl.
+       (set_decl_linkage): New.  Broken out of retrofit_lang_decl.  Use enum.
+       (fit_decomposition_lang_decl): Likewise.
+       (retrofit_lang_decl): Use worker functions.
+       (cxx_dup_lang_specific_decl): Use selector enum.
+       (maybe_add_lang_type_raw): New.  Broken out of ...
+       (cxx_make_type_name): ... here.  Call it.
+
 2017-05-30  Jason Merrill  <jason@redhat.com>
 
        PR c++/80856 - ICE with local extern in template
index d6713f1..1c3cce8 100644 (file)
@@ -2423,13 +2423,25 @@ struct GTY(()) lang_type {
 #define NAMESPACE_LEVEL(NODE) \
   (LANG_DECL_NS_CHECK (NODE)->level)
 \f
+/* Discriminator values for lang_decl.  */
+
+enum lang_decl_selector
+{
+  lds_min,
+  lds_fn,
+  lds_ns,
+  lds_parm,
+  lds_decomp
+};
+
 /* Flags shared by all forms of DECL_LANG_SPECIFIC.
 
    Some of the flags live here only to make lang_decl_min/fn smaller.  Do
    not make this struct larger than 32 bits; instead, make sel smaller.  */
 
 struct GTY(()) lang_decl_base {
-  unsigned selector : 16;   /* Larger than necessary for faster access.  */
+  /* Larger than necessary for faster access.  */
+  ENUM_BITFIELD(lang_decl_selector) selector : 16;
   ENUM_BITFIELD(languages) language : 1;
   unsigned use_template : 2;
   unsigned not_really_extern : 1;         /* var or fn */
@@ -2444,8 +2456,7 @@ struct GTY(()) lang_decl_base {
   unsigned u2sel : 1;
   unsigned concept_p : 1;                  /* applies to vars and functions */
   unsigned var_declared_inline_p : 1;     /* var */
-  unsigned decomposition_p : 1;                   /* var */
-  /* 1 spare bit */
+  /* 2 spare bits */
 };
 
 /* True for DECL codes which have template info and access.  */
@@ -2577,12 +2588,13 @@ struct GTY(()) lang_decl_decomp {
 
 struct GTY(()) lang_decl {
   union GTY((desc ("%h.base.selector"))) lang_decl_u {
+     /* Nothing of only the base type exists.  */
     struct lang_decl_base GTY ((default)) base;
-    struct lang_decl_min GTY((tag ("0"))) min;
-    struct lang_decl_fn GTY ((tag ("1"))) fn;
-    struct lang_decl_ns GTY((tag ("2"))) ns;
-    struct lang_decl_parm GTY((tag ("3"))) parm;
-    struct lang_decl_decomp GTY((tag ("4"))) decomp;
+    struct lang_decl_min GTY((tag ("lds_min"))) min;
+    struct lang_decl_fn GTY ((tag ("lds_fn"))) fn;
+    struct lang_decl_ns GTY((tag ("lds_ns"))) ns;
+    struct lang_decl_parm GTY((tag ("lds_parm"))) parm;
+    struct lang_decl_decomp GTY((tag ("lds_decomp"))) decomp;
   } u;
 };
 
@@ -2603,26 +2615,29 @@ struct GTY(()) lang_decl {
    lang_decl_fn, look down through a TEMPLATE_DECL into its result.  */
 #define LANG_DECL_FN_CHECK(NODE) __extension__                         \
 ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (STRIP_TEMPLATE (NODE));  \
-   if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != 1)   \
+   if (!DECL_DECLARES_FUNCTION_P (NODE)                                        \
+       || lt->u.base.selector != lds_fn)                               \
      lang_check_failed (__FILE__, __LINE__, __FUNCTION__);             \
    &lt->u.fn; })
 
 #define LANG_DECL_NS_CHECK(NODE) __extension__                         \
 ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE);                   \
-   if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != 2) \
+   if (TREE_CODE (NODE) != NAMESPACE_DECL                              \
+       || lt->u.base.selector != lds_ns)                               \
      lang_check_failed (__FILE__, __LINE__, __FUNCTION__);             \
    &lt->u.ns; })
 
 #define LANG_DECL_PARM_CHECK(NODE) __extension__               \
 ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE);           \
-  if (TREE_CODE (NODE) != PARM_DECL)                           \
+  if (TREE_CODE (NODE) != PARM_DECL                            \
+      || lt->u.base.selector != lds_parm)                      \
     lang_check_failed (__FILE__, __LINE__, __FUNCTION__);      \
   &lt->u.parm; })
 
 #define LANG_DECL_DECOMP_CHECK(NODE) __extension__             \
 ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE);           \
   if (!VAR_P (NODE)                                            \
-      || lt->u.base.selector != 4)                             \
+      || lt->u.base.selector != lds_decomp)                    \
     lang_check_failed (__FILE__, __LINE__, __FUNCTION__);      \
   &lt->u.decomp; })
 
@@ -3893,11 +3908,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
    declaration or one of VAR_DECLs for the user identifiers in it.  */
 #define DECL_DECOMPOSITION_P(NODE) \
   (VAR_P (NODE) && DECL_LANG_SPECIFIC (NODE)                   \
-   ? DECL_LANG_SPECIFIC (NODE)->u.base.decomposition_p         \
+   ? DECL_LANG_SPECIFIC (NODE)->u.base.selector == lds_decomp          \
    : false)
-#define SET_DECL_DECOMPOSITION_P(NODE) \
-  (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.decomposition_p \
-   = true)
 
 /* The underlying artificial VAR_DECL for structured binding.  */
 #define DECL_DECOMP_BASE(NODE) \
@@ -6338,7 +6350,8 @@ extern tree unqualified_name_lookup_error (tree,
 extern tree unqualified_fn_lookup_error                (cp_expr);
 extern tree build_lang_decl                    (enum tree_code, tree, tree);
 extern tree build_lang_decl_loc                        (location_t, enum tree_code, tree, tree);
-extern void retrofit_lang_decl                 (tree, int = 0);
+extern void retrofit_lang_decl                 (tree);
+extern void fit_decomposition_lang_decl                (tree, tree);
 extern tree copy_decl                          (tree CXX_MEM_STAT_INFO);
 extern tree copy_type                          (tree CXX_MEM_STAT_INFO);
 extern tree cxx_make_type                      (enum tree_code);
index 59cb315..e895fa7 100644 (file)
@@ -7372,11 +7372,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
              DECL_HAS_VALUE_EXPR_P (first) = 1;
            }
          if (processing_template_decl)
-           {
-             retrofit_lang_decl (first, 4);
-             SET_DECL_DECOMPOSITION_P (first);
-             DECL_DECOMP_BASE (first) = decl;
-           }
+           fit_decomposition_lang_decl (first, decl);
          first = DECL_CHAIN (first);
        }
       return;
@@ -7388,9 +7384,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
   for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
     {
       v[count - i - 1] = d;
-      retrofit_lang_decl (d, 4);
-      SET_DECL_DECOMPOSITION_P (d);
-      DECL_DECOMP_BASE (d) = decl;
+      fit_decomposition_lang_decl (d, decl);
     }
 
   tree type = TREE_TYPE (decl);
@@ -12314,10 +12308,8 @@ grokdeclarator (const cp_declarator *declarator,
          {
            gcc_assert (declarator && declarator->kind == cdk_decomp);
            DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
-           retrofit_lang_decl (decl, 4);
            DECL_ARTIFICIAL (decl) = 1;
-           SET_DECL_DECOMPOSITION_P (decl);
-           DECL_DECOMP_BASE (decl) = NULL_TREE;
+           fit_decomposition_lang_decl (decl, NULL_TREE);
          }
       }
 
index 1b4eb35..5dc9eee 100644 (file)
@@ -525,53 +525,52 @@ build_lang_decl_loc (location_t loc, enum tree_code code, tree name, tree type)
   return t;
 }
 
-/* Add DECL_LANG_SPECIFIC info to T.  Called from build_lang_decl
-   and pushdecl (for functions generated by the back end).  */
+/* Maybe add a raw lang_decl to T, a decl.  Return true if it needed
+   one.  */
 
-void
-retrofit_lang_decl (tree t, int sel)
+static bool
+maybe_add_lang_decl_raw (tree t, bool decomp_p)
 {
-  struct lang_decl *ld;
   size_t size;
-  size_t oldsize = 0;
-
-  if (DECL_LANG_SPECIFIC (t))
-    {
-      if (sel)
-       {
-         if (DECL_LANG_SPECIFIC (t)->u.base.selector == sel)
-           return;
-         gcc_assert (DECL_LANG_SPECIFIC (t)->u.base.selector == 0);
-         oldsize = sizeof (struct lang_decl_min);
-       }
-      else
-       return;
-    }
+  lang_decl_selector sel;
 
-  if (sel == 4)
-    size = sizeof (struct lang_decl_decomp);
+  if (decomp_p)
+    sel = lds_decomp, size = sizeof (struct lang_decl_decomp);
   else if (TREE_CODE (t) == FUNCTION_DECL)
-    sel = 1, size = sizeof (struct lang_decl_fn);
+    sel = lds_fn, size = sizeof (struct lang_decl_fn);
   else if (TREE_CODE (t) == NAMESPACE_DECL)
-    sel = 2, size = sizeof (struct lang_decl_ns);
+    sel = lds_ns, size = sizeof (struct lang_decl_ns);
   else if (TREE_CODE (t) == PARM_DECL)
-    sel = 3, size = sizeof (struct lang_decl_parm);
+    sel = lds_parm, size = sizeof (struct lang_decl_parm);
   else if (LANG_DECL_HAS_MIN (t))
-    sel = 0, size = sizeof (struct lang_decl_min);
+    sel = lds_min, size = sizeof (struct lang_decl_min);
   else
-    gcc_unreachable ();
+    return false;
 
-  ld = (struct lang_decl *) ggc_internal_cleared_alloc (size);
-  if (oldsize)
-    memcpy (ld, DECL_LANG_SPECIFIC (t), oldsize);
+  struct lang_decl *ld
+    = (struct lang_decl *) ggc_internal_cleared_alloc (size);
 
   ld->u.base.selector = sel;
   DECL_LANG_SPECIFIC (t) = ld;
 
-  if (sel == 2)
+  if (sel == lds_ns)
     /* Who'd create a namespace, only to put nothing in it?  */
     ld->u.ns.bindings = hash_map<lang_identifier *, tree>::create_ggc (499);
 
+  if (GATHER_STATISTICS)
+    {
+      tree_node_counts[(int)lang_decl] += 1;
+      tree_node_sizes[(int)lang_decl] += size;
+    }
+  return true;
+}
+
+/* T has just had a decl_lang_specific added.  Initialize its
+   linkage.  */
+
+static void
+set_decl_linkage (tree t)
+{
   if (current_lang_name == lang_name_cplusplus
       || decl_linkage (t) == lk_none)
     SET_DECL_LANGUAGE (t, lang_cplusplus);
@@ -579,37 +578,79 @@ retrofit_lang_decl (tree t, int sel)
     SET_DECL_LANGUAGE (t, lang_c);
   else
     gcc_unreachable ();
+}
 
-  if (GATHER_STATISTICS)
+/* T is a VAR_DECL node that needs to be a decomposition of BASE.  */
+
+void
+fit_decomposition_lang_decl (tree t, tree base)
+{
+  if (struct lang_decl *orig_ld = DECL_LANG_SPECIFIC (t))
     {
-      tree_node_counts[(int)lang_decl] += 1;
-      tree_node_sizes[(int)lang_decl] += size;
+      if (orig_ld->u.base.selector == lds_min)
+       {
+         maybe_add_lang_decl_raw (t, true);
+         memcpy (DECL_LANG_SPECIFIC (t), orig_ld,
+                 sizeof (struct lang_decl_min));
+         /* Reset selector, which will have been bashed by the
+            memcpy.  */
+         DECL_LANG_SPECIFIC (t)->u.base.selector = lds_decomp;
+       }
+      else
+       gcc_checking_assert (orig_ld->u.base.selector == lds_decomp);
+    }
+  else
+    {
+      maybe_add_lang_decl_raw (t, true);
+      set_decl_linkage (t);
     }
+
+  DECL_DECOMP_BASE (t) = base;
+}
+
+/* Add DECL_LANG_SPECIFIC info to T, if it needs one.  Generally
+   every C++ decl needs one, but C builtins etc do not.   */
+
+void
+retrofit_lang_decl (tree t)
+{
+  if (DECL_LANG_SPECIFIC (t))
+    return;
+
+  if (maybe_add_lang_decl_raw (t, false))
+    set_decl_linkage (t);
 }
 
 void
 cxx_dup_lang_specific_decl (tree node)
 {
   int size;
-  struct lang_decl *ld;
 
   if (! DECL_LANG_SPECIFIC (node))
     return;
 
-  if (TREE_CODE (node) == FUNCTION_DECL)
-    size = sizeof (struct lang_decl_fn);
-  else if (TREE_CODE (node) == NAMESPACE_DECL)
-    size = sizeof (struct lang_decl_ns);
-  else if (TREE_CODE (node) == PARM_DECL)
-    size = sizeof (struct lang_decl_parm);
-  else if (DECL_DECOMPOSITION_P (node))
-    size = sizeof (struct lang_decl_decomp);
-  else if (LANG_DECL_HAS_MIN (node))
-    size = sizeof (struct lang_decl_min);
-  else
-    gcc_unreachable ();
+  switch (DECL_LANG_SPECIFIC (node)->u.base.selector)
+    {
+    case lds_min:
+      size = sizeof (struct lang_decl_min);
+      break;
+    case lds_fn:
+      size = sizeof (struct lang_decl_fn);
+      break;
+    case lds_ns:
+      size = sizeof (struct lang_decl_ns);
+      break;
+    case lds_parm:
+      size = sizeof (struct lang_decl_parm);
+      break;
+    case lds_decomp:
+      size = sizeof (struct lang_decl_decomp);
+      break;
+    default:
+      gcc_unreachable ();
+    }
 
-  ld = (struct lang_decl *) ggc_internal_alloc (size);
+  struct lang_decl *ld = (struct lang_decl *) ggc_internal_alloc (size);
   memcpy (ld, DECL_LANG_SPECIFIC (node), size);
   DECL_LANG_SPECIFIC (node) = ld;
 
@@ -670,18 +711,18 @@ copy_type (tree type MEM_STAT_DECL)
   return copy;
 }
 
-tree
-cxx_make_type (enum tree_code code)
-{
-  tree t = make_node (code);
+/* Add a raw lang_type to T, a type, should it need one.  */
 
-  /* Create lang_type structure.  */
-  if (RECORD_OR_UNION_CODE_P (code)
-      || code == BOUND_TEMPLATE_TEMPLATE_PARM)
+static bool
+maybe_add_lang_type_raw (tree t)
+{
+  bool add = (RECORD_OR_UNION_CODE_P (TREE_CODE (t))
+             || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM);
+  if (add)
     {
       struct lang_type *pi
-          = (struct lang_type *) ggc_internal_cleared_alloc
-         (sizeof (struct lang_type));
+       = (struct lang_type *) ggc_internal_cleared_alloc
+       (sizeof (struct lang_type));
 
       TYPE_LANG_SPECIFIC (t) = pi;
       pi->u.c.h.is_lang_type_class = 1;
@@ -692,6 +733,15 @@ cxx_make_type (enum tree_code code)
          tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
        }
     }
+  return add;
+}
+
+tree
+cxx_make_type (enum tree_code code)
+{
+  tree t = make_node (code);
+
+  maybe_add_lang_type_raw (t);
 
   /* Set up some flags that give proper default behavior.  */
   if (RECORD_OR_UNION_CODE_P (code))