Patchwork C++ PATCH for c++/48936 (failure with static constant template variable in sizeof)

login
register
mail settings
Submitter Jason Merrill
Date May 9, 2011, 5:59 p.m.
Message ID <4DC82B94.1040505@redhat.com>
Download mbox | patch
Permalink /patch/94833/
State New
Headers show

Comments

Jason Merrill - May 9, 2011, 5:59 p.m.
This issue had to do with us bailing out too soon when trying to 
mark_used a constant variable in an unevaluated context.  I fixed this 
for 4.6 as part of the constexpr work, but a subset of that patch seems 
suitable for backporting.

Tested x86_64-pc-linux-gnu, applying to 4.4 and 4.5.
commit fc071e935530d226d24e08c25e5f66b0c61f0654
Author: Jason Merrill <jason@redhat.com>
Date:   Mon May 9 09:42:17 2011 -0400

    	PR c++/48936
    	* decl2.c (mark_used): Instantiate constant variables even
    	in unevaluated context.

Patch

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index d27ed43..6c33434 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3991,8 +3991,6 @@  possibly_inlined_p (tree decl)
 void
 mark_used (tree decl)
 {
-  HOST_WIDE_INT saved_processing_template_decl = 0;
-
   /* If DECL is a BASELINK for a single function, then treat it just
      like the DECL for the function.  Otherwise, if the BASELINK is
      for an overloaded function, we don't know which function was
@@ -4029,9 +4027,6 @@  mark_used (tree decl)
       error ("used here");
       return;
     }
-  /* If we don't need a value, then we don't need to synthesize DECL.  */
-  if (cp_unevaluated_operand != 0)
-    return;
 
   /* We can only check DECL_ODR_USED on variables or functions with
      DECL_LANG_SPECIFIC set, and these are also the only decls that we
@@ -4059,9 +4054,10 @@  mark_used (tree decl)
      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 (TREE_CODE (decl) == VAR_DECL
-      && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
-      && DECL_CLASS_SCOPE_P (decl))
+  if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+      && !DECL_INITIAL (decl)
+      && DECL_LANG_SPECIFIC (decl)
+      && DECL_TEMPLATE_INSTANTIATION (decl))
     {
       /* Don't try to instantiate members of dependent types.  We
 	 cannot just use dependent_type_p here because this function
@@ -4071,12 +4067,14 @@  mark_used (tree decl)
       if (CLASSTYPE_TEMPLATE_INFO ((DECL_CONTEXT (decl)))
 	  && uses_template_parms (CLASSTYPE_TI_ARGS (DECL_CONTEXT (decl))))
 	return;
-      /* Pretend that we are not in a template, even if we are, so
-	 that the static data member initializer will be processed.  */
-      saved_processing_template_decl = processing_template_decl;
-      processing_template_decl = 0;
+      instantiate_decl (decl, /*defer_ok=*/false,
+			/*expl_inst_class_mem_p=*/false);
     }
 
+  /* If we don't need a value, then we don't need to synthesize DECL.  */
+  if (cp_unevaluated_operand != 0)
+    return;
+
   if (processing_template_decl)
     return;
 
@@ -4149,8 +4147,6 @@  mark_used (tree decl)
        need.  Therefore, we always try to defer instantiation.  */
     instantiate_decl (decl, /*defer_ok=*/true,
 		      /*expl_inst_class_mem_p=*/false);
-
-  processing_template_decl = saved_processing_template_decl;
 }
 
 #include "gt-cp-decl2.h"
diff --git a/gcc/testsuite/g++.dg/template/nontype23.C b/gcc/testsuite/g++.dg/template/nontype23.C
new file mode 100644
index 0000000..dfda4fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/nontype23.C
@@ -0,0 +1,9 @@ 
+// PR c++/48936
+
+template <bool C> int foo (void);
+template <class T> struct S
+{
+  static const unsigned int a = sizeof (T);
+  enum { c = sizeof (foo <(a == 0)> ()) };
+};
+S<int> x;