From 172a459435c48df322c74231fa60b8d10a36e2af Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Mon, 12 Jan 2009 22:47:49 +0000 Subject: [PATCH] re PR c++/36019 (template parameter does not hide class name) gcc/cp/ChangeLog: 2009-01-12 Dodji Seketeli PR c++/36019 * pt.c (parameter_of_template_p): New function. * cp-tree.h: Declare it. * name-lookup.c (binding_to_template_parms_of_scope_p): New function. (outer_binding): Take template parameters in account when looking for a name binding. gcc/testsuite/ChangeLog: 2009-01-12 Dodji Seketeli PR c++/36019 * g++.dg/lookup/hidden-class12.C: New test. * g++.dg/lookup/hidden-class13.C: New test. * g++.dg/lookup/hidden-class14.C: New test. * g++.dg/lookup/hidden-class15.C: New test. * g++.dg/lookup/hidden-class16.C: New test. From-SVN: r143315 --- gcc/cp/ChangeLog | 10 ++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/name-lookup.c | 35 ++++++++++++++++++-- gcc/cp/pt.c | 24 ++++++++++++++ gcc/testsuite/ChangeLog | 9 +++++ gcc/testsuite/g++.dg/lookup/hidden-class12.C | 24 ++++++++++++++ gcc/testsuite/g++.dg/lookup/hidden-class13.C | 25 ++++++++++++++ gcc/testsuite/g++.dg/lookup/hidden-class14.C | 23 +++++++++++++ gcc/testsuite/g++.dg/lookup/hidden-class15.C | 30 +++++++++++++++++ gcc/testsuite/g++.dg/lookup/hidden-class16.C | 27 +++++++++++++++ 10 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class12.C create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class13.C create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class14.C create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class15.C create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class16.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1a9ca4fc4c9..542b71d71be 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2009-01-12 Dodji Seketeli + + PR c++/36019 + * pt.c (parameter_of_template_p): New function. + * cp-tree.h: Declare it. + * name-lookup.c (binding_to_template_parms_of_scope_p): New + function. + (outer_binding): Take template parameters in account when looking for + a name binding. + 2009-01-12 Jason Merrill PR c++/31488 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9c89d9617a0..718167f0160 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4603,6 +4603,7 @@ extern bool reregister_specialization (tree, tree, tree); extern tree fold_non_dependent_expr (tree); extern bool explicit_class_specialization_p (tree); extern struct tinst_level *outermost_tinst_level(void); +extern bool parameter_of_template_p (tree, tree); /* in repo.c */ extern void init_repo (void); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 4c06afdafac..889d9ef559f 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3968,9 +3968,34 @@ qualified_lookup_using_namespace (tree name, tree scope, POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node); } +/* Subroutine of outer_binding. + Returns TRUE if BINDING is a binding to a template parameter of SCOPE, + FALSE otherwise. */ + +static bool +binding_to_template_parms_of_scope_p (cxx_binding *binding, + cxx_scope *scope) +{ + tree binding_value; + + if (!binding || !scope) + return false; + + binding_value = binding->value ? binding->value : binding->type; + + return (scope + && scope->this_entity + && get_template_info (scope->this_entity) + && parameter_of_template_p (binding_value, + TI_TEMPLATE (get_template_info \ + (scope->this_entity)))); +} + /* Return the innermost non-namespace binding for NAME from a scope - containing BINDING, or, if BINDING is NULL, the current scope. If - CLASS_P is false, then class bindings are ignored. */ + containing BINDING, or, if BINDING is NULL, the current scope. + Please note that for a given template, the template parameters are + considered to be in the scope containing the current scope. + If CLASS_P is false, then class bindings are ignored. */ cxx_binding * outer_binding (tree name, @@ -4018,6 +4043,12 @@ outer_binding (tree name, return class_binding; } } + /* If SCOPE is a template and if NAME binds to one of its template parameters + return the binding, otherwise we might miss it. */ + if (outer_scope && outer_scope->kind == sk_template_parms + && binding_to_template_parms_of_scope_p (outer, scope)) + return outer; + scope = scope->level_chain; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 410641de80d..de70e531d0b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6427,6 +6427,30 @@ 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) + if (parm == TREE_VALUE (TREE_VEC_ELT (parms, i))) + 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 53ad9ce495e..6d2fe902c0a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2009-01-12 Dodji Seketeli + + PR c++/36019 + * g++.dg/lookup/hidden-class12.C: New test. + * g++.dg/lookup/hidden-class13.C: New test. + * g++.dg/lookup/hidden-class14.C: New test. + * g++.dg/lookup/hidden-class15.C: New test. + * g++.dg/lookup/hidden-class16.C: New test. + 2009-01-12 Mark Mitchell * gcc.dg/struct/wo_prof_single_str_global.c: Mask return value. diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class12.C b/gcc/testsuite/g++.dg/lookup/hidden-class12.C new file mode 100644 index 00000000000..4a3f2d7618b --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/hidden-class12.C @@ -0,0 +1,24 @@ +// Contributed by Dodji Seketeli +// Origin PR c++/36019 +// { dg-do compile } + +struct F { + static const int x = 0; +}; + +struct A { + template + static int f () + { + return A::x; + } +}; + + +int +main () +{ + int i = A::f (); + return i; +} + diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class13.C b/gcc/testsuite/g++.dg/lookup/hidden-class13.C new file mode 100644 index 00000000000..2f685b2cb36 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/hidden-class13.C @@ -0,0 +1,25 @@ +// Contributed by Dodji Seketeli +// Origin PR c++/36019 +// { dg-do compile } + +struct F { + static const int x = 0; +}; + +struct B { + template + struct C + { + static int f () + { + return B::x; + } + }; +}; + +int +main () +{ + int j = B::C::f (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class14.C b/gcc/testsuite/g++.dg/lookup/hidden-class14.C new file mode 100644 index 00000000000..99bd6731b1b --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/hidden-class14.C @@ -0,0 +1,23 @@ +// Contributed by Dodji Seketeli +// Origin PR c++/36019 +// { dg-do compile } + +struct F { + static const int x = 0; + typedef int A; +}; + +struct A { + template + struct G : public F + { + static const A i = 0; + }; +}; + +int +main () +{ + return A::G::i ; +} + diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class15.C b/gcc/testsuite/g++.dg/lookup/hidden-class15.C new file mode 100644 index 00000000000..b0ed660a6a3 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/hidden-class15.C @@ -0,0 +1,30 @@ +// Contributed by Dodji Seketeli +// Origin PR c++/36019 +// { dg-do compile } + +struct F { + static const int y = 0; +}; + +struct A { + static const int x = 0; +}; + +struct B : public A { + template + struct C + { + static int f () + { + return A::x; // { dg-error "'x' is not a member of 'F'" } + } + }; +}; + +int +main () +{ + int j = B::C::f (); + return 0; +} + diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class16.C b/gcc/testsuite/g++.dg/lookup/hidden-class16.C new file mode 100644 index 00000000000..25cc4029408 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/hidden-class16.C @@ -0,0 +1,27 @@ +// Contributed by Dodji Seketeli +// Origin PR c++/36019 +// { dg-do compile } + +struct F { + static const int y = 0; +}; + +struct A { + static const int x = 0; +}; + +struct B : public A { + template + static int f () + { + return A::x; // { dg-error "'x' is not a member of 'F'" } + } +}; + +int +main () +{ + int j = B::f (); + return 0; +} +