diff options
-rw-r--r-- | gcc/cp/call.cc | 9 | ||||
-rw-r--r-- | gcc/cp/pt.cc | 49 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/non-dependent19.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/non-dependent19a.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/non-dependent20.C | 16 |
5 files changed, 73 insertions, 31 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index b2e89c5..d6eed5e 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -11189,12 +11189,11 @@ build_new_method_call (tree instance, tree fns, vec<tree, va_gc> **args, if (really_overloaded_fn (fns)) { if (DECL_TEMPLATE_INFO (fn) - && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn)) - && dependent_type_p (DECL_CONTEXT (fn))) + && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn))) { - /* FIXME: We're not prepared to fully instantiate "inside-out" - partial instantiations such as A<T>::f<int>(). So instead - use the selected template, not the specialization. */ + /* Use the selected template, not the specialization, so that + this looks like an actual lookup result for sake of + filter_memfn_lookup. */ if (OVL_SINGLE_P (fns)) /* If the original overload set consists of a single function diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 5c995da..86b6ddc 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -16317,12 +16317,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) } /* OLDFNS is a lookup set of member functions from some class template, and - NEWFNS is a lookup set of member functions from a specialization of that - class template. Return the subset of NEWFNS which are specializations of - a function from OLDFNS. */ + NEWFNS is a lookup set of member functions from NEWTYPE, a specialization + of that class template. Return the subset of NEWFNS which are + specializations of a function from OLDFNS. */ static tree -filter_memfn_lookup (tree oldfns, tree newfns) +filter_memfn_lookup (tree oldfns, tree newfns, tree newtype) { /* Record all member functions from the old lookup set OLDFNS into VISIBLE_SET. */ @@ -16332,38 +16332,34 @@ filter_memfn_lookup (tree oldfns, tree newfns) if (TREE_CODE (fn) == USING_DECL) { /* FIXME: Punt on (dependent) USING_DECL for now; mapping - a dependent USING_DECL to its instantiation seems - tricky. */ + a dependent USING_DECL to the member functions it introduces + seems tricky. */ gcc_checking_assert (DECL_DEPENDENT_P (fn)); return newfns; } - else if (TREE_CODE (fn) == TEMPLATE_DECL) - /* A member function template. */ - visible_set.add (fn); - else if (TREE_CODE (fn) == FUNCTION_DECL) - { - if (DECL_TEMPLATE_INFO (fn)) - /* A non-template member function. */ - visible_set.add (DECL_TI_TEMPLATE (fn)); - else - /* A non-template member function from a non-template base, - injected via a using-decl. */ - visible_set.add (fn); - } else - gcc_unreachable (); + visible_set.add (fn); } /* Returns true iff (a less specialized version of) FN appeared in the old lookup set OLDFNS. */ - auto visible_p = [&visible_set] (tree fn) { - if (TREE_CODE (fn) == FUNCTION_DECL - && !DECL_TEMPLATE_INFO (fn)) + auto visible_p = [newtype, &visible_set] (tree fn) { + if (DECL_CONTEXT (fn) != newtype) + /* FN is a member function from a base class, introduced via a + non-dependent using-decl; look in the old lookup set for + FN exactly. */ return visible_set.contains (fn); - else if (DECL_TEMPLATE_INFO (fn)) + else if (TREE_CODE (fn) == TEMPLATE_DECL) + /* FN is a member function template from the current class; + look in the old lookup set for the TEMPLATE_DECL from which + it was specialized. */ return visible_set.contains (DECL_TI_TEMPLATE (fn)); else - gcc_unreachable (); + /* FN is a non-template member function from the current class; + look in the old lookup set for the FUNCTION_DECL from which + it was specialized. */ + return visible_set.contains (DECL_TEMPLATE_RESULT + (DECL_TI_TEMPLATE (fn))); }; bool lookup_changed_p = false; @@ -16455,7 +16451,8 @@ tsubst_baselink (tree baselink, tree object_type, performed in an incomplete-class context, within which later-declared members ought to remain invisible. */ BASELINK_FUNCTIONS (baselink) - = filter_memfn_lookup (fns, BASELINK_FUNCTIONS (baselink)); + = filter_memfn_lookup (fns, BASELINK_FUNCTIONS (baselink), + binfo_type); BASELINK_FUNCTIONS_MAYBE_INCOMPLETE_P (baselink) = true; } diff --git a/gcc/testsuite/g++.dg/template/non-dependent19.C b/gcc/testsuite/g++.dg/template/non-dependent19.C new file mode 100644 index 0000000..d690e80 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/non-dependent19.C @@ -0,0 +1,14 @@ +// PR c++/104432 +// { dg-do compile { target c++11 } } + +struct A { + template<class=int> void f(); + void f(int); +}; + +template<class> struct B : A { + using A::f; + void g() { f(); } +}; + +template struct B<int>; diff --git a/gcc/testsuite/g++.dg/template/non-dependent19a.C b/gcc/testsuite/g++.dg/template/non-dependent19a.C new file mode 100644 index 0000000..2f523c8 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/non-dependent19a.C @@ -0,0 +1,16 @@ +// PR c++/104432 +// { dg-do compile { target c++11 } } +// A variant of non-dependent19.C where A is a template. + +template<class> +struct A { + template<class=int> void f(); + void f(int); +}; + +template<class> struct B : A<int> { + using A<int>::f; + void g() { f(); } +}; + +template struct B<int>; diff --git a/gcc/testsuite/g++.dg/template/non-dependent20.C b/gcc/testsuite/g++.dg/template/non-dependent20.C new file mode 100644 index 0000000..ebf7d7f --- /dev/null +++ b/gcc/testsuite/g++.dg/template/non-dependent20.C @@ -0,0 +1,16 @@ +// PR c++/104432 +// { dg-do compile { target c++11 } } + +template<class T> +struct A { + template<class=int> static void f(T); + static void f(); +}; + +template<class> struct B : A<int>, A<int&> { + using A<int>::f; + using A<int&>::f; + void g() { f(0); } +}; + +template struct B<int>; |