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