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);
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);
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);
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);
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)
--- /dev/null
+// 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 };