c++: Rewrite members for all deduction guides. [PR96199]
After the last patch, it occurred to me that we could run into the specialization issue with non-alias deduction guides as well, so this patch extends the rewriting to C++17 mode. Doing this revealed that we weren't properly pushing into class scope for normalization. gcc/cp/ChangeLog: PR c++/96199 * pt.c (tsubst_aggr_type): Rewrite in C++17, too. (maybe_dependent_member_ref): Likewise. (build_deduction_guide): Re-substitute template parms. * cp-tree.h (struct push_nested_class_guard): New. * constraint.cc (get_normalized_constraints_from_decl): Use it. gcc/testsuite/ChangeLog: PR c++/96199 * g++.dg/cpp1z/class-deduction-spec1.C: New test.
This commit is contained in:
parent
9125cf8c33
commit
b871301f09
4 changed files with 71 additions and 4 deletions
|
@ -840,6 +840,8 @@ get_normalized_constraints_from_decl (tree d, bool diag = false)
|
|||
if (tree *p = hash_map_safe_get (normalized_map, tmpl))
|
||||
return *p;
|
||||
|
||||
push_nested_class_guard pncs (DECL_CONTEXT (d));
|
||||
|
||||
tree args = generic_targs_for (tmpl);
|
||||
tree ci = get_constraints (decl);
|
||||
tree norm = get_normalized_constraints_from_info (ci, args, tmpl, diag);
|
||||
|
|
|
@ -8137,6 +8137,24 @@ is_constrained_auto (const_tree t)
|
|||
return is_auto (t) && PLACEHOLDER_TYPE_CONSTRAINTS (t);
|
||||
}
|
||||
|
||||
/* RAII class to push/pop class scope T; if T is not a class, do nothing. */
|
||||
|
||||
struct push_nested_class_guard
|
||||
{
|
||||
bool push;
|
||||
push_nested_class_guard (tree t)
|
||||
: push (t && CLASS_TYPE_P (t))
|
||||
{
|
||||
if (push)
|
||||
push_nested_class (t);
|
||||
}
|
||||
~push_nested_class_guard ()
|
||||
{
|
||||
if (push)
|
||||
pop_nested_class ();
|
||||
}
|
||||
};
|
||||
|
||||
#if CHECKING_P
|
||||
namespace selftest {
|
||||
extern void run_cp_tests (void);
|
||||
|
|
17
gcc/cp/pt.c
17
gcc/cp/pt.c
|
@ -13391,7 +13391,7 @@ 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))
|
||||
else if (cxx_dialect >= cxx17 && dependent_scope_p (context))
|
||||
{
|
||||
/* See maybe_dependent_member_ref. */
|
||||
tree name = TYPE_IDENTIFIER (t);
|
||||
|
@ -16328,14 +16328,13 @@ tsubst_init (tree init, tree decl, tree args,
|
|||
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. */
|
||||
This can happen when forming a C++17 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)
|
||||
if (cxx_dialect < cxx17)
|
||||
return NULL_TREE;
|
||||
|
||||
tree ctx = context_for_name_lookup (t);
|
||||
|
@ -28370,6 +28369,16 @@ build_deduction_guide (tree type, tree ctor, tree outer_args, tsubst_flags_t com
|
|||
fargs = tsubst (fargs, tsubst_args, complain, ctor);
|
||||
current_template_parms = save_parms;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Substitute in the same arguments to rewrite class members into
|
||||
references to members of an unknown specialization. */
|
||||
cp_evaluated ev;
|
||||
fparms = tsubst_arg_types (fparms, targs, NULL_TREE, complain, ctor);
|
||||
fargs = tsubst (fargs, targs, complain, ctor);
|
||||
if (ci)
|
||||
ci = tsubst_constraint_info (ci, targs, complain, ctor);
|
||||
}
|
||||
|
||||
--processing_template_decl;
|
||||
if (!ok)
|
||||
|
|
38
gcc/testsuite/g++.dg/cpp1z/class-deduction-spec1.C
Normal file
38
gcc/testsuite/g++.dg/cpp1z/class-deduction-spec1.C
Normal file
|
@ -0,0 +1,38 @@
|
|||
// PR c++/96199
|
||||
// { dg-do compile { target c++17 } }
|
||||
|
||||
template<int> struct A1 { };
|
||||
template<int&> struct A2 { };
|
||||
template<class> struct A3 { };
|
||||
|
||||
int i;
|
||||
template<typename V> struct B {
|
||||
enum E { X };
|
||||
B(A1<X>, V) { }
|
||||
|
||||
constexpr static V& ir = i;
|
||||
B(A2<ir>, V) { }
|
||||
|
||||
B(A3<E>, V) { }
|
||||
};
|
||||
|
||||
// template<class T> B(A1<B<T>::X>,T) -> B<T>;
|
||||
// template<class T> B(A2<B<T>::ir>,T) -> B<T>;
|
||||
// template<class T> B(A3<typename B<T>::E>,T) -> B<T>;
|
||||
|
||||
int j;
|
||||
template <> struct B<int> {
|
||||
using V = int;
|
||||
|
||||
enum E { X = 1 };
|
||||
B(A1<X>, V) { }
|
||||
|
||||
constexpr static V& ir = j;
|
||||
B(A2<ir>, V) { }
|
||||
|
||||
B(A3<E>, V) { }
|
||||
};
|
||||
|
||||
B u1 { A1<1>(), 42 };
|
||||
B u2 { A2<j>(), 42 };
|
||||
B u3 { A3<B<int>::E>(), 42 };
|
Loading…
Add table
Reference in a new issue