In my patch to fix template/inherit4.C after 83714, I made all SCOPE_REFs instantiation-dependent if the current class has dependent bases. This was excessive; only a reference to a non-static member of an unknown base needs to be treated as instantiation-dependent.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 6d409191cfcd993863e791672ae6de78444796b1 Author: Jason Merrill <ja...@redhat.com> Date: Fri Feb 9 13:31:27 2018 -0500 PR c++/84296 - ICE with qualified-id in template. PR c++/83714 * pt.c (unknown_base_ref_p): New. (instantiation_dependent_scope_ref_p): Use it instead of any_dependent_bases_p. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a9e47701527..9c57709e7a7 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -24012,6 +24012,30 @@ dependent_scope_p (tree scope) && !currently_open_class (scope)); } +/* T is a SCOPE_REF. Return whether it represents a non-static member of + an unknown base of 'this' (and is therefore instantiation-dependent). */ + +static bool +unknown_base_ref_p (tree t) +{ + if (!current_class_ptr) + return false; + + tree mem = TREE_OPERAND (t, 1); + if (shared_member_p (mem)) + return false; + + tree cur = current_nonlambda_class_type (); + if (!any_dependent_bases_p (cur)) + return false; + + tree ctx = TREE_OPERAND (t, 0); + if (DERIVED_FROM_P (ctx, cur)) + return false; + + return true; +} + /* T is a SCOPE_REF; return whether we need to consider it instantiation-dependent so that we can check access at instantiation time even though we know which member it resolves to. */ @@ -24021,9 +24045,7 @@ instantiation_dependent_scope_ref_p (tree t) { if (DECL_P (TREE_OPERAND (t, 1)) && CLASS_TYPE_P (TREE_OPERAND (t, 0)) - /* A dependent base could make a member inaccessible in the current - class. */ - && !any_dependent_bases_p () + && !unknown_base_ref_p (t) && accessible_in_template_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1))) return false; diff --git a/gcc/testsuite/g++.dg/template/scope5.C b/gcc/testsuite/g++.dg/template/scope5.C new file mode 100644 index 00000000000..629225cd556 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/scope5.C @@ -0,0 +1,66 @@ +// PR c++/84296 + +namespace b {} +namespace c { +using namespace b; +} +namespace b { +template <int d> struct e { static const int f = d; }; +} +template <typename> struct g; +template <typename h, typename i, typename aa, typename j> +struct g<h(i, aa, j)> : h::template ab<i, aa, j> {}; +struct k { + template <typename l> struct m { typedef typename g<l>::n o; }; +}; +template <typename> struct ac; +struct r { + typedef ac<int> p; +}; +template <typename q> struct s : k { + template <typename i, typename, typename> + struct ab : q::template t<typename i::u>::template ab<i, int, int> {}; +}; +struct ad { + typedef int u; +}; +template <typename> struct ae; +template <typename, typename ag> struct ah { + typedef ae<ag> ai; + typedef typename ai::template w<ai(r, int)>::o n; +}; +struct x { + template <typename i, typename, typename> struct ab : ah<i, int> {}; +}; +struct y { + struct z { + template <typename> struct t : x {}; + }; + struct aj : s<z> {}; +}; +template <typename i> struct ak { + typedef y::aj al; + typedef typename al::m<al(i, int, int)>::o o; +}; +struct am { + enum { an }; +}; +template <typename> struct ao {}; +template <typename af> struct ap : af::aq {}; +template <> struct ae<int> { + template <typename> struct w; + template <typename ar, typename as, typename at> struct w<ar(as, at)> { + typedef typename as::p o; + }; +}; +enum { a = b::e<0>::f }; +template <typename> class au; +template <typename av> struct ac : ao<av> { typedef c::e<am::an> aq; }; +template <typename aw, typename i, typename ax> void ay(aw, i, ax) { + au<c::e<ap<typename ak<i>::o>::f> > az(); +} +void v() { + ad a; + void az(); + ay(az, a, v); +}