From 74788b800931abc7ab79a06812799862eede96c0 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 13 Mar 2012 21:25:22 +0000 Subject: [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter gcc/cp/ PR c++/51641 * cp-tree.h (template_type_parameter_p): Declare new function. (parameter_of_template_p): Remove * pt.c (template_type_parameter_p): Define new function. (parameter_of_template_p): Remove. * name-lookup.c (binding_to_template_parms_of_scope_p): Don't rely on parameter_of_template_p anymore. Compare the level of the template parameter to the depth of the template. gcc/testsuite/ PR c++/51641 * g++.dg/lookup/hidden-class17.C: New test. Conflicts: gcc/cp/pt.c From-SVN: r185357 --- gcc/cp/ChangeLog | 11 +++++ gcc/cp/cp-tree.h | 2 +- gcc/cp/name-lookup.c | 28 +++++++++++-- gcc/cp/pt.c | 44 ++++++-------------- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/lookup/hidden-class17.C | 22 ++++++++++ 6 files changed, 75 insertions(+), 37 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class17.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f04ac604ae6..6ef5545fbf5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2012-01-30 Dodji Seketeli + + PR c++/51641 + * cp-tree.h (template_type_parameter_p): Declare new function. + (parameter_of_template_p): Remove + * pt.c (template_type_parameter_p): Define new function. + (parameter_of_template_p): Remove. + * name-lookup.c (binding_to_template_parms_of_scope_p): Don't rely + on parameter_of_template_p anymore. Compare the level of the + template parameter to the depth of the template. + 2011-12-15 Dodji Seketeli * call.c (standard_conversion, build_integral_nontype_arg_conv) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 71573ff0b37..d24c5961f27 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5361,10 +5361,10 @@ extern bool explicit_class_specialization_p (tree); extern int push_tinst_level (tree); extern void pop_tinst_level (void); extern struct tinst_level *outermost_tinst_level(void); -extern bool parameter_of_template_p (tree, tree); extern void init_template_processing (void); extern void print_template_statistics (void); bool template_template_parameter_p (const_tree); +bool template_type_parameter_p (const_tree); extern bool primary_template_instantiation_p (const_tree); extern tree get_primary_template_innermost_parameters (const_tree); extern tree get_template_parms_at_level (tree, int); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index e85d603d22f..886a7b13930 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4466,8 +4466,8 @@ static bool binding_to_template_parms_of_scope_p (cxx_binding *binding, cp_binding_level *scope) { - tree binding_value; - tree tinfo; + tree binding_value, tmpl, tinfo; + int level; if (!binding || !scope || !scope->this_entity) return false; @@ -4475,9 +4475,29 @@ binding_to_template_parms_of_scope_p (cxx_binding *binding, binding_value = binding->value ? binding->value : binding->type; tinfo = get_template_info (scope->this_entity); - return (tinfo + /* BINDING_VALUE must be a template parm. */ + if (binding_value == NULL_TREE + || (!DECL_P (binding_value) + || !DECL_TEMPLATE_PARM_P (binding_value))) + return false; + + /* The level of BINDING_VALUE. */ + level = + template_type_parameter_p (binding_value) + ? TEMPLATE_PARM_LEVEL (TEMPLATE_TYPE_PARM_INDEX + (TREE_TYPE (binding_value))) + : TEMPLATE_PARM_LEVEL (DECL_INITIAL (binding_value)); + + /* The template of the current scope, iff said scope is a primary + template. */ + tmpl = (tinfo && PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo)) - && parameter_of_template_p (binding_value, TI_TEMPLATE (tinfo))); + ? TI_TEMPLATE (tinfo) + : NULL_TREE); + + /* If the level of the parm BINDING_VALUE equals the depth of TMPL, + then BINDING_VALUE is a parameter of TMPL. */ + return (tmpl && level == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))); } /* Return the innermost non-namespace binding for NAME from a scope diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 54d540d0f52..6dd004e632d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2869,6 +2869,18 @@ template_template_parameter_p (const_tree parm) return DECL_TEMPLATE_TEMPLATE_PARM_P (parm); } +/* Return true iff PARM is a DECL representing a type template + parameter. */ + +bool +template_type_parameter_p (const_tree parm) +{ + return (parm + && (TREE_CODE (parm) == TYPE_DECL + || TREE_CODE (parm) == TEMPLATE_DECL) + && DECL_TEMPLATE_PARM_P (parm)); +} + /* Return the template parameters of T if T is a primary template instantiation, NULL otherwise. */ @@ -8118,38 +8130,6 @@ outermost_tinst_level (void) return level; } -/* Returns TRUE if PARM is a parameter of the template TEMPL. */ - -bool -parameter_of_template_p (tree parm, tree templ) -{ - tree parms; - int i; - - if (!parm || !templ) - return false; - - gcc_assert (DECL_TEMPLATE_PARM_P (parm)); - gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL); - - parms = DECL_TEMPLATE_PARMS (templ); - parms = INNERMOST_TEMPLATE_PARMS (parms); - - for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) - { - tree p = TREE_VALUE (TREE_VEC_ELT (parms, i)); - if (p == error_mark_node) - continue; - - if (parm == p - || (DECL_INITIAL (parm) - && DECL_INITIAL (parm) == DECL_INITIAL (p))) - return true; - } - - return false; -} - /* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL. ARGS is the vector of template arguments, as for tsubst. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2824244a7f8..bf9503c2981 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-01-30 Dodji Seketeli + + PR c++/51641 + * g++.dg/lookup/hidden-class17.C: New test. + 2012-03-13 Jakub Jelinek PR c/52577 diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class17.C b/gcc/testsuite/g++.dg/lookup/hidden-class17.C new file mode 100644 index 00000000000..3d5ccec39cc --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/hidden-class17.C @@ -0,0 +1,22 @@ +// Origin PR c++/51641 +// { dg-do compile } + +struct A { + struct B { typedef int X; }; +}; + +template struct C : A { + B::X q; // Ok: A::B. + struct U { typedef int X; }; + template + struct D; +}; + +template +template +struct C::D { + typename U::X r; // { dg-error "" } +}; + +C::D y; +