PR c++/81073 - constexpr and static var in statement-expression.
authorJason Merrill <jason@redhat.com>
Mon, 19 Jun 2017 18:20:10 +0000 (14:20 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 19 Jun 2017 18:20:10 +0000 (14:20 -0400)
* typeck2.c (store_init_value): Always call
require_potential_constant_expression.
* pt.c (convert_nontype_argument): Likewise.
* constexpr.c (potential_constant_expression_1): Adjust message.
Use decl_maybe_constant_var_p instead of decl_constant_var_p.
* decl2.c (decl_maybe_constant_var_p): Consider initializer.

From-SVN: r249382

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-trivial2.C
gcc/testsuite/g++.dg/ext/stmtexpr19.C [new file with mode: 0644]

index 5b90bbff94bcb306de1f946dd10b76da7453bce5..55ba486d9f226fde6ee277b027e4efc0eeab5fbd 100644 (file)
@@ -1,3 +1,13 @@
+2017-06-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/81073 - constexpr and static var in statement-expression.
+       * typeck2.c (store_init_value): Always call
+       require_potential_constant_expression.
+       * pt.c (convert_nontype_argument): Likewise.
+       * constexpr.c (potential_constant_expression_1): Adjust message.
+       Use decl_maybe_constant_var_p instead of decl_constant_var_p.
+       * decl2.c (decl_maybe_constant_var_p): Consider initializer.
+
 2017-06-19  Nathan Sidwell  <nathan@acm.org>
 
        * pt.c (coerce_template_parms): Fix indentation.
index ae24e4010ff11e7db805f0dcbb31dd1996da4a98..569a247d6b0a81a41000856ebc2b0c7000730df9 100644 (file)
@@ -5212,10 +5212,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
       if (want_rval
          && !var_in_maybe_constexpr_fn (t)
          && !type_dependent_expression_p (t)
-         && !decl_constant_var_p (t)
+         && !decl_maybe_constant_var_p (t)
          && (strict
              || !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t))
-             || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t))
+             || (DECL_INITIAL (t)
+                 && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t)))
          && COMPLETE_TYPE_P (TREE_TYPE (t))
          && !is_really_empty_class (TREE_TYPE (t)))
         {
@@ -5540,21 +5541,21 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
            {
              if (flags & tf_error)
                error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
-                         "%<static%> in %<constexpr%> function", tmp);
+                         "%<static%> in %<constexpr%> context", tmp);
              return false;
            }
          else if (CP_DECL_THREAD_LOCAL_P (tmp))
            {
              if (flags & tf_error)
                error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
-                         "%<thread_local%> in %<constexpr%> function", tmp);
+                         "%<thread_local%> in %<constexpr%> context", tmp);
              return false;
            }
          else if (!DECL_NONTRIVIALLY_INITIALIZED_P (tmp))
            {
              if (flags & tf_error)
                error_at (DECL_SOURCE_LOCATION (tmp), "uninitialized "
-                         "variable %qD in %<constexpr%> function", tmp);
+                         "variable %qD in %<constexpr%> context", tmp);
              return false;
            }
        }
index 72239ec620812fa6f889f61f24fa2a413549b7aa..a4751460e065172821a49d4d0611d54068b2fd42 100644 (file)
@@ -4145,10 +4145,19 @@ decl_maybe_constant_var_p (tree decl)
     /* A proxy isn't constant.  */
     return false;
   if (TREE_CODE (type) == REFERENCE_TYPE)
-    /* References can be constant.  */
+    /* References can be constant.  */;
+  else if (CP_TYPE_CONST_NON_VOLATILE_P (type)
+          && INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+    /* And const integers.  */;
+  else
+    return false;
+
+  if (DECL_INITIAL (decl)
+      && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+    /* We know the initializer, and it isn't constant.  */
+    return false;
+  else
     return true;
-  return (CP_TYPE_CONST_NON_VOLATILE_P (type)
-         && INTEGRAL_OR_ENUMERATION_TYPE_P (type));
 }
 
 /* Complain that DECL uses a type with no linkage.  In C++98 mode this is
index e5238ad2fa5ced2d88b69077e6b7616431e04966..69ca9291960681fcdb62ca002c7f1eb2fd1e7e7c 100644 (file)
@@ -6585,10 +6585,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
          if (complain & tf_error)
            {
              int errs = errorcount, warns = warningcount + werrorcount;
-             if (processing_template_decl
-                 && !require_potential_constant_expression (expr))
-               return NULL_TREE;
-             expr = cxx_constant_value (expr);
+             if (!require_potential_constant_expression (expr))
+               expr = error_mark_node;
+             else
+               expr = cxx_constant_value (expr);
              if (errorcount > errs || warningcount + werrorcount > warns)
                inform (loc, "in template argument for type %qT ", type);
              if (expr == error_mark_node)
index 4623d6d9197e478129765cf28a964fa4235c430c..430ba30536a0f9719f0ef0cb3a21540138124060 100644 (file)
@@ -821,8 +821,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
          || (DECL_IN_AGGR_P (decl) && !DECL_VAR_DECLARED_INLINE_P (decl)))
        {
          /* Diagnose a non-constant initializer for constexpr.  */
-         if (processing_template_decl
-             && !require_potential_constant_expression (value))
+         if (!require_potential_constant_expression (value))
            value = error_mark_node;
          else
            value = cxx_constant_value (value, decl);
index 450a0b5f9d4705eeeb0c6210c6ad1acd193255b8..ccb8d81adca6054a075a67b0b44cf22f46d21fbb 100644 (file)
@@ -16,5 +16,5 @@ constexpr int i = ai.f();
 constexpr int b = A<B>().f();  // { dg-error "" }
 
 template <class T>
-constexpr int f (T t) { return 42; } // { dg-error "parameter" }
-constexpr int x = f(B());           // { dg-error "constexpr" }
+constexpr int f (T t) { return 42; }
+constexpr int x = f(B());           // { dg-error "non-literal" }
index d24111465e391b95a6be126a5b9d1e240bd0e83a..005f07befb9cd9518b8326be5d54adc2fbaa4a5d 100644 (file)
@@ -10,5 +10,5 @@ struct T
 
 int main()
 {
-    constexpr T t = (T{} = T{});
+    constexpr T t = (T{} = T{}); // { dg-error "" "" { target c++11_only } }
 }
diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr19.C b/gcc/testsuite/g++.dg/ext/stmtexpr19.C
new file mode 100644 (file)
index 0000000..0c19a21
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/81073
+// { dg-options "" }
+// { dg-do compile { target c++11 } }
+
+struct test { const int *addr; };
+
+const test* setup()
+{
+  static constexpr test atest =
+    {
+      ({ static const int inner = 123; &inner; }) // { dg-error "static" }
+    };
+
+  return &atest;
+}
+
+int main(){}