decl.c (start_decl): Complain about static/thread_local vars in constexpr function.
authorJason Merrill <jason@redhat.com>
Fri, 3 Oct 2014 16:48:24 +0000 (12:48 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 3 Oct 2014 16:48:24 +0000 (12:48 -0400)
* decl.c (start_decl): Complain about static/thread_local vars
in constexpr function.
(check_for_uninitialized_const_var): Also uninitialized vars.
* parser.c (cp_parser_jump_statement): And gotos.
(cp_parser_asm_operand_list): And asm.
(cp_parser_try_block): And try.
* semantics.c (ensure_literal_type_for_constexpr_object): And
non-literal.

From-SVN: r215863

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C [new file with mode: 0644]

index 56c3bdbd51b9fa2f9597412f68a5faa25622f487..7a703aae203738db3ef4cafcfcdb95fd5678191b 100644 (file)
@@ -1,5 +1,14 @@
 2014-10-03  Jason Merrill  <jason@redhat.com>
 
+       * decl.c (start_decl): Complain about static/thread_local vars
+       in constexpr function.
+       (check_for_uninitialized_const_var): Also uninitialized vars.
+       * parser.c (cp_parser_jump_statement): And gotos.
+       (cp_parser_asm_operand_list): And asm.
+       (cp_parser_try_block): And try.
+       * semantics.c (ensure_literal_type_for_constexpr_object): And
+       non-literal.
+
        * semantics.c (constexpr_fn_retval): Ignore declarations in C++14.
        (var_in_constexpr_fn): New.
        (cxx_eval_constant_expression): Look into DECL_INITIAL.
index 7856dd836edb88ffc62bc1ccf83d75dcf70927ec..9c8ecc0c4d06a6167022924b1d40e4bb43151a92 100644 (file)
@@ -4767,6 +4767,16 @@ start_decl (const cp_declarator *declarator,
       DECL_THIS_STATIC (decl) = 1;
     }
 
+  if (current_function_decl && VAR_P (decl)
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+    {
+      if (DECL_THREAD_LOCAL_P (decl))
+       error ("%qD declared %<thread_local%> in %<constexpr%> function",
+              decl);
+      else if (TREE_STATIC (decl))
+       error ("%qD declared %<static%> in %<constexpr%> function", decl);
+    }
+
   if (!processing_template_decl && VAR_P (decl))
     start_decl_1 (decl, initialized);
 
@@ -5135,15 +5145,20 @@ check_for_uninitialized_const_var (tree decl)
      7.1.6 */
   if (VAR_P (decl)
       && TREE_CODE (type) != REFERENCE_TYPE
-      && CP_TYPE_CONST_P (type)
+      && (CP_TYPE_CONST_P (type) || var_in_constexpr_fn (decl))
       && !DECL_INITIAL (decl))
     {
       tree field = default_init_uninitialized_part (type);
       if (!field)
        return;
 
-      permerror (DECL_SOURCE_LOCATION (decl),
-                "uninitialized const %qD", decl);
+      if (CP_TYPE_CONST_P (type))
+       permerror (DECL_SOURCE_LOCATION (decl),
+                  "uninitialized const %qD", decl);
+      else
+       error_at (DECL_SOURCE_LOCATION (decl),
+                 "uninitialized variable %qD in %<constexpr%> function",
+                 decl);
 
       if (CLASS_TYPE_P (type))
        {
index 0050b8d21a00c74ab9043e6be84aa557e81375b7..18cae5bafd958c00099c1530108d9be229777c13 100644 (file)
@@ -10915,6 +10915,10 @@ cp_parser_jump_statement (cp_parser* parser)
       break;
 
     case RID_GOTO:
+      if (parser->in_function_body
+         && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+       error ("%<goto%> in %<constexpr%> function");
+
       /* Create the goto-statement.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_MULT))
        {
@@ -16484,6 +16488,11 @@ cp_parser_asm_definition (cp_parser* parser)
 
   /* Look for the `asm' keyword.  */
   cp_parser_require_keyword (parser, RID_ASM, RT_ASM);
+
+  if (parser->in_function_body
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+    error ("%<asm%> in %<constexpr%> function");
+
   /* See if the next token is `volatile'.  */
   if (cp_parser_allow_gnu_extensions_p (parser)
       && cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE))
@@ -21441,6 +21450,10 @@ cp_parser_try_block (cp_parser* parser)
   tree try_block;
 
   cp_parser_require_keyword (parser, RID_TRY, RT_TRY);
+  if (parser->in_function_body
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+    error ("%<try%> in %<constexpr%> function");
+
   try_block = begin_try_block ();
   cp_parser_compound_statement (parser, NULL, true, false);
   finish_try_block (try_block);
index 6c6a5c8821422f0de2165555571f567be3181f7a..5d1aafc1f2c253170cb1cc28cdf358f58f9c89df 100644 (file)
@@ -7537,7 +7537,9 @@ tree
 ensure_literal_type_for_constexpr_object (tree decl)
 {
   tree type = TREE_TYPE (decl);
-  if (VAR_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl)
+  if (VAR_P (decl)
+      && (DECL_DECLARED_CONSTEXPR_P (decl)
+         || var_in_constexpr_fn (decl))
       && !processing_template_decl)
     {
       tree stype = strip_array_types (type);
@@ -7546,8 +7548,12 @@ ensure_literal_type_for_constexpr_object (tree decl)
           when we try to initialize the variable.  */;
       else if (!literal_type_p (type))
        {
-         error ("the type %qT of constexpr variable %qD is not literal",
-                type, decl);
+         if (DECL_DECLARED_CONSTEXPR_P (decl))
+           error ("the type %qT of constexpr variable %qD is not literal",
+                  type, decl);
+         else
+           error ("variable %qD of non-literal type %qT in %<constexpr%> "
+                  "function", decl, type);
          explain_non_literal_class (type);
          return NULL;
        }
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C
new file mode 100644 (file)
index 0000000..ae3dcc6
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++14 } }
+
+struct A { A(); };
+
+constexpr int f(int i) {
+  static int j = i;            // { dg-error "static" }
+  thread_local int l = i;      // { dg-error "thread_local" }
+  goto foo;                    // { dg-error "goto" }
+ foo:
+  asm("foo");                  // { dg-error "asm" }
+  int k;                       // { dg-error "uninitialized" }
+  A a;                         // { dg-error "non-literal" }
+  return i;
+}
+
+// FIXME remove
+// { dg-prune-output "return" }