From: Dodji Seketeli Date: Mon, 12 Jan 2009 22:41:19 +0000 (+0000) Subject: re PR c++/36019 (template parameter does not hide class name) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e0c07607a24d10974ee3d47cb4e1740b94bb693;p=thirdparty%2Fgcc.git 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. * pt.c (get_template_info): Ditto. * cp-tree.h: Declare those. * 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. * gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C: Adjust testcase. From-SVN: r143313 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 172ccf76b9ef..9708b2138662 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2009-01-12 Dodji Seketeli + + PR c++/36019 + * pt.c (parameter_of_template_p): New function. + * pt.c (get_template_info): Ditto. + * cp-tree.h: Declare those. + * 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. + 2008-11-19 Dodji Seketeli PR c++/37142 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 48d8de8ff202..576fc28d79c0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4163,6 +4163,8 @@ extern bool reregister_specialization (tree, tree, tree); extern tree fold_non_dependent_expr (tree); extern bool explicit_class_specialization_p (tree); extern tree outermost_tinst_level (void); +extern tree get_template_info (tree t); +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 f02bf269fad3..f990a3bd616e 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3850,9 +3850,33 @@ 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, @@ -3900,6 +3924,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 67654df9d910..3bc9edff9a96 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -251,6 +251,25 @@ finish_member_template_decl (tree decl) return error_mark_node; } +/* Return the template info node corresponding to T, whatever T is. */ + +tree +get_template_info (tree t) +{ + tree tinfo = NULL_TREE; + + if (DECL_P (t) && DECL_LANG_SPECIFIC (t)) + tinfo = DECL_TEMPLATE_INFO (t); + + if (!tinfo && TREE_CODE (t) == TYPE_DECL) + t = TREE_TYPE (t); + + if (TAGGED_TYPE_P (t)) + tinfo = TYPE_TEMPLATE_INFO (t); + + return tinfo; +} + /* Returns the template nesting level of the indicated class TYPE. For example, in: @@ -5327,6 +5346,30 @@ outermost_tinst_level (void) return tree_last (current_tinst_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 268fbe0e1518..666bc5d7e102 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +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. + * gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C: Adjust testcase. + 2008-12-05 Eric Botcazou * gcc.dg/union-5.c: Run only on x86 and x86-64. 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 000000000000..4a3f2d7618be --- /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 000000000000..2f685b2cb363 --- /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 000000000000..99bd6731b1b0 --- /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 000000000000..b0ed660a6a3e --- /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 000000000000..25cc40294088 --- /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; +} + diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C b/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C index 73b99659e121..791850366df9 100644 --- a/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C +++ b/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C @@ -83,7 +83,7 @@ public: template struct Xfour {// { dg-error "" } .* int T10; // { dg-error "" } .* void f(){ - char T10; + char T10; // { dg-error "declaration of 'char T10'" } } }; @@ -126,8 +126,8 @@ public: template friend bool foo(T161 u) { - Xseven obj; // { dg-error "" } .* - return (obj.inst == u.inst); // { dg-error "" } .* + Xseven obj; + return (obj.inst == u.inst); } };