We currently have 7 different tag_types, but our TYPENAME_TYPE
representation only differentiates between four of them:
class/enum/union/typename.  This patch makes our representation and
cache of TYPENAME_TYPE remember the tag_type fully so that later
substitution/resolution of the TYPENAME_TYPE is sound.

gcc/cp/ChangeLog:

        * cp-tree.h (TYPENAME_TYPE_TAG_BIT_0): New.
        (TYPENAME_TYPE_TAG_BIT_1): New.
        (TYPENAME_TYPE_TAG_BIT_2): New.
        (TYPENAME_IS_ENUM_P): Use get_typename_tag_type.
        (TYPENAME_IS_CLASS_P): Rename to ...
        (TYPENAME_IS_CLASS_OR_STRUCT_P): ... this, and use
        get_typename_tag_type.
        (TYPENAME_IS_UNION_P): Use get_typename_tag_type.
        (TYPENAME_IS_RESOLVING_P): Use TREE_LANG_FLAG_3
        instead of _2.
        (get_typename_tag_type): New.
        (set_typename_tag_type): New.
        * decl.cc (typename_info): Replace bool fields with a single
        tag_types field.
        (typename_hasher::equal): Adjust.
        (build_typename_type): Adjust.
        * error.cc (dump_type) <case TYPENAME_TYPE>: Adjust.
        * module.cc (trees_out::type_node) <case TYPENAME_TYPE>: Use
        get_typename_tag_type.
        * pt.cc (tsubst) <case TYPENAME_TYPE>: Likewise.
        get_typename_tag_type.
---
 gcc/cp/cp-tree.h | 48 +++++++++++++++++++++++++++++++++++++++---------
 gcc/cp/decl.cc   | 16 ++++------------
 gcc/cp/error.cc  |  2 +-
 gcc/cp/module.cc | 11 +----------
 gcc/cp/pt.cc     | 12 +++---------
 5 files changed, 48 insertions(+), 41 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6f244a8bdfd4..604f87e1315d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -417,7 +417,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
       STMT_EXPR_NO_SCOPE (in STMT_EXPR)
       BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
-      TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
+      TYPENAME_TYPE_TAG_BIT_0 (in TYPENAME_TYPE)
       OMP_FOR_GIMPLIFYING_P (in OMP_FOR, OMP_SIMD, OMP_DISTRIBUTE,
                             and OMP_TASKLOOP)
       BASELINK_QUALIFIED_P (in BASELINK)
@@ -460,7 +460,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       DELETE_EXPR_USE_VEC (in DELETE_EXPR).
       ICS_ELLIPSIS_FLAG (in _CONV)
       DECL_INITIALIZED_P (in VAR_DECL)
-      TYPENAME_IS_CLASS_P (in TYPENAME_TYPE)
+      TYPENAME_TYPE_TAG_BIT_1 (in TYPENAME_TYPE)
       STMT_IS_FULL_EXPR_P (in _STMT)
       TARGET_EXPR_LIST_INIT_P (in TARGET_EXPR)
       DECL_FINAL_P (in FUNCTION_DECL)
@@ -480,7 +480,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       ICS_THIS_FLAG (in _CONV)
       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
       STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
-      TYPENAME_IS_RESOLVING_P (in TYPENAME_TYPE)
+      TYPENAME_TYPE_TAG_BIT_2 (in TYPENAME_TYPE)
       TYPE_POLYMORPHIC_P (in RECORD_TYPE and UNION_TYPE)
       TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
       FNDECL_USED_AUTO (in FUNCTION_DECL)
@@ -513,7 +513,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       TARGET_EXPR_ELIDING_P (in TARGET_EXPR)
       IF_STMT_VACUOUS_INIT_P (IF_STMT)
       contract_semantic (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT)
-      TYPENAME_IS_UNION_P (in TYPENAME_TYPE)
+      TYPENAME_IS_RESOLVING_P (in TYPENAME_TYPE)
    4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
       TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
          CALL_EXPR, or FIELD_DECL).
@@ -4551,21 +4551,30 @@ get_vec_init_expr (tree t)
 #define TYPENAME_TYPE_FULLNAME(NODE) \
   (TYPE_VALUES_RAW (TYPENAME_TYPE_CHECK (NODE)))
 
+/* Storage for the tag type of a TYPENAME_TYPE.  */
+#define TYPENAME_TYPE_TAG_BIT_0(NODE) \
+  (TREE_LANG_FLAG_0 (TYPENAME_TYPE_CHECK (NODE)))
+#define TYPENAME_TYPE_TAG_BIT_1(NODE) \
+  (TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE)))
+#define TYPENAME_TYPE_TAG_BIT_2(NODE) \
+  (TREE_LANG_FLAG_2 (TYPENAME_TYPE_CHECK (NODE)))
+
 /* True if a TYPENAME_TYPE was declared as an "enum".  */
 #define TYPENAME_IS_ENUM_P(NODE) \
-  (TREE_LANG_FLAG_0 (TYPENAME_TYPE_CHECK (NODE)))
+  (get_typename_tag_type (NODE) == enum_type)
 
 /* True if a TYPENAME_TYPE was declared as a "class" or "struct".  */
-#define TYPENAME_IS_CLASS_P(NODE) \
-  (TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE)))
+#define TYPENAME_IS_CLASS_OR_STRUCT_P(NODE) \
+  (get_typename_tag_type (NODE) == class_type \
+   || get_typename_tag_type (NODE) == record_type)
 
 /* True if a TYPENAME_TYPE was declared as a "union".  */
 #define TYPENAME_IS_UNION_P(NODE) \
-  (TREE_LANG_FLAG_3 (TYPENAME_TYPE_CHECK (NODE)))
+  (get_typename_tag_type (NODE) == union_type)
 
 /* True if a TYPENAME_TYPE is in the process of being resolved.  */
 #define TYPENAME_IS_RESOLVING_P(NODE) \
-  (TREE_LANG_FLAG_2 (TYPENAME_TYPE_CHECK (NODE)))
+  (TREE_LANG_FLAG_3 (TYPENAME_TYPE_CHECK (NODE)))
 
 /* [class.virtual]
 
@@ -5791,6 +5800,27 @@ enum tag_types {
   scope_type    /* namespace or tagged type name followed by :: */
 };
 
+/* Return the tag type of the given TYPENAME_TYPE.  */
+
+inline tag_types
+get_typename_tag_type (tree t)
+{
+  unsigned bit0 = TYPENAME_TYPE_TAG_BIT_0 (t);
+  unsigned bit1 = TYPENAME_TYPE_TAG_BIT_1 (t);
+  unsigned bit2 = TYPENAME_TYPE_TAG_BIT_2 (t);
+  return tag_types ((bit2 << 2) | (bit1 << 1) | bit0);
+}
+
+/* Set the tag type of the given TYPENAME_TYPE.  */
+
+inline void
+set_typename_tag_type (tree t, tag_types tag)
+{
+  TYPENAME_TYPE_TAG_BIT_0 (t) = (tag >> 0) & 1;
+  TYPENAME_TYPE_TAG_BIT_1 (t) = (tag >> 1) & 1;
+  TYPENAME_TYPE_TAG_BIT_2 (t) = (tag >> 2) & 1;
+}
+
 /* The various kinds of lvalues we distinguish.  */
 enum cp_lvalue_kind_flags {
   clk_none = 0,     /* Things that are not an lvalue.  */
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 74c862ec1c7d..5879a1b54fa0 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4843,9 +4843,7 @@ struct typename_info {
   tree scope;
   tree name;
   tree template_id;
-  bool enum_p;
-  bool class_p;
-  bool union_p;
+  tag_types tag_type;
 };
 
 struct typename_hasher : ggc_ptr_hash<tree_node>
@@ -4883,9 +4881,7 @@ struct typename_hasher : ggc_ptr_hash<tree_node>
     return (TYPE_IDENTIFIER (t1) == t2->name
            && TYPE_CONTEXT (t1) == t2->scope
            && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
-           && TYPENAME_IS_ENUM_P (t1) == t2->enum_p
-           && TYPENAME_IS_CLASS_P (t1) == t2->class_p
-           && TYPENAME_IS_UNION_P (t1) == t2->union_p);
+           && get_typename_type_tag (t1) == t2->tag_type);
   }
 };
 
@@ -4908,9 +4904,7 @@ build_typename_type (tree context, tree name, tree 
fullname,
   ti.scope = FROB_CONTEXT (context);
   ti.name = name;
   ti.template_id = fullname;
-  ti.enum_p = tag_type == enum_type;
-  ti.class_p = (tag_type == class_type || tag_type == record_type);
-  ti.union_p = tag_type == union_type;
+  ti.tag_type = tag_type;
   hashval_t hash = typename_hasher::hash (&ti);
 
   /* See if we already have this type.  */
@@ -4924,9 +4918,7 @@ build_typename_type (tree context, tree name, tree 
fullname,
       t = cxx_make_type (TYPENAME_TYPE);
       TYPE_CONTEXT (t) = ti.scope;
       TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
-      TYPENAME_IS_ENUM_P (t) = ti.enum_p;
-      TYPENAME_IS_CLASS_P (t) = ti.class_p;
-      TYPENAME_IS_UNION_P (t) = ti.union_p;
+      set_typename_tag_type (t, ti.tag_type);
 
       /* Build the corresponding TYPE_DECL.  */
       tree d = build_decl (input_location, TYPE_DECL, name, t);
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index ae899ec9f770..1359aaab7229 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -824,7 +824,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
       pp_cxx_cv_qualifier_seq (pp, t);
       pp_cxx_ws_string (pp,
                         TYPENAME_IS_ENUM_P (t) ? "enum"
-                        : TYPENAME_IS_CLASS_P (t) ? "class"
+                        : TYPENAME_IS_CLASS_OR_STRUCT_P (t) ? "class"
                         : TYPENAME_IS_UNION_P (t) ? "union"
                         : "typename");
       dump_typename (pp, t, flags);
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 7899fac8a2db..89b3522f869c 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -9727,16 +9727,7 @@ trees_out::type_node (tree type)
        tree_node (DECL_NAME (TYPE_NAME (type)));
        tree_node (TYPENAME_TYPE_FULLNAME (type));
        if (streaming_p ())
-         {
-           enum tag_types tag_type = none_type;
-           if (TYPENAME_IS_ENUM_P (type))
-             tag_type = enum_type;
-           else if (TYPENAME_IS_CLASS_P (type))
-             tag_type = class_type;
-           else if (TYPENAME_IS_UNION_P (type))
-             tag_type = union_type;
-           u (int (tag_type));
-         }
+         u (get_typename_tag_type (type));
        }
       break;
 
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 9fade00ac808..7d6228a0aaa1 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -17323,14 +17323,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
              return error_mark_node;
          }
 
-       /* FIXME: TYPENAME_IS_CLASS_P conflates 'class' vs 'struct' tags.
-          TYPENAME_TYPE should probably remember the exact tag that
-          was written for -Wmismatched-tags.  */
-       enum tag_types tag_type
-         = (TYPENAME_IS_CLASS_P (t) ? class_type
-            : TYPENAME_IS_UNION_P (t) ? union_type
-            : TYPENAME_IS_ENUM_P (t) ? enum_type
-            : typename_type);
+       enum tag_types tag_type = get_typename_tag_type (t);
        tsubst_flags_t tcomplain = complain | tf_keep_type_decl;
        tcomplain |= tst_ok_flag | qualifying_scope_flag;
        f = make_typename_type (ctx, f, tag_type, tcomplain);
@@ -17352,7 +17345,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
                else
                  return error_mark_node;
              }
-           else if (TYPENAME_IS_CLASS_P (t) && !NON_UNION_CLASS_TYPE_P (f))
+           else if (TYPENAME_IS_CLASS_OR_STRUCT_P (t)
+                    && !NON_UNION_CLASS_TYPE_P (f))
              {
                if (complain & tf_error)
                  error ("%qT resolves to %qT, which is not a non-union "
-- 
2.52.0.209.ge85ae279b0

Reply via email to