This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 28235
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 18 Jul 2006 17:24:49 -0700
- Subject: C++ PATCH: PR 28235
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/28235, an ICE-on-valid regression. Here, we
were trying to substitute T for T in a static data member A<T>::i,
and, even though that's a no-op, we created a new node. Confusion
ensued.
Tested on x86_64-unknown-linux-gnu, applied on the mainline. Will
apply to 4.1 branch once testing completes.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
2006-07-18 Mark Mitchell <mark@codesourcery.com>
PR c++/28235
* pt.c (tsubst_decl): Handling substitutions into a static data
member from within the scope of the tempalte itself.
2006-07-18 Mark Mitchell <mark@codesourcery.com>
PR c++/28235
* g++.dg/template/static27.C: New test.
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (revision 115544)
+++ gcc/cp/pt.c (working copy)
@@ -6673,7 +6673,7 @@ tsubst_decl (tree t, tree args, tsubst_f
tree tmpl = NULL_TREE;
tree ctx;
tree type = NULL_TREE;
- int local_p;
+ bool local_p;
if (TREE_CODE (t) == TYPE_DECL)
{
@@ -6691,40 +6691,64 @@ tsubst_decl (tree t, tree args, tsubst_f
}
}
- /* Assume this is a non-local variable. */
- local_p = 0;
+ /* Check to see if we already have the specialization we
+ need. */
+ spec = NULL_TREE;
+ if (DECL_CLASS_SCOPE_P (t) || DECL_NAMESPACE_SCOPE_P (t))
+ {
+ /* T is a static data member or namespace-scope entity.
+ We have to substitute into namespace-scope variables
+ (even though such entities are never templates) because
+ of cases like:
+
+ template <class T> void f() { extern T t; }
+
+ where the entity referenced is not known until
+ instantiation time. */
+ local_p = false;
+ ctx = DECL_CONTEXT (t);
+ if (DECL_CLASS_SCOPE_P (t))
+ {
+ ctx = tsubst_aggr_type (ctx, args,
+ complain,
+ in_decl, /*entering_scope=*/1);
+ /* If CTX is unchanged, then T is in fact the
+ specialization we want. That situation occurs when
+ referencing a static data member within in its own
+ class. We can use pointer equality, rather than
+ same_type_p, because DECL_CONTEXT is always
+ canonical. */
+ if (ctx == DECL_CONTEXT (t))
+ spec = t;
+ }
- if (TYPE_P (CP_DECL_CONTEXT (t)))
- ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
- complain,
- in_decl, /*entering_scope=*/1);
- else if (DECL_NAMESPACE_SCOPE_P (t))
- ctx = DECL_CONTEXT (t);
+ if (!spec)
+ {
+ tmpl = DECL_TI_TEMPLATE (t);
+ gen_tmpl = most_general_template (tmpl);
+ argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
+ spec = (retrieve_specialization
+ (gen_tmpl, argvec,
+ /*class_specializations_p=*/false));
+ }
+ }
else
{
+ /* A local variable. */
+ local_p = true;
/* Subsequent calls to pushdecl will fill this in. */
ctx = NULL_TREE;
- local_p = 1;
+ spec = retrieve_local_specialization (t);
}
-
- /* Check to see if we already have this specialization. */
- if (!local_p)
- {
- tmpl = DECL_TI_TEMPLATE (t);
- gen_tmpl = most_general_template (tmpl);
- argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
- spec = retrieve_specialization (gen_tmpl, argvec,
- /*class_specializations_p=*/false);
- }
- else
- spec = retrieve_local_specialization (t);
-
+ /* If we already have the specialization we need, there is
+ nothing more to do. */
if (spec)
{
r = spec;
break;
}
+ /* Create a new node for the specialization we need. */
r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL)
{
Index: gcc/testsuite/g++.dg/template/static27.C
===================================================================
--- gcc/testsuite/g++.dg/template/static27.C (revision 0)
+++ gcc/testsuite/g++.dg/template/static27.C (revision 0)
@@ -0,0 +1,13 @@
+// PR c++/28235
+
+template<typename> struct A
+{
+ static const bool i = true;
+ template<bool = i> struct B {};
+ B<> b;
+};
+
+void f() {
+ A<int> a1, a2;
+ a1.b = a2.b;
+}