* [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter
@ 2012-01-26 11:44 Dodji Seketeli
2012-01-26 22:13 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Dodji Seketeli @ 2012-01-26 11:44 UTC (permalink / raw)
To: GCC Patches; +Cc: Jason Merrill
Hello,
In the example of the patch, the U in 'typename U::X r' should bind to
the template parameter U rather than the class member U.
I think the problem comes from parameter_of_template_p that compares
parameters by using pointer equality, rather than by using type
equivalence like compparms does.
As a result, binding_to_template_parms_of_scope_p and then
outer_binding (via binding_to_template_parms_of_scope_p) misses the
template parameter U and returns the class member U instead.
Fixed thus, tested on x86_64-unknown-linux-gnu against trunk.
OK for trunk when stage 1 opens?
gcc/cp/
PR c++/51641
* cp-tree.h (template_type_parameter_p): Declare ...
* pt.c (template_type_parameter_p): ... new function.
(parameter_of_template_p): Rely on type equivalence rather
than pointer equality to compare template parms.
gcc/testsuite/
PR c++/51641
* g++.dg/lookup/hidden-class17.C: New test.
---
gcc/cp/cp-tree.h | 1 +
gcc/cp/pt.c | 29 ++++++++++++++++++++++---
gcc/testsuite/g++.dg/lookup/hidden-class17.C | 22 +++++++++++++++++++
3 files changed, 48 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class17.C
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f27755e..972c600 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5361,6 +5361,7 @@ 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/pt.c b/gcc/cp/pt.c
index e440be7..cb9554a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2890,6 +2890,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. */
@@ -8160,10 +8172,19 @@ parameter_of_template_p (tree parm, tree templ)
if (p == error_mark_node)
continue;
- if (parm == p
- || (DECL_INITIAL (parm)
- && DECL_INITIAL (parm) == DECL_INITIAL (p)))
- return true;
+ if (template_type_parameter_p (parm))
+ {
+ if (same_type_p (TREE_TYPE (parm), TREE_TYPE (p)))
+ return true;
+ }
+ else
+ {
+ if (DECL_INITIAL (parm)
+ && DECL_INITIAL (p)
+ && same_type_p (TREE_TYPE (DECL_INITIAL (parm)),
+ TREE_TYPE (DECL_INITIAL (p))))
+ return true;
+ }
}
return false;
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 0000000..3d5ccec
--- /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<class B> struct C : A {
+ B::X q; // Ok: A::B.
+ struct U { typedef int X; };
+ template<class U>
+ struct D;
+};
+
+template<class B>
+template<class U>
+struct C<B>::D {
+ typename U::X r; // { dg-error "" }
+};
+
+C<int>::D<double> y;
+
--
1.7.6.5
--
Dodji
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter
2012-01-26 11:44 [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter Dodji Seketeli
@ 2012-01-26 22:13 ` Jason Merrill
2012-01-27 23:20 ` Dodji Seketeli
0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2012-01-26 22:13 UTC (permalink / raw)
To: Dodji Seketeli; +Cc: GCC Patches
Comparing by same_type_p means that we treat any template parameter of
the appropriate level and index as equivalent. But that should be OK,
since we only have one set of level N template parameters in scope. So
I think we should be able to just compare the level of the template
parameter to the level of the parameters of the template. Right?
Jason
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter
2012-01-26 22:13 ` Jason Merrill
@ 2012-01-27 23:20 ` Dodji Seketeli
2012-01-29 21:01 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Dodji Seketeli @ 2012-01-27 23:20 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
Jason Merrill <jason@redhat.com> writes:
> Comparing by same_type_p means that we treat any template parameter of
> the appropriate level and index as equivalent. But that should be OK,
> since we only have one set of level N template parameters in scope.
> So I think we should be able to just compare the level of the template
> parameter to the level of the parameters of the template. Right?
OK. I understand that just comparing levels like that is not a good
enough implementation for parameter_of_template_p in the general case.
So I removed that function and did the test inline in
binding_to_template_parms_of_scope_p instead.
Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.
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.
---
gcc/cp/cp-tree.h | 2 +-
gcc/cp/name-lookup.c | 36 ++++++++++++++++-----
gcc/cp/pt.c | 44 +++++++-------------------
gcc/testsuite/g++.dg/lookup/hidden-class17.C | 22 +++++++++++++
4 files changed, 62 insertions(+), 42 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class17.C
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f27755e..71bca53 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5357,10 +5357,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 2351342..3330138 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4466,21 +4466,39 @@ static bool
binding_to_template_parms_of_scope_p (cxx_binding *binding,
cp_binding_level *scope)
{
- tree binding_value;
+ tree binding_value, tmpl;
+ int level;
if (!binding || !scope)
return false;
binding_value = binding->value ? binding->value : binding->type;
+ /* BINDING_VALUE must be a template parm. */
+ if (binding_value == NULL_TREE
+ && (!DECL_P (binding_value)
+ || !DECL_TEMPLATE_PARM_P (binding_value)))
+ return false;
- return (scope
- && scope->this_entity
- && get_template_info (scope->this_entity)
- && PRIMARY_TEMPLATE_P (TI_TEMPLATE
- (get_template_info (scope->this_entity)))
- && parameter_of_template_p (binding_value,
- TI_TEMPLATE (get_template_info \
- (scope->this_entity))));
+ /* 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 =
+ (scope
+ && scope->this_entity
+ && get_template_info (scope->this_entity)
+ && PRIMARY_TEMPLATE_P (TI_TEMPLATE (get_template_info (scope->this_entity))))
+ ? TI_TEMPLATE (get_template_info (scope->this_entity))
+ : 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 e440be7..76d09aa 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2890,6 +2890,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. */
@@ -8137,38 +8149,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/g++.dg/lookup/hidden-class17.C b/gcc/testsuite/g++.dg/lookup/hidden-class17.C
new file mode 100644
index 0000000..3d5ccec
--- /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<class B> struct C : A {
+ B::X q; // Ok: A::B.
+ struct U { typedef int X; };
+ template<class U>
+ struct D;
+};
+
+template<class B>
+template<class U>
+struct C<B>::D {
+ typename U::X r; // { dg-error "" }
+};
+
+C<int>::D<double> y;
+
--
1.7.6.5
--
Dodji
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter
2012-01-27 23:20 ` Dodji Seketeli
@ 2012-01-29 21:01 ` Jason Merrill
0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2012-01-29 21:01 UTC (permalink / raw)
To: Dodji Seketeli; +Cc: GCC Patches
On 01/27/2012 06:19 PM, Dodji Seketeli wrote:
> + /* BINDING_VALUE must be a template parm. */
> + if (binding_value == NULL_TREE
> + && (!DECL_P (binding_value)
> + || !DECL_TEMPLATE_PARM_P (binding_value)))
> + return false;
I think the && should be || here.
OK with that change.
Jason
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2012-01-29 21:01 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-26 11:44 [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter Dodji Seketeli
2012-01-26 22:13 ` Jason Merrill
2012-01-27 23:20 ` Dodji Seketeli
2012-01-29 21:01 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).