From: Patrick Palka <ppalka@redhat.com>
To: gcc-patches@gcc.gnu.org
Cc: jason@redhat.com, Patrick Palka <ppalka@redhat.com>
Subject: [PATCH 1/2] c++: factor out TYPENAME_TYPE substitution
Date: Mon, 13 Feb 2023 12:23:39 -0500 [thread overview]
Message-ID: <20230213172340.849204-1-ppalka@redhat.com> (raw)
[N.B. this is a corrected version of
https://gcc.gnu.org/pipermail/gcc-patches/2022-November/607443.html ]
This patch factors out the TYPENAME_TYPE case of tsubst into a separate
function tsubst_typename_type. It also factors out the two tsubst flags
controlling TYPENAME_TYPE substitution, tf_keep_type_decl and tf_tst_ok,
into distinct boolean parameters of this new function (and of
make_typename_type). Consequently, callers which used to pass tf_tst_ok
to tsubst now instead must directly call tsubst_typename_type when
appropriate. In a subsequent patch we'll add another flag to
tsubst_typename_type controlling whether we want to ignore non-types
during the qualified lookup.
gcc/cp/ChangeLog:
* cp-tree.h (enum tsubst_flags): Remove tf_keep_type_decl
and tf_tst_ok.
(make_typename_type): Add two trailing boolean parameters
defaulted to false.
* decl.cc (make_typename_type): Replace uses of
tf_keep_type_decl and tf_tst_ok with the corresponding new
boolean parameters.
* pt.cc (tsubst_typename_type): New, factored out from tsubst
and adjusted after removing tf_keep_type_decl and tf_tst_ok.
(tsubst_decl) <case VAR_DECL>: Conditionally call
tsubst_typename_type directly instead of using tf_tst_ok.
(tsubst) <case TYPENAME_TYPE>: Call tsubst_typename_type.
(tsubst_copy) <case CAST_EXPR>: Conditionally call
tsubst_typename_type directly instead of using tf_tst_ok.
(tsubst_copy_and_build) <case CAST_EXPR>: Likewise.
<case CONSTRUCTOR>: Likewise.
---
gcc/cp/cp-tree.h | 9 +-
gcc/cp/decl.cc | 17 ++--
gcc/cp/pt.cc | 223 +++++++++++++++++++++++++----------------------
3 files changed, 134 insertions(+), 115 deletions(-)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 06bc64a6b8d..a7c5765fc33 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5573,8 +5573,7 @@ enum tsubst_flags {
tf_error = 1 << 0, /* give error messages */
tf_warning = 1 << 1, /* give warnings too */
tf_ignore_bad_quals = 1 << 2, /* ignore bad cvr qualifiers */
- tf_keep_type_decl = 1 << 3, /* retain typedef type decls
- (make_typename_type use) */
+ /* 1 << 3 available */
tf_ptrmem_ok = 1 << 4, /* pointers to member ok (internal
instantiate_type use) */
tf_user = 1 << 5, /* found template must be a user template
@@ -5594,8 +5593,7 @@ enum tsubst_flags {
(build_target_expr and friends) */
tf_norm = 1 << 11, /* Build diagnostic information during
constraint normalization. */
- tf_tst_ok = 1 << 12, /* Allow a typename-specifier to name
- a template (C++17 or later). */
+ /* 1 << 12 available */
tf_dguide = 1 << 13, /* Building a deduction guide from a ctor. */
/* Convenient substitution flags combinations. */
tf_warning_or_error = tf_warning | tf_error
@@ -6846,7 +6844,8 @@ extern tree declare_local_label (tree);
extern tree define_label (location_t, tree);
extern void check_goto (tree);
extern bool check_omp_return (void);
-extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t);
+extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t,
+ bool = false, bool = false);
extern tree build_typename_type (tree, tree, tree, tag_types);
extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
extern tree make_unbound_class_template_raw (tree, tree, tree);
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index d606b31d7a7..430533606b0 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4228,14 +4228,17 @@ build_typename_type (tree context, tree name, tree fullname,
/* Resolve `typename CONTEXT::NAME'. TAG_TYPE indicates the tag
provided to name the type. Returns an appropriate type, unless an
error occurs, in which case error_mark_node is returned. If we
- locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
+ locate a non-artificial TYPE_DECL and KEEP_TYPE_DECL is true, we
return that, rather than the _TYPE it corresponds to, in other
- cases we look through the type decl. If TF_ERROR is set, complain
- about errors, otherwise be quiet. */
+ cases we look through the type decl. If TEMPLATE_OK is true and
+ we found a TEMPLATE_DECL then we return a CTAD placeholder for the
+ TEMPLATE_DECL. If TF_ERROR is set, complain about errors, otherwise
+ be quiet. */
tree
make_typename_type (tree context, tree name, enum tag_types tag_type,
- tsubst_flags_t complain)
+ tsubst_flags_t complain, bool keep_type_decl /* = false */,
+ bool template_ok /* = false */)
{
tree fullname;
tree t;
@@ -4352,8 +4355,8 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
}
if (!want_template && TREE_CODE (t) != TYPE_DECL)
{
- if ((complain & tf_tst_ok) && cxx_dialect >= cxx17
- && DECL_TYPE_TEMPLATE_P (t))
+ if (template_ok && DECL_TYPE_TEMPLATE_P (t)
+ && cxx_dialect >= cxx17)
/* The caller permits this typename-specifier to name a template
(because it appears in a CTAD-enabled context). */;
else
@@ -4383,7 +4386,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
t = TYPE_NAME (t);
}
- if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
+ if (DECL_ARTIFICIAL (t) || !keep_type_decl)
t = TREE_TYPE (t);
maybe_record_typedef_use (t);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e89dbf47097..bc47bf15d38 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -13949,6 +13949,94 @@ tsubst_aggr_type_1 (tree t,
return t;
}
+/* Substitute ARGS into the TYPENAME_TYPE T. The flag TEMPLATE_OK
+ is passed to make_typename_type. */
+
+static tree
+tsubst_typename_type (tree t, tree args, tsubst_flags_t complain, tree in_decl,
+ bool template_ok = false)
+{
+ tree ctx = TYPE_CONTEXT (t);
+ if (TREE_CODE (ctx) == TYPE_PACK_EXPANSION)
+ {
+ ctx = tsubst_pack_expansion (ctx, args, complain, in_decl);
+ if (ctx == error_mark_node
+ || TREE_VEC_LENGTH (ctx) > 1)
+ return error_mark_node;
+ if (TREE_VEC_LENGTH (ctx) == 0)
+ {
+ if (complain & tf_error)
+ error ("%qD is instantiated for an empty pack",
+ TYPENAME_TYPE_FULLNAME (t));
+ return error_mark_node;
+ }
+ ctx = TREE_VEC_ELT (ctx, 0);
+ }
+ else
+ ctx = tsubst_aggr_type (ctx, args, complain, in_decl,
+ /*entering_scope=*/1);
+ if (ctx == error_mark_node)
+ return error_mark_node;
+
+ tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args,
+ complain, in_decl);
+ if (f == error_mark_node)
+ return error_mark_node;
+
+ if (!MAYBE_CLASS_TYPE_P (ctx))
+ {
+ if (complain & tf_error)
+ error ("%qT is not a class, struct, or union type", ctx);
+ return error_mark_node;
+ }
+ else if (!uses_template_parms (ctx) && !TYPE_BEING_DEFINED (ctx))
+ {
+ /* Normally, make_typename_type does not require that the CTX
+ have complete type in order to allow things like:
+
+ template <class T> struct S { typename S<T>::X Y; };
+
+ But, such constructs have already been resolved by this
+ point, so here CTX really should have complete type, unless
+ it's a partial instantiation. */
+ if (!complete_type_or_maybe_complain (ctx, NULL_TREE, complain))
+ return error_mark_node;
+ }
+
+ f = make_typename_type (ctx, f, typename_type, complain,
+ /*keep_type_decl=*/true, template_ok);
+ if (f == error_mark_node)
+ return f;
+ if (TREE_CODE (f) == TYPE_DECL)
+ {
+ complain |= tf_ignore_bad_quals;
+ f = TREE_TYPE (f);
+ }
+
+ if (TREE_CODE (f) != TYPENAME_TYPE)
+ {
+ if (TYPENAME_IS_ENUM_P (t) && TREE_CODE (f) != ENUMERAL_TYPE)
+ {
+ if (complain & tf_error)
+ error ("%qT resolves to %qT, which is not an enumeration type",
+ t, f);
+ else
+ return error_mark_node;
+ }
+ else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f))
+ {
+ if (complain & tf_error)
+ error ("%qT resolves to %qT, which is not a class type",
+ t, f);
+ else
+ return error_mark_node;
+ }
+ }
+
+ return cp_build_qualified_type
+ (f, cp_type_quals (f) | cp_type_quals (t), complain);
+}
+
/* Map from a FUNCTION_DECL to a vec of default argument instantiations,
indexed in reverse order of the parameters. */
@@ -15193,10 +15281,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
&& VAR_HAD_UNKNOWN_BOUND (t)
&& type != error_mark_node)
type = strip_array_domain (type);
- tsubst_flags_t tcomplain = complain;
- if (VAR_P (t))
- tcomplain |= tf_tst_ok;
- type = tsubst (type, args, tcomplain, in_decl);
+ if (VAR_P (t)
+ && TREE_CODE (type) == TYPENAME_TYPE
+ && !typedef_variant_p (type))
+ type = tsubst_typename_type (type, args, complain, in_decl,
+ /*template_ok=*/true);
+ else
+ type = tsubst (type, args, complain, in_decl);
/* Substituting the type might have recursively instantiated this
same alias (c++/86171). */
if (gen_tmpl && DECL_ALIAS_TEMPLATE_P (gen_tmpl)
@@ -15889,9 +15980,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
bool fndecl_type = (complain & tf_fndecl_type);
complain &= ~tf_fndecl_type;
- bool tst_ok = (complain & tf_tst_ok);
- complain &= ~tf_tst_ok;
-
if (type
&& code != TYPENAME_TYPE
&& code != TEMPLATE_TYPE_PARM
@@ -16424,89 +16512,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
case TYPENAME_TYPE:
- {
- tree ctx = TYPE_CONTEXT (t);
- if (TREE_CODE (ctx) == TYPE_PACK_EXPANSION)
- {
- ctx = tsubst_pack_expansion (ctx, args, complain, in_decl);
- if (ctx == error_mark_node
- || TREE_VEC_LENGTH (ctx) > 1)
- return error_mark_node;
- if (TREE_VEC_LENGTH (ctx) == 0)
- {
- if (complain & tf_error)
- error ("%qD is instantiated for an empty pack",
- TYPENAME_TYPE_FULLNAME (t));
- return error_mark_node;
- }
- ctx = TREE_VEC_ELT (ctx, 0);
- }
- else
- ctx = tsubst_aggr_type (ctx, args, complain, in_decl,
- /*entering_scope=*/1);
- if (ctx == error_mark_node)
- return error_mark_node;
-
- tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args,
- complain, in_decl);
- if (f == error_mark_node)
- return error_mark_node;
-
- if (!MAYBE_CLASS_TYPE_P (ctx))
- {
- if (complain & tf_error)
- error ("%qT is not a class, struct, or union type", ctx);
- return error_mark_node;
- }
- else if (!uses_template_parms (ctx) && !TYPE_BEING_DEFINED (ctx))
- {
- /* Normally, make_typename_type does not require that the CTX
- have complete type in order to allow things like:
-
- template <class T> struct S { typename S<T>::X Y; };
-
- But, such constructs have already been resolved by this
- point, so here CTX really should have complete type, unless
- it's a partial instantiation. */
- if (!complete_type_or_maybe_complain (ctx, NULL_TREE, complain))
- return error_mark_node;
- }
-
- tsubst_flags_t tcomplain = complain | tf_keep_type_decl;
- if (tst_ok)
- tcomplain |= tf_tst_ok;
- f = make_typename_type (ctx, f, typename_type, tcomplain);
- if (f == error_mark_node)
- return f;
- if (TREE_CODE (f) == TYPE_DECL)
- {
- complain |= tf_ignore_bad_quals;
- f = TREE_TYPE (f);
- }
-
- if (TREE_CODE (f) != TYPENAME_TYPE)
- {
- if (TYPENAME_IS_ENUM_P (t) && TREE_CODE (f) != ENUMERAL_TYPE)
- {
- if (complain & tf_error)
- error ("%qT resolves to %qT, which is not an enumeration type",
- t, f);
- else
- return error_mark_node;
- }
- else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f))
- {
- if (complain & tf_error)
- error ("%qT resolves to %qT, which is not a class type",
- t, f);
- else
- return error_mark_node;
- }
- }
-
- return cp_build_qualified_type
- (f, cp_type_quals (f) | cp_type_quals (t), complain);
- }
+ return tsubst_typename_type (t, args, complain, in_decl);
case UNBOUND_CLASS_TEMPLATE:
{
@@ -17391,10 +17397,14 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case IMPLICIT_CONV_EXPR:
CASE_CONVERT:
{
- tsubst_flags_t tcomplain = complain;
- if (code == CAST_EXPR)
- tcomplain |= tf_tst_ok;
- tree type = tsubst (TREE_TYPE (t), args, tcomplain, in_decl);
+ tree type = TREE_TYPE (t);
+ if (code == CAST_EXPR
+ && TREE_CODE (type) == TYPENAME_TYPE
+ && !typedef_variant_p (type))
+ type = tsubst_typename_type (type, args, complain, in_decl,
+ /*template_ok=*/true);
+ else
+ type = tsubst (type, args, complain, in_decl);
tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
return build1 (code, type, op0);
}
@@ -20430,13 +20440,16 @@ tsubst_copy_and_build (tree t,
case DYNAMIC_CAST_EXPR:
case STATIC_CAST_EXPR:
{
- tree type;
+ tree type = TREE_TYPE (t);
tree op, r = NULL_TREE;
- tsubst_flags_t tcomplain = complain;
- if (TREE_CODE (t) == CAST_EXPR)
- tcomplain |= tf_tst_ok;
- type = tsubst (TREE_TYPE (t), args, tcomplain, in_decl);
+ if (TREE_CODE (t) == CAST_EXPR
+ && TREE_CODE (type) == TYPENAME_TYPE
+ && !typedef_variant_p (type))
+ type = tsubst_typename_type (type, args, complain, in_decl,
+ /*template_ok=*/true);
+ else
+ type = tsubst (type, args, complain, in_decl);
op = RECUR (TREE_OPERAND (t, 0));
@@ -21421,10 +21434,14 @@ tsubst_copy_and_build (tree t,
bool need_copy_p = false;
tree r;
- tsubst_flags_t tcomplain = complain;
- if (COMPOUND_LITERAL_P (t))
- tcomplain |= tf_tst_ok;
- tree type = tsubst (TREE_TYPE (t), args, tcomplain, in_decl);
+ tree type = TREE_TYPE (t);
+ if (COMPOUND_LITERAL_P (t)
+ && TREE_CODE (type) == TYPENAME_TYPE
+ && !typedef_variant_p (type))
+ type = tsubst_typename_type (type, args, complain, in_decl,
+ /*template_ok=*/true);
+ else
+ type = tsubst (type, args, complain, in_decl);
if (type == error_mark_node)
RETURN (error_mark_node);
--
2.39.1.433.g23c56f7bd5
next reply other threads:[~2023-02-13 17:23 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-13 17:23 Patrick Palka [this message]
2023-02-13 17:23 ` [PATCH 2/2] c++: TYPENAME_TYPE lookup ignoring non-types [PR107773] Patrick Palka
2023-02-14 22:16 ` Jason Merrill
2023-02-14 22:15 ` [PATCH 1/2] c++: factor out TYPENAME_TYPE substitution Jason Merrill
2023-02-14 22:49 ` Jason Merrill
2023-02-15 17:21 ` Patrick Palka
2023-02-15 19:26 ` Jason Merrill
2023-02-15 20:11 ` Patrick Palka
2023-02-20 3:49 ` Jason Merrill
2023-02-22 0:05 ` Patrick Palka
2023-03-01 21:33 ` Jason Merrill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230213172340.849204-1-ppalka@redhat.com \
--to=ppalka@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).