This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR c++/23691
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 8 Sep 2005 12:01:08 -0700
- Subject: C++ PATCH: PR c++/23691
- Reply-to: mark at codesourcery dot com
This patch fixes another problem with the static data member change.
In particular, a static data member initialized by a
constant-expression is not value-dependent, so we need to instantiate
it when we see a use -- even when in the body of a template. Both PR
c++/23691 and c++/23771 were instances of this problem.
Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
4.0 branch.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2005-09-08 Mark Mitchell <mark@codesourcery.com>
PR c++/23691
* decl2.c (mark_used): Instantiate static data members initialized
by constants, even in a template.
2005-09-08 Mark Mitchell <mark@codesourcery.com>
PR c++/23691
* g++.dg/template/static16.C: New test.
Index: gcc/cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.797
diff -c -5 -p -r1.797 decl2.c
*** gcc/cp/decl2.c 6 Sep 2005 02:12:29 -0000 1.797
--- gcc/cp/decl2.c 8 Sep 2005 07:47:16 -0000
*************** check_default_args (tree x)
*** 3215,3230 ****
break;
}
}
}
void
mark_used (tree decl)
{
TREE_USED (decl) = 1;
! if (processing_template_decl || skip_evaluation)
return;
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
&& !TREE_ASM_WRITTEN (decl))
/* Remember it, so we can check it was defined. */
{
--- 3215,3256 ----
break;
}
}
}
+ /* Mark DECL as "used" in the program. If DECL is a specialization or
+ implicitly declared class member, generate the actual definition. */
+
void
mark_used (tree decl)
{
+ HOST_WIDE_INT saved_processing_template_decl = 0;
+
TREE_USED (decl) = 1;
! /* If we don't need a value, then we don't need to synthesize DECL. */
! if (skip_evaluation)
return;
+ /* Normally, we can wait until instantiation-time to synthesize
+ DECL. However, if DECL is a static data member initialized with
+ a constant, we need the value right now because a reference to
+ such a data member is not value-dependent. */
+ if (processing_template_decl)
+ {
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
+ && DECL_CLASS_SCOPE_P (decl)
+ && !dependent_type_p (DECL_CONTEXT (decl)))
+ {
+ /* Pretend that we are not in a template so that the
+ initializer for the static data member will be full
+ simplified. */
+ saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ }
+ else
+ return;
+ }
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
&& !TREE_ASM_WRITTEN (decl))
/* Remember it, so we can check it was defined. */
{
*************** mark_used (tree decl)
*** 3280,3287 ****
--- 3306,3315 ----
times. Maintaining a stack of active functions is expensive,
and the inliner knows to instantiate any functions it might
need. */
instantiate_decl (decl, /*defer_ok=*/true,
/*expl_inst_class_mem_p=*/false);
+
+ processing_template_decl = saved_processing_template_decl;
}
#include "gt-cp-decl2.h"
Index: gcc/testsuite/g++.dg/template/static16.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/static16.C
diff -N gcc/testsuite/g++.dg/template/static16.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/static16.C 8 Sep 2005 07:47:16 -0000
***************
*** 0 ****
--- 1,20 ----
+ // PR c++/23691
+
+ namespace std {
+ class type_info {
+ bool operator==(const type_info& __arg) const;
+ };
+ }
+ template <class T, T val> struct integral_constant {
+ static const T value = val;
+ };
+ template< typename T > struct is_integral : integral_constant<bool,false> {};
+ template <bool B> struct enable_if_c {};
+ template<typename Functor>
+ typename enable_if_c<(is_integral<Functor>::value)>::type
+ operator==(const int& f, Functor g);
+ template<class D>
+ int get_deleter( std::type_info const & ti )
+ {
+ return ti == typeid(D);
+ }