On 12/14/25 12:15 AM, Patrick Palka wrote:
On Sat, 13 Dec 2025, Patrick Palka wrote:
On Sat, 13 Dec 2025, Jason Merrill wrote:
On 12/13/25 11:23 PM, Patrick Palka wrote:
On Sat, 13 Dec 2025, Jason Merrill wrote:
On 12/12/25 10:39 PM, Patrick Palka wrote:
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.
What do you mean by "sound"? This only makes a difference for
-Wmismatched-tags, right?
True for record_type vs class_type which we now differentiate.
But I there's also scope_type tag_type which our current representation
of TYPENAME_TYPE can't encode, and so we effectively encode as
none_type. But scope_type indicates a type-only lookup context unlike
none_type.
Ah, right, please mention scope_type in the commit message. Did my other
comments make sense?
Done.
So building a TYPENAME_TYPE with tag_type=scope_type and then resolving
it (i.e. build_typename_type + make_typename_type) is different from
just doing the lookup immediately (i.e. just make_typename_type)
because we don't know the lookup is type-only anymore.
+/* Set the tag type of the given TYPENAME_TYPE. */
+
+inline void
+set_typename_tag_type (tree t, tag_types tag)
+{
Maybe assert that 'tag' fits in 3 bits?
Done.
+ 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/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");
If we're going to represent struct vs class, let's also print it here.
Turns out we already have a helper for that, tag_name, which I extended
and used here instead.
Oh and I opted to rename get/set_typename_type_tag to
get/set_typename_tag. The "_type" component of the name seems
unnecessary and it sidesteps the question of where it should
appear in the name, e.g.
get_typename_type_tag,
get_typename_tag_type, or perhaps
get_typename_tag_tag_type
OK.
Jason