aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-08-06 02:40:10 -0400
committerJason Merrill <jason@redhat.com>2020-08-18 16:20:08 -0400
commit9125cf8c33b710c378bfb3c7e67ec2f9f1c523c9 (patch)
tree5204a73a439256bc622a2d8ec0b53d2d4e7ea36f /gcc/cp
parent3c04bd60e56da399a441f73ebb687b5039b9cf3f (diff)
downloadgcc-9125cf8c33b710c378bfb3c7e67ec2f9f1c523c9.zip
gcc-9125cf8c33b710c378bfb3c7e67ec2f9f1c523c9.tar.gz
gcc-9125cf8c33b710c378bfb3c7e67ec2f9f1c523c9.tar.bz2
c++: Handle enumerator in C++20 alias CTAD. [PR96199]
To form a deduction guide for an alias template, we substitute the template arguments from the pattern into the deduction guide for the underlying class. In the case of B(A1<X>), that produces B(A1<B<T,1>::X>) -> B<T,1>. But since an enumerator doesn't have its own template info, and B<T,1> is a dependent scope, trying to look up B<T,1>::X fails and we crash. So we need to produce a SCOPE_REF instead. And trying to use the members of the template class is wrong for other members, as well, as it gives a nonsensical result if the class is specialized. gcc/cp/ChangeLog: PR c++/96199 * pt.c (maybe_dependent_member_ref): New. (tsubst_copy) [CONST_DECL]: Use it. [VAR_DECL]: Likewise. (tsubst_aggr_type): Handle nested type. gcc/testsuite/ChangeLog: PR c++/96199 * g++.dg/cpp2a/class-deduction-alias4.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/pt.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b80fe0a..585d944 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13391,6 +13391,17 @@ tsubst_aggr_type (tree t,
complain, in_decl);
if (argvec == error_mark_node)
r = error_mark_node;
+ else if (cxx_dialect >= cxx20 && dependent_scope_p (context))
+ {
+ /* See maybe_dependent_member_ref. */
+ tree name = TYPE_IDENTIFIER (t);
+ tree fullname = name;
+ if (instantiates_primary_template_p (t))
+ fullname = build_nt (TEMPLATE_ID_EXPR, name,
+ INNERMOST_TEMPLATE_ARGS (argvec));
+ return build_typename_type (context, name, fullname,
+ typename_type);
+ }
else
{
r = lookup_template_class (t, argvec, in_decl, context,
@@ -16313,6 +16324,32 @@ tsubst_init (tree init, tree decl, tree args,
return init;
}
+/* If T is a reference to a dependent member of the current instantiation C and
+ we are trying to refer to that member in a partial instantiation of C,
+ return a SCOPE_REF; otherwise, return NULL_TREE.
+
+ This can happen when forming a C++20 alias template deduction guide, as in
+ PR96199. */
+
+static tree
+maybe_dependent_member_ref (tree t, tree args, tsubst_flags_t complain,
+ tree in_decl)
+{
+ if (cxx_dialect < cxx20)
+ return NULL_TREE;
+
+ tree ctx = context_for_name_lookup (t);
+ if (!CLASS_TYPE_P (ctx))
+ return NULL_TREE;
+
+ ctx = tsubst (ctx, args, complain, in_decl);
+ if (dependent_scope_p (ctx))
+ return build_qualified_name (NULL_TREE, ctx, DECL_NAME (t),
+ /*template_p=*/false);
+
+ return NULL_TREE;
+}
+
/* Like tsubst, but deals with expressions. This function just replaces
template parms; to finish processing the resultant expression, use
tsubst_copy_and_build or tsubst_expr. */
@@ -16371,6 +16408,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (args == NULL_TREE)
return scalar_constant_value (t);
+ if (tree ref = maybe_dependent_member_ref (t, args, complain, in_decl))
+ return ref;
+
/* Unfortunately, we cannot just call lookup_name here.
Consider:
@@ -16421,6 +16461,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return t;
case VAR_DECL:
+ if (tree ref = maybe_dependent_member_ref (t, args, complain, in_decl))
+ return ref;
+ gcc_fallthrough();
case FUNCTION_DECL:
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
r = tsubst (t, args, complain, in_decl);