re PR c++/48707 ([c++0x] ICE initializing static const int)
authorJason Merrill <jason@redhat.com>
Mon, 25 Apr 2011 21:51:33 +0000 (17:51 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 25 Apr 2011 21:51:33 +0000 (17:51 -0400)
PR c++/48707
* decl.c (type_dependent_init_p): New.
(cp_finish_decl): Check it.
* pt.c (any_type_dependent_elements_p): New.
* cp-tree.h: Declare it.

From-SVN: r172941

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C [new file with mode: 0644]

index 965ee6ee73b7a462b3b34002aadc4188bb4f7eb3..d2dbe4ea2e81f191f782a6b0de426c7141ca870b 100644 (file)
@@ -1,3 +1,11 @@
+2011-04-25  Jason Merrill  <jason@redhat.com>
+
+       PR c++/48707
+       * decl.c (type_dependent_init_p): New.
+       (cp_finish_decl): Check it.
+       * pt.c (any_type_dependent_elements_p): New.
+       * cp-tree.h: Declare it.
+
 2011-04-20  Jason Merrill  <jason@redhat.com>
 
        * semantics.c (finish_compound_literal): Don't put an array
index e5388259ae68a76c6724b8248c46384dd8e2995e..66ac4e8d26dc31c06440fff74af8f565a0dc00bb 100644 (file)
@@ -5105,6 +5105,7 @@ extern bool dependent_template_p          (tree);
 extern bool dependent_template_id_p            (tree, tree);
 extern bool type_dependent_expression_p                (tree);
 extern bool any_type_dependent_arguments_p      (const VEC(tree,gc) *);
+extern bool any_type_dependent_elements_p       (const_tree);
 extern bool type_dependent_expression_p_push   (tree);
 extern bool value_dependent_expression_p       (tree);
 extern bool any_value_dependent_elements_p      (const_tree);
index cf4a40efed392b3fef6c3302f6b5cc6b923aea30..dcd18ab5b8884d7a9b242aea0132d2c37e1d7dee 100644 (file)
@@ -5700,6 +5700,36 @@ initialize_artificial_var (tree decl, VEC(constructor_elt,gc) *v)
   make_rtl_for_nonlocal_decl (decl, init, /*asmspec=*/NULL);
 }
 
+/* INIT is the initializer for a variable, as represented by the
+   parser.  Returns true iff INIT is type-dependent.  */
+
+static bool
+type_dependent_init_p (tree init)
+{
+  if (TREE_CODE (init) == TREE_LIST)
+    /* A parenthesized initializer, e.g.: int i (3, 2); ? */
+    return any_type_dependent_elements_p (init);
+  else if (TREE_CODE (init) == CONSTRUCTOR)
+  /* A brace-enclosed initializer, e.g.: int i = { 3 }; ? */
+    {
+      VEC(constructor_elt, gc) *elts;
+      size_t nelts;
+      size_t i;
+
+      elts = CONSTRUCTOR_ELTS (init);
+      nelts = VEC_length (constructor_elt, elts);
+      for (i = 0; i < nelts; ++i)
+       if (type_dependent_init_p (VEC_index (constructor_elt,
+                                             elts, i)->value))
+         return true;
+    }
+  else
+    /* It must be a simple expression, e.g., int i = 3;  */
+    return type_dependent_expression_p (init);
+
+  return false;
+}
+
 /* INIT is the initializer for a variable, as represented by the
    parser.  Returns true iff INIT is value-dependent.  */
 
@@ -5876,19 +5906,25 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
         template is instantiated.  But, if DECL is a variable constant
         then it can be used in future constant expressions, so its value
         must be available. */
-      if (init
-         && init_const_expr_p
-         && !type_dependent_p
-         && decl_maybe_constant_var_p (decl)
-         && !value_dependent_init_p (init))
-       {
+
+      if (TREE_CODE (decl) != VAR_DECL || dependent_type_p (type))
+       /* We can't do anything if the decl has dependent type.  */;
+      else if (init
+              && init_const_expr_p
+              && !type_dependent_p
+              && decl_maybe_constant_var_p (decl)
+              && !type_dependent_init_p (init)
+              && !value_dependent_init_p (init))
+       {
+         /* This variable seems to be a non-dependent constant, so process
+            its initializer.  If check_initializer returns non-null the
+            initialization wasn't constant after all.  */
          tree init_code = check_initializer (decl, init, flags, &cleanup);
          if (init_code == NULL_TREE)
            init = NULL_TREE;
        }
-      else if (TREE_CODE (decl) == VAR_DECL
-              && !DECL_PRETTY_FUNCTION_P (decl)
-              && !type_dependent_p)
+      else if (!DECL_PRETTY_FUNCTION_P (decl))
+       /* Deduce array size even if the initializer is dependent.  */
        maybe_deduce_size_from_array_init (decl, init);
 
       if (init)
index fc69a0c11e0e2a3692b14d6db38abe4abc2ca952..70fcbba73955cc4dc5c126b3f5f54216c8792147 100644 (file)
@@ -18456,6 +18456,19 @@ any_type_dependent_arguments_p (const VEC(tree,gc) *args)
   return false;
 }
 
+/* Returns TRUE if LIST (a TREE_LIST whose TREE_VALUEs are
+   expressions) contains any type-dependent expressions.  */
+
+bool
+any_type_dependent_elements_p (const_tree list)
+{
+  for (; list; list = TREE_CHAIN (list))
+    if (value_dependent_expression_p (TREE_VALUE (list)))
+      return true;
+
+  return false;
+}
+
 /* Returns TRUE if LIST (a TREE_LIST whose TREE_VALUEs are
    expressions) contains any value-dependent expressions.  */
 
index 793c8266ca467485c247dbbb51b4f44feb436362..cd361e7e18c766666f63f35e4fe0e16a3b36f386 100644 (file)
@@ -1,3 +1,7 @@
+2011-04-25  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/regress/template-const2.C: New.
+
 2011-04-25  Jeff Law <law@redhat.com>
 
        * gcc.dg/tree-ssa/vrp56.c: new test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C b/gcc/testsuite/g++.dg/cpp0x/regress/template-const2.C
new file mode 100644 (file)
index 0000000..25354b3
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/48707
+// { dg-options -std=c++0x }
+
+struct A {
+  static int a();
+};
+
+template<typename X>
+struct B: A {
+  static int const b;
+};
+
+template<typename X>
+int const B<X>::b=B<X>::a();