This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR c++/23691


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);
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]