This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR c++/43327
- From: Dodji Seketeli <dodji at redhat dot com>
- To: jason at redhat dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 16 Mar 2010 11:51:25 +0100
- Subject: [PATCH] PR c++/43327
Hello,
Here is what I think is happening in this PR.
In the first test/example below, fold_non_dependent_expr does not fold a
static const variable into its constant value, but just returns the
variable as is.
Later when we try to find the most specialized class template of
A<C>::B<1,4> (in most_specialized_class), get_class_bindings fails when
calling unify.
It fails because unify doesn't expect the non-folded VAR_DECL C::m as a
template parameter of
template<> template<int_N> struct A<C>::B<_N, C::m> but rather expects
the C::m parm to be folded into 4.
This patch fixes tsubst_copy_and_build so that fold_non_dependent_expr
folds constant VAR_DECLs into their constant values.
The second hunk prevents unify to crash whenever a VAR_DECL sleeps
through. This situation can happen in the second example in the patch
below. In that case, unification should fail without crashing.
Tested on x86_64-unknown-linux-gnu against trunk.
Dodji
commit 65a606c2b667ab51f50d9568e7ad5e7df3c20e8c
Author: Dodji Seketeli <dodji@redhat.com>
Date: Tue Mar 16 11:28:37 2010 +0100
Draft fix for PR c++/43327
gcc/cp/ChangeLog:
PR c++/43327
pt.c (tsubst_copy_and_build): Fold const variables into their
values.
(unify): Handle VAR_DECLs.
gcc/testsuite/ChangeLog:
PR c++/43327
g++.dg/other/crash-10.C: New test.
g++.dg/other/crash-11.C: New test.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 66e7d73..03a46cf 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12714,7 +12714,14 @@ tsubst_copy_and_build (tree t,
case VAR_DECL:
if (!args)
- return t;
+ {
+ /* If the variable is a constant, fold it into its value. */
+ if (TREE_CONSTANT (t)
+ && !dependent_type_p (TREE_TYPE (t))
+ && !value_dependent_expression_p DECL_INITIAL (t))
+ return DECL_INITIAL (t);
+ return t;
+ }
/* Fall through */
case PARM_DECL:
@@ -15035,6 +15042,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
/* Matched cases are handled by the ARG == PARM test above. */
return 1;
+ case VAR_DECL:
+ /* A non-type template parameter that is a variable should be a
+ an integral constant, in which case, it whould have been
+ folded into its value. So we should not be getting a variable here. */
+ return 1;
+
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
diff --git a/gcc/testsuite/g++.dg/other/crash-10.C b/gcc/testsuite/g++.dg/other/crash-10.C
new file mode 100644
index 0000000..6dcd791
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/crash-10.C
@@ -0,0 +1,24 @@
+// Origin: PR c++/43327
+// { dg-do compile }
+
+template <typename _T>
+struct A
+{
+ template <int _N, int _M> struct B;
+
+ template <int _N>
+ struct B<_N, _T::m>
+ {
+ static void f();
+ };
+};
+
+struct C
+{
+ static const int m = 4;
+};
+
+void m()
+{
+ A<C>::B<1, 4>::f();
+}
diff --git a/gcc/testsuite/g++.dg/other/crash-11.C b/gcc/testsuite/g++.dg/other/crash-11.C
new file mode 100644
index 0000000..f2037f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/crash-11.C
@@ -0,0 +1,27 @@
+// Origin: PR c++/43327
+// { dg-do compile }
+
+template <typename _T>
+struct A
+{
+ template <int _N, int _M> struct B;
+
+ template <int _N>
+ struct B<_N, _T::m>
+ {
+ static void f();
+ };
+};
+
+struct C
+{
+ static int m;
+};
+
+void m()
+{
+ A<C>::B<1, 4>::f(); // { dg-error "incomplete type 'A<C>\:\:B<1, 4>'" }
+}
+
+int C::m = 4;
+