]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/30759 (initializer-list accepted for object of non-POD type)
authorSimon Martin <simartin@users.sourceforge.net>
Thu, 7 Jun 2007 19:59:33 +0000 (19:59 +0000)
committerSimon Martin <simartin@gcc.gnu.org>
Thu, 7 Jun 2007 19:59:33 +0000 (19:59 +0000)
gcc/

2007-06-07  Simon Martin  <simartin@users.sourceforge.net>

PR c++/30759
* c-common.h (flag_cpp0x): Replaced by...
(cxx_dialect): ... this new variable specifying the C++ dialect that
is used.
* c-common.c (flag_cpp0x): Removed.
(cxx_dialect): Defined.
* c-cppbuiltin.c (c_cpp_builtins): flag_cpp0x rewritten in terms of
cxx_dialect.
* c-opts.c (c_common_post_options): Likewise.
(set_std_cxx98): Set cxx_dialect to cxx98.
(set_std_cxx0x): Set cxx_dialect to cxx0x.

gcc/cp/

2007-06-07  Simon Martin  <simartin@users.sourceforge.net>

PR c++/30759
* decl.c (check_initializer): Report an error when a brace enclosed
initializer is used for a non-aggregate type in C++98.
(redeclaration_error_message): Rewrote flag_cpp0x in terms of
cxx_dialect.
(grokdeclarator): Likewise.
(move_fn_p): Likewise.
* typeck.c (check_return_expr): Likewise.
* call.c (reference_binding): Likewise.
* error.c (cp_cpp_error): Likewise.
* pt.c (check_default_tmpl_args): Likewise.
(tsubst): Likewise.
* lex.c (init_reswords): Likewise.
* parser.c (p_parser_primary_expression): Likewise.
(TOKEN_PRECEDENCE): Likewise.
(cp_parser_init_declarator): Likewise.
(cp_parser_ptr_operator): Likewise.
(cp_parser_parameter_declaration): Likewise.
(cp_parser_enclosed_template_argument_list): Likewise.
(cp_parser_skip_to_end_of_template_parameter_list): Likewise.
(cp_parser_next_token_ends_template_argument_p): Likewise.

gcc/testsuite/

2007-06-07  Simon Martin  <simartin@users.sourceforge.net>

PR c++/30759
* g++.dg/init/brace6.C: New test.

From-SVN: r125539

15 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-cppbuiltin.c
gcc/c-opts.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/decl.c
gcc/cp/error.c
gcc/cp/lex.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/brace6.C [new file with mode: 0644]

index ba69834d817ccc6c4f687f889814235f9583a67d..30e9f6ec38e2de488c263b95ec1a2bb6a81cb26a 100644 (file)
@@ -1,3 +1,17 @@
+2007-06-07  Simon Martin  <simartin@users.sourceforge.net>
+
+       PR c++/30759
+       * c-common.h (flag_cpp0x): Replaced by...
+       (cxx_dialect): ... this new variable specifying the C++ dialect that
+       is used.
+       * c-common.c (flag_cpp0x): Removed.
+       (cxx_dialect): Defined.
+       * c-cppbuiltin.c (c_cpp_builtins): flag_cpp0x rewritten in terms of
+       cxx_dialect.
+       * c-opts.c (c_common_post_options): Likewise.
+       (set_std_cxx98): Set cxx_dialect to cxx98.
+       (set_std_cxx0x): Set cxx_dialect to cxx0x.
+
 2007-06-06  Geoffrey Keating  <geoffk@apple.com>
            Hui-May Chang <hm.chang@apple.com>
 
index b9032188c5a742b538e813b18b90aebe4b5d5f63..f17bb7fef686bc29576672943616d8940b7a5ae8 100644 (file)
@@ -406,10 +406,9 @@ int flag_access_control = 1;
 
 int flag_check_new;
 
-/* Nonzero if we want to allow the use of experimental features that
-   are likely to become part of C++0x. */
+/* The C++ dialect being used. C++98 is the default.  */
 
-int flag_cpp0x = 0;
+enum cxx_dialect cxx_dialect = cxx98;
 
 /* Nonzero if we want the new ISO rules for pushing a new scope for `for'
    initialization variables.
index c60ce562a3829c5d88c59bd6fb54847bebfa0b68..62032c62c686419762019654e26d84c7eea8a7b8 100644 (file)
@@ -543,10 +543,18 @@ extern int flag_access_control;
 
 extern int flag_check_new;
 
-/* Nonzero if we want to allow the use of experimental features that
-   are likely to become part of C++0x. */
+/* The supported C++ dialects.  */
+
+enum cxx_dialect {
+  /* C++98  */
+  cxx98,
+  /* Experimental features that are likely to become part of
+     C++0x.  */
+  cxx0x
+};
 
-extern int flag_cpp0x;
+/* The C++ dialect being used. C++98 is the default.  */
+extern enum cxx_dialect cxx_dialect;
 
 /* Nonzero if we want the new ISO rules for pushing a new scope for `for'
    initialization variables.
index 1b52da0297558e7e5e3d999338e3102be1b8752d..19bb47c14102ae17943dba9a534c202106475cc9 100644 (file)
@@ -419,7 +419,7 @@ c_cpp_builtins (cpp_reader *pfile)
        cpp_define (pfile, "__GXX_WEAK__=0");
       if (warn_deprecated)
        cpp_define (pfile, "__DEPRECATED");
-      if (flag_cpp0x)
+      if (cxx_dialect == cxx0x)
         cpp_define (pfile, "__GXX_EXPERIMENTAL_CXX0X__");
     }
   /* Note that we define this for C as well, so that we know if
index b11e671e49bc2236a64a84f1015b88ef43d33b9d..d0fafc6f9dbcd740b7541d0f9bccf2d630b50fcd 100644 (file)
@@ -1145,7 +1145,7 @@ c_common_post_options (const char **pfilename)
 
   /* If we're allowing C++0x constructs, don't warn about C++0x
      compatibility problems.  */
-  if (flag_cpp0x)
+  if (cxx_dialect == cxx0x)
     warn_cxx0x_compat = 0;
 
   if (flag_preprocess_only)
@@ -1610,6 +1610,7 @@ set_std_cxx98 (int iso)
   flag_no_gnu_keywords = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
+  cxx_dialect = cxx98;
 }
 
 /* Set the C++ 0x working draft "standard" (without GNU extensions if ISO).  */
@@ -1620,7 +1621,7 @@ set_std_cxx0x (int iso)
   flag_no_gnu_keywords = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
-  flag_cpp0x = 1;
+  cxx_dialect = cxx0x;
 }
 
 /* Handle setting implicit to ON.  */
index 1f04e284c67ed87347c072f67ed4bd43593a15bd..bc6bdd19d7e076cd122281550748fdc489ed75a9 100644 (file)
@@ -1,3 +1,27 @@
+2007-06-07  Simon Martin  <simartin@users.sourceforge.net>
+
+       PR c++/30759
+       * decl.c (check_initializer): Report an error when a brace enclosed
+       initializer is used for a non-aggregate type in C++98.
+       (redeclaration_error_message): Rewrote flag_cpp0x in terms of
+       cxx_dialect.
+       (grokdeclarator): Likewise.
+       (move_fn_p): Likewise.
+       * typeck.c (check_return_expr): Likewise.
+       * call.c (reference_binding): Likewise.
+       * error.c (cp_cpp_error): Likewise.
+       * pt.c (check_default_tmpl_args): Likewise.
+       (tsubst): Likewise.
+       * lex.c (init_reswords): Likewise.
+       * parser.c (p_parser_primary_expression): Likewise.
+       (TOKEN_PRECEDENCE): Likewise.
+       (cp_parser_init_declarator): Likewise.
+       (cp_parser_ptr_operator): Likewise.
+       (cp_parser_parameter_declaration): Likewise.
+       (cp_parser_enclosed_template_argument_list): Likewise.
+       (cp_parser_skip_to_end_of_template_parameter_list): Likewise.
+       (cp_parser_next_token_ends_template_argument_p): Likewise.
+
 2007-06-04  Simon Baldwin  <simonb@google.com>
 
        * decl.c (grokdeclarator): Readability change.  Moved case labels
index deae301882caf2afc19f98de3d696a24309c2840..6e6be645d6e59a4089a969543bb2c0101b032b39 100644 (file)
@@ -1160,7 +1160,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
      DR391. */
   if (compatible_p
       && (lvalue_p
-         || (flag_cpp0x
+         || ((cxx_dialect != cxx98)
              && (CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE (rto))
              && CLASS_TYPE_P (from))))
     {
index 2f65f1c105374a3208f711af9f2ed2991979781a..f7a9f1ec5475b381d8bf6f96605d2c1fd552b8a6 100644 (file)
@@ -2161,7 +2161,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
            default template-argument, that declaration shall be a
            definition and shall be the only declaration of the
            function template in the translation unit.  */
-      if (flag_cpp0x 
+      if ((cxx_dialect != cxx98) 
           && TREE_CODE (ot) == FUNCTION_DECL && DECL_FRIEND_P (ot)
           && !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl), 
                                        /*is_primary=*/1, /*is_partial=*/0,
@@ -4777,14 +4777,29 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
   else
     /* There is no way to make a variable-sized class type in GNU C++.  */
     gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
-  
-  if (!CP_AGGREGATE_TYPE_P (type)
-      && init && BRACE_ENCLOSED_INITIALIZER_P (init)
-      && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) != 1)
+
+  if (init && BRACE_ENCLOSED_INITIALIZER_P (init))
     {
-      error ("scalar object %qD requires one element in initializer", decl);
-      TREE_TYPE (decl) = error_mark_node;
-      return NULL_TREE;
+      int init_len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
+      if (SCALAR_TYPE_P (type))
+       {
+         if (init_len != 1)
+           {
+             error ("scalar object %qD requires one element in initializer",
+                    decl);
+             TREE_TYPE (decl) = error_mark_node;
+             return NULL_TREE;
+           }
+       }
+      else if ((cxx_dialect == cxx98) && !CP_AGGREGATE_TYPE_P (type))
+       {
+         /* A non-aggregate that is not a scalar cannot be initialized
+            via an initializer-list in C++98.  */
+         error ("braces around initializer for non-aggregate type %qT",
+                type);
+         TREE_TYPE (decl) = error_mark_node;
+         return NULL_TREE;
+       }
     }
 
   if (TREE_CODE (decl) == CONST_DECL)
@@ -7871,7 +7886,7 @@ grokdeclarator (const cp_declarator *declarator,
                 are still forbidden, occurs below. Reasoning behind the change
                 can be found in DR106, DR540, and the rvalue reference
                 proposals. */
-             else if (!flag_cpp0x)
+             else if (cxx_dialect == cxx98)
                {
                  error ("cannot declare reference to %q#T", type);
                  type = TREE_TYPE (type);
@@ -9217,8 +9232,8 @@ move_fn_p (tree d)
 
   gcc_assert (DECL_FUNCTION_MEMBER_P (d));
 
-  if (!flag_cpp0x)
-    /* There are no move constructors if we aren't in C++0x mode.  */
+  if (cxx_dialect == cxx98)
+    /* There are no move constructors if we are in C++98 mode.  */
     return false;
 
   if (TREE_CODE (d) == TEMPLATE_DECL
index 6121436a7949b53ca01cd9bf0a2041e56f847394..512944b5ce59b3f8d2dec8db548d239d7c844b6a 100644 (file)
@@ -2549,7 +2549,7 @@ cp_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
 void
 maybe_warn_variadic_templates (void)
 {
-  if (!flag_cpp0x && !in_system_header)
+  if ((cxx_dialect == cxx98) && !in_system_header)
     /* We really want to suppress this warning in system headers,
        because libstdc++ uses variadic templates even when we aren't
        in C++0x mode. */
index 080a843df413bc8106e2f8f58e8cbd079d3458c4..f1dc8643a01fbe5e4590944b3f944c77824c0564 100644 (file)
@@ -334,7 +334,7 @@ init_reswords (void)
   int mask = ((flag_no_asm ? D_ASM : 0)
              | D_OBJC
              | (flag_no_gnu_keywords ? D_EXT : 0)
-              | (flag_cpp0x ? 0 : D_CXX0X));
+              | ((cxx_dialect == cxx0x) ? 0 : D_CXX0X));
 
   ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
   for (i = 0; i < ARRAY_SIZE (reswords); i++)
index c1a3276bb8eaadb6c8508aad8505b02dbf3f9bdb..7b41a5682f2d7b58b356fddc0ad29230e030d104 100644 (file)
@@ -3109,7 +3109,7 @@ cp_parser_primary_expression (cp_parser *parser,
                  /* C++0x only: A ">>" treated like two ">" tokens,
                      in a template-argument-list.  */
                  && (next_token->type != CPP_RSHIFT
-                      || !flag_cpp0x
+                      || (cxx_dialect == cxx98)
                      || parser->greater_than_is_operator_p))
                cast_p = false;
            }
@@ -5887,11 +5887,11 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
    The binops_by_token map is used to get the tree codes for each <token> type.
    binary-expressions are associated according to a precedence table.  */
 
-#define TOKEN_PRECEDENCE(token)                                \
-(((token->type == CPP_GREATER                          \
-   || (flag_cpp0x && token->type == CPP_RSHIFT))       \
-  && !parser->greater_than_is_operator_p)              \
- ? PREC_NOT_OPERATOR                                   \
+#define TOKEN_PRECEDENCE(token)                                     \
+(((token->type == CPP_GREATER                               \
+   || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT)) \
+  && !parser->greater_than_is_operator_p)                   \
+ ? PREC_NOT_OPERATOR                                        \
  : binops_by_token[token->type].prec)
 
 static tree
@@ -11974,7 +11974,8 @@ cp_parser_init_declarator (cp_parser* parser,
                      ((is_parenthesized_init || !is_initialized)
                     ? 0 : LOOKUP_ONLYCONVERTING));
     }
-  else if (flag_cpp0x && friend_p && decl && TREE_CODE (decl) == FUNCTION_DECL)
+  else if ((cxx_dialect != cxx98) && friend_p
+          && decl && TREE_CODE (decl) == FUNCTION_DECL)
     /* Core issue #226 (C++0x only): A default template-argument
        shall not be specified in a friend class template
        declaration. */
@@ -12590,7 +12591,8 @@ cp_parser_ptr_operator (cp_parser* parser,
     code = INDIRECT_REF;
   else if (token->type == CPP_AND)
     code = ADDR_EXPR;
-  else if (flag_cpp0x && token->type == CPP_AND_AND) /* C++0x only */
+  else if ((cxx_dialect != cxx98) &&
+          token->type == CPP_AND_AND) /* C++0x only */
     code = NON_LVALUE_EXPR;
 
   if (code != ERROR_MARK)
@@ -13273,7 +13275,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
                  break;
 
                 case CPP_RSHIFT:
-                  if (!flag_cpp0x)
+                  if (cxx_dialect == cxx98)
                     break;
                   /* Fall through for C++0x, which treats the `>>'
                      operator like two `>' tokens in certain
@@ -16808,7 +16810,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
      a '>>' instead, it's probably just a typo.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
     {
-      if (flag_cpp0x)
+      if (cxx_dialect != cxx98)
         {
           /* In C++0x, a `>>' in a template argument list or cast
              expression is considered to be two separate `>'
@@ -17338,7 +17340,7 @@ cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser)
          break;
 
         case CPP_RSHIFT:
-          if (!flag_cpp0x)
+          if (cxx_dialect == cxx98)
             /* C++0x views the `>>' operator as two `>' tokens, but
                C++98 does not. */
             break;
@@ -17460,7 +17462,7 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
   return (token->type == CPP_COMMA 
           || token->type == CPP_GREATER
           || token->type == CPP_ELLIPSIS
-         || (flag_cpp0x && token->type == CPP_RSHIFT));
+         || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT));
 }
 
 /* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the
index 47f3c0de05b2cc1aa09e7ba23f47ba7d6680225d..f3210dd5b8fdf8ca2dddf7ea5d91c7001ed6068d 100644 (file)
@@ -3447,7 +3447,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
 
   /* Core issue 226 (C++0x only): the following only applies to class
      templates.  */
-  if (!flag_cpp0x || TREE_CODE (decl) != FUNCTION_DECL)
+  if ((cxx_dialect == cxx98) || TREE_CODE (decl) != FUNCTION_DECL)
     {
       /* [temp.param]
 
@@ -3482,7 +3482,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
         }
     }
 
-  if ((!flag_cpp0x && TREE_CODE (decl) != TYPE_DECL)
+  if (((cxx_dialect == cxx98) && TREE_CODE (decl) != TYPE_DECL)
       || is_partial 
       || !is_primary
       || is_friend_decl)
@@ -3510,7 +3510,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
     msg = "default template arguments may not be used in function template friend re-declaration";
   else if (is_friend_decl)
     msg = "default template arguments may not be used in function template friend declarations";
-  else if (TREE_CODE (decl) == FUNCTION_DECL && !flag_cpp0x)
+  else if (TREE_CODE (decl) == FUNCTION_DECL && (cxx_dialect == cxx98))
     msg = "default template arguments may not be used in function templates";
   else if (is_partial)
     msg = "default template arguments may not be used in partial specializations";
@@ -8736,7 +8736,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          during instantiation is no longer a cause for failure. We
          only enforce this check in strict C++98 mode.  */
        if ((TREE_CODE (type) == REFERENCE_TYPE
-            && ((!flag_cpp0x && flag_iso) || code != REFERENCE_TYPE))
+            && (((cxx_dialect == cxx98) && flag_iso) || code != REFERENCE_TYPE))
            || (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
          {
            static location_t last_loc;
@@ -11537,9 +11537,9 @@ type_unification_real (tree tparms,
                If a template argument has not been deduced, its
                default template argument, if any, is used. 
 
-             When we are not in C++0x mode (i.e., !flag_cpp0x),
-             TREE_PURPOSE will either be NULL_TREE or ERROR_MARK_NODE,
-             so we do not need to explicitly check flag_cpp0x here.  */
+             When we are in C++98 mode, TREE_PURPOSE will either
+            be NULL_TREE or ERROR_MARK_NODE, so we do not need
+            to explicitly check cxx_dialect here.  */
           if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
             {
               tree arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)), 
index 4219e69433e17b2dd10f3bfa92ecc6d3288657b3..f17aa807de4fc9e5fc6914c471242bf6552b2d05 100644 (file)
@@ -6733,7 +6733,7 @@ check_return_expr (tree retval, bool *no_warning)
       /* Under C++0x [12.8/16 class.copy], a returned lvalue is sometimes
         treated as an rvalue for the purposes of overload resolution to
         favor move constructors over copy constructors.  */
-      if (flag_cpp0x 
+      if ((cxx_dialect != cxx98) 
           && named_return_value_okay_p
           /* The variable must not have the `volatile' qualifier.  */
          && !(cp_type_quals (TREE_TYPE (retval)) & TYPE_QUAL_VOLATILE)
index d364c9a0ca7e9d76768df07f69c5092798f57754..0c650e7fa5e1de3d2b0359c456b95896a4c660f6 100644 (file)
@@ -1,3 +1,8 @@
+2007-06-07  Simon Martin  <simartin@users.sourceforge.net>
+
+       PR c++/30759
+       * g++.dg/init/brace6.C: New test.
+
 2007-06-07  Geoffrey Keating  <geoffk@apple.com>
 
        * gcc.dg/attr-weakref-1-darwin.c: Run on all Darwin platforms.
diff --git a/gcc/testsuite/g++.dg/init/brace6.C b/gcc/testsuite/g++.dg/init/brace6.C
new file mode 100644 (file)
index 0000000..ffb7011
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR c++/30759 */
+/* { dg-do "compile" } */
+
+struct A {
+   A(int) { }
+};
+
+struct B {
+   B(const B&);
+   int b;
+};
+
+struct C {};
+
+struct D { int c; };
+
+int main()
+{
+   int i = { 1 };
+   int j = { 1, 2 }; /* { dg-error "requires one element" } */
+   A a = { 6 }; /* { dg-error "initializer for non" } */
+   B b = { 6 }; /* { dg-error "initializer for non" } */
+   C c = { 6 }; /* { dg-error "too many initializers" } */
+   D d = { 6 };
+}