diff mbox

C++ PATCH to handling of overflow in in-class static member initializers

Message ID 51CBA49E.2000400@redhat.com
State New
Headers show

Commit Message

Jason Merrill June 27, 2013, 2:34 a.m. UTC
A question from a student of a committee member led me to notice that we 
were handling overflow in a class model of Fibonacci numbers oddly: 
C++11 says that arithmetic overflow causes an expression to not be 
constant, but instead of enforcing that on the actual affected variable 
initialization, we were initializing it fine and then preventing other 
expressions using that variable from being constant.

Checking this directly in store_init_value means we don't need to check 
in cp_finish_decl anymore.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 0bc5f82462c2a625608de5a69dcc54dbc08699c2
Author: Jason Merrill <jason@redhat.com>
Date:   Sun Jun 23 06:15:20 2013 -0400

    	* typeck2.c (store_init_value): Diagnose a non-constant
    	initializer for in-class static.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f562546..047fd77 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6346,25 +6346,6 @@  cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 	  cleanups = make_tree_vector ();
 	  init = check_initializer (decl, init, flags, &cleanups);
 
-	  /* Check that the initializer for a static data member was a
-	     constant.  Although we check in the parser that the
-	     initializer is an integral constant expression, we do not
-	     simplify division-by-zero at the point at which it
-	     occurs.  Therefore, in:
-
-	       struct S { static const int i = 7 / 0; };
-
-	     we issue an error at this point.  It would
-	     probably be better to forbid division by zero in
-	     integral constant expressions.  */
-	  if (DECL_EXTERNAL (decl) && init)
-	    {
-	      error ("%qD cannot be initialized by a non-constant expression"
-		     " when being declared", decl);
-	      DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
-	      init = NULL_TREE;
-	    }
-
 	  /* Handle:
 
 	     [dcl.init]
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index a447893..7932939 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -775,7 +775,8 @@  store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
       bool const_init;
       value = fold_non_dependent_expr (value);
       value = maybe_constant_init (value);
-      if (DECL_DECLARED_CONSTEXPR_P (decl))
+      if (DECL_DECLARED_CONSTEXPR_P (decl)
+	  || DECL_IN_AGGR_P (decl))
 	{
 	  /* Diagnose a non-constant initializer for constexpr.  */
 	  if (processing_template_decl
diff --git a/gcc/testsuite/g++.dg/cpp0x/overflow1.C b/gcc/testsuite/g++.dg/cpp0x/overflow1.C
new file mode 100644
index 0000000..7033e9c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/overflow1.C
@@ -0,0 +1,23 @@ 
+template <long long i>
+struct Fib
+{
+    static const long long value // { dg-error "overflow" }
+    = Fib<i-1>::value + Fib<i-2>::value;
+};
+
+template <>
+struct Fib<0>
+{
+   static const long long value = 0;
+};
+
+template <>
+struct Fib<1>
+{
+   static const long long value = 1;
+};
+
+int main()
+{
+  return Fib<95>::value;
+}
diff --git a/libstdc++-v3/testsuite/20_util/ratio/operations/ops_overflow_neg.cc b/libstdc++-v3/testsuite/20_util/ratio/operations/ops_overflow_neg.cc
index f0dcdec..f2f2330 100644
--- a/libstdc++-v3/testsuite/20_util/ratio/operations/ops_overflow_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/ratio/operations/ops_overflow_neg.cc
@@ -46,5 +46,6 @@  test02()
 // { dg-error "overflow in multiplication" "" { target *-*-* } 97 }
 // { dg-error "overflow in multiplication" "" { target *-*-* } 99 }
 // { dg-error "overflow in multiplication" "" { target *-*-* } 101 }
+// { dg-error "overflow in constant expression" "" { target *-*-* } 108 }
 // { dg-prune-output "out of range" }
 // { dg-prune-output "not usable in a constant expression" }