OSDN Git Service

* NEWS: Document removal of "new X = ..." extension.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 11 Oct 2002 16:50:44 +0000 (16:50 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 11 Oct 2002 16:50:44 +0000 (16:50 +0000)
* class.c (initialize_array): Set TREE_HAS_CONSTRUCTOR on
brace-enclosed initializers.
* cp-tree.h (CP_AGGREGATE_TYPE_P): New macro.
(initialize_local_var): Remove declaration.
(expand_static_init): Likewise.
* decl.c (next_initializable_field): New function.
(reshape_init): Likewise.
(check_initializer): Use them.  Build dynamic initializer for
aggregates here too.
(initialize_local_var): Simplify, and incorporate cleanup
insertion code as well.
(destroy_local_var): Remove.
(cp_finish_decl): Tidy.
(expand_static_init): Fold checks for whether or not a variable
needs initialization into this function.  Simplify.
* decl2.c (do_static_initialization): Simplify.
* init.c (build_init): Do not set TREE_SIDE_EFFECTS when it will
be done for us automatically.
(expand_default_init): Handle brace-enclosed initializers
correctly.
(expand_aggr_init_1): Remove RTL-generation code.
(build_vec_init): Remove "new X = ..." support.
* parse.y (new_initializer): Likewise.
* rtti.c (get_pseudo_ti_init): Set TREE_HAS_CONSTRUCTOR on
brace-enclosed initializer.
(create_pseudo_type_info): Likewise.
* typeck2.c (store_init_value): Don't try to handle digest_init
being called more than once.
(digest_init): Tidy handling of brace-enclosed initializers.

* g++.dg/init/array1.C: Remove invalid braces.
* g++.dg/init/brace1.C: New test.
* g++.dg/init/copy2.C: Likewise.
* g++.dg/init/copy3.C: Likewise.
* g++.old-deja/g++.ext/arrnew.C: Change WARNING to ERROR.
* g++.old-deja/g++.mike/p9129.C: Add ERROR on invalid use of
braces.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@58053 138bc75d-0d04-0410-961f-82ee72b054a4

17 files changed:
gcc/cp/ChangeLog
gcc/cp/NEWS
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/parse.y
gcc/cp/rtti.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/array1.C
gcc/testsuite/g++.dg/init/brace1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/copy2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/copy3.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.ext/arrnew.C
gcc/testsuite/g++.old-deja/g++.mike/p9129.C

index 0c5af6e..c2a44c3 100644 (file)
@@ -1,3 +1,36 @@
+2002-10-11  Mark Mitchell  <mark@codesourcery.com>
+
+       * NEWS: Document removal of "new X = ..." extension.
+       * class.c (initialize_array): Set TREE_HAS_CONSTRUCTOR on
+       brace-enclosed initializers.
+       * cp-tree.h (CP_AGGREGATE_TYPE_P): New macro.
+       (initialize_local_var): Remove declaration.
+       (expand_static_init): Likewise.
+       * decl.c (next_initializable_field): New function.
+       (reshape_init): Likewise.
+       (check_initializer): Use them.  Build dynamic initializer for
+       aggregates here too.
+       (initialize_local_var): Simplify, and incorporate cleanup
+       insertion code as well.
+       (destroy_local_var): Remove.
+       (cp_finish_decl): Tidy.
+       (expand_static_init): Fold checks for whether or not a variable
+       needs initialization into this function.  Simplify.
+       * decl2.c (do_static_initialization): Simplify.
+       * init.c (build_init): Do not set TREE_SIDE_EFFECTS when it will
+       be done for us automatically.
+       (expand_default_init): Handle brace-enclosed initializers
+       correctly.
+       (expand_aggr_init_1): Remove RTL-generation code.
+       (build_vec_init): Remove "new X = ..." support.
+       * parse.y (new_initializer): Likewise.
+       * rtti.c (get_pseudo_ti_init): Set TREE_HAS_CONSTRUCTOR on
+       brace-enclosed initializer.
+       (create_pseudo_type_info): Likewise.
+       * typeck2.c (store_init_value): Don't try to handle digest_init
+       being called more than once.
+       (digest_init): Tidy handling of brace-enclosed initializers.
+       
 2002-10-10  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * decl.c (typename_hash): Use htab_hash_pointer.
index caee3fb..85642b5 100644 (file)
@@ -1,3 +1,7 @@
+*** Changes in GCC 3.3:
+
+* The "new X = 3" extension has been removed; you must now use "new X(3)".
+
 *** Changes in GCC 3.1:
 
 * -fhonor-std and -fno-honor-std have been removed. -fno-honor-std was
index 267bd78..5b53325 100644 (file)
@@ -6994,6 +6994,7 @@ initialize_array (decl, inits)
   context = DECL_CONTEXT (decl);
   DECL_CONTEXT (decl) = NULL_TREE;
   DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
+  TREE_HAS_CONSTRUCTOR (DECL_INITIAL (decl)) = 1;
   cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
   DECL_CONTEXT (decl) = context;
 }
index 5701a50..97b7177 100644 (file)
@@ -2437,8 +2437,18 @@ struct lang_decl GTY(())
    || TYPE_PTRMEM_P (TYPE)                     \
    || TYPE_PTRMEMFUNC_P (TYPE))
 
-/* Nonzero for _TYPE means that the _TYPE defines
-   at least one constructor.  */
+/* [dcl.init.aggr]
+
+   An aggregate is an array or a class with no user-declared
+   constructors, no private or protected non-static data members, no
+   base classes, and no virtual functions.  */
+#define CP_AGGREGATE_TYPE_P(TYPE)              \
+  (TREE_CODE (TYPE) == ARRAY_TYPE              \
+   || (CLASS_TYPE_P (TYPE)                     \
+       && !CLASSTYPE_NON_AGGREGATE (TYPE)))
+
+/* Nonzero for a class type means that the class type has a
+   user-declared constructor.  */
 #define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1 (NODE))
 
 /* When appearing in an INDIRECT_REF, it means that the tree structure
@@ -3667,8 +3677,6 @@ extern void start_decl_1                  PARAMS ((tree));
 extern void cp_finish_decl                     PARAMS ((tree, tree, tree, int));
 extern void finish_decl                                PARAMS ((tree, tree, tree));
 extern void maybe_inject_for_scope_var          PARAMS ((tree));
-extern void initialize_local_var                PARAMS ((tree, tree, int));
-extern void expand_static_init                 PARAMS ((tree, tree));
 extern tree start_handler_parms                 PARAMS ((tree, tree));
 extern int complete_array_type                 PARAMS ((tree, tree, int));
 extern tree build_ptrmemfunc_type              PARAMS ((tree));
index 735aa1b..f4651db 100644 (file)
@@ -121,11 +121,10 @@ static void pop_labels PARAMS ((tree));
 static void maybe_deduce_size_from_array_init PARAMS ((tree, tree));
 static void layout_var_decl PARAMS ((tree));
 static void maybe_commonize_var PARAMS ((tree));
-static tree check_initializer PARAMS ((tree, tree));
+static tree check_initializer (tree, tree, int);
 static void make_rtl_for_nonlocal_decl PARAMS ((tree, tree, const char *));
 static void save_function_data PARAMS ((tree));
 static void check_function_type PARAMS ((tree, tree));
-static void destroy_local_var PARAMS ((tree));
 static void begin_constructor_body PARAMS ((void));
 static void finish_constructor_body PARAMS ((void));
 static void begin_destructor_body PARAMS ((void));
@@ -143,6 +142,10 @@ static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
 static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
 static void store_parm_decls PARAMS ((tree));
 static int cp_missing_noreturn_ok_p PARAMS ((tree));
+static void initialize_local_var (tree, tree);
+static void expand_static_init (tree, tree);
+static tree next_initializable_field (tree);
+static tree reshape_init (tree, tree *);
 
 #if defined (DEBUG_BINDING_LEVELS)
 static void indent PARAMS ((void));
@@ -7727,14 +7730,220 @@ check_for_uninitialized_const_var (decl)
     error ("uninitialized const `%D'", decl);
 }
 
+/* FIELD is a FIELD_DECL or NULL.  In the former case, the value
+   returned is the next FIELD_DECL (possibly FIELD itself) that can be
+   initialized.  If there are no more such fields, the return value
+   will be NULL.  */
+
+static tree
+next_initializable_field (tree field)
+{
+  while (field
+        && (TREE_CODE (field) != FIELD_DECL
+            || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
+            || DECL_ARTIFICIAL (field)))
+    field = TREE_CHAIN (field);
+
+  return field;
+}
+
+/* Undo the brace-elision allowed by [dcl.init.aggr] in a
+   brace-enclosed aggregate initializer.
+
+   *INITP is one of a list of initializers describing a brace-enclosed
+   initializer for an entity of the indicated aggregate TYPE.  It may
+   not presently match the shape of the TYPE; for example:
+   
+     struct S { int a; int b; };
+     struct S a[] = { 1, 2, 3, 4 };
+
+   Here *INITP will point to TREE_LIST of four elements, rather than a
+   list of two elements, each itself a list of two elements.  This
+   routine transforms INIT from the former form into the latter.  The
+   revised initializer is returned.  */
+
+static tree
+reshape_init (tree type, tree *initp)
+{
+  tree inits;
+  tree old_init;
+  tree old_init_value;
+  tree new_init;
+  bool brace_enclosed_p;
+
+  old_init = *initp;
+  old_init_value = (TREE_CODE (*initp) == TREE_LIST
+                   ? TREE_VALUE (*initp) : old_init);
+
+  /* If the initializer is brace-enclosed, pull initializers from the
+     enclosed elements.  Advance past the brace-enclosed initializer
+     now.  */
+  if (TREE_CODE (old_init_value) == CONSTRUCTOR 
+      && TREE_HAS_CONSTRUCTOR (old_init_value))
+    {
+      *initp = TREE_CHAIN (old_init);
+      TREE_CHAIN (old_init) = NULL_TREE;
+      inits = CONSTRUCTOR_ELTS (old_init_value);
+      initp = &inits;
+      brace_enclosed_p = true;
+    }
+  else
+    {
+      inits = NULL_TREE;
+      brace_enclosed_p = false;
+    }
+
+  /* A non-aggregate type is always initialized with a single
+     initializer.  */
+  if (!CP_AGGREGATE_TYPE_P (type))
+      {
+       *initp = TREE_CHAIN (old_init);
+       TREE_CHAIN (old_init) = NULL_TREE;
+       /* It is invalid to initialize a non-aggregate type with a
+          brace-enclosed initializer.  */
+       if (brace_enclosed_p)
+         {
+           error ("brace-enclosed initializer used to initialize `%T'",
+                  type);
+           if (TREE_CODE (old_init) == TREE_LIST)
+             TREE_VALUE (old_init) = error_mark_node;
+           else
+             old_init = error_mark_node;
+         }
+       
+       return old_init;
+      }
+
+  /* [dcl.init.aggr]
+
+     All implicit type conversions (clause _conv_) are considered when
+     initializing the aggregate member with an initializer from an
+     initializer-list.  If the initializer can initialize a member,
+     the member is initialized.  Otherwise, if the member is itself a
+     non-empty subaggregate, brace elision is assumed and the
+     initializer is considered for the initialization of the first
+     member of the subaggregate.  */
+  if (CLASS_TYPE_P (type) 
+      && !brace_enclosed_p
+      && can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value))
+    {
+      *initp = TREE_CHAIN (old_init);
+      TREE_CHAIN (old_init) = NULL_TREE;
+      return old_init;
+    }
+
+  if (TREE_CODE (old_init) == STRING_CST
+      && TREE_CODE (type) == ARRAY_TYPE
+      && char_type_p (TREE_TYPE (type)))
+    {
+      /* [dcl.init.string]
+
+        A char array (whether plain char, signed char, or unsigned char)
+        can be initialized by a string-literal (optionally enclosed in
+        braces); a wchar_t array can be initialized by a wide
+        string-literal (optionally enclosed in braces).  */
+      new_init = old_init;
+      /* Move past the initializer.  */
+      *initp = TREE_CHAIN (old_init);
+      TREE_CHAIN (old_init) = NULL_TREE;
+    }
+  else
+    {
+      /* Build a CONSTRUCTOR to hold the contents of the aggregate.  */  
+      new_init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+      TREE_HAS_CONSTRUCTOR (new_init) = 1;
+
+      if (CLASS_TYPE_P (type))
+       {
+         tree field;
+
+         field = next_initializable_field (TYPE_FIELDS (type));
+
+         if (!field)
+           {
+             /* [dcl.init.aggr]
+             
+                An initializer for an aggregate member that is an
+                empty class shall have the form of an empty
+                initializer-list {}.  */
+             if (!brace_enclosed_p)
+               error ("initializer for `%T' must be brace-enclosed",
+                      type);
+           }
+         else
+           {
+             /* Loop through the initializable fields, gathering
+                initializers.  */
+             while (*initp && field)
+               {
+                 tree field_init;
+
+                 field_init = reshape_init (TREE_TYPE (field), initp);
+                 TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
+                 CONSTRUCTOR_ELTS (new_init) = field_init;
+                 /* [dcl.init.aggr] 
+
+                    When a union  is  initialized with a brace-enclosed
+                    initializer, the braces shall only contain an
+                    initializer for the first member of the union.  */
+                 if (TREE_CODE (type) == UNION_TYPE)
+                   break;
+                 if (TREE_PURPOSE (field_init))
+                   field = TREE_PURPOSE (field_init);
+                 field = next_initializable_field (TREE_CHAIN (field));
+               }
+           }
+       }
+      else if (TREE_CODE (type) == ARRAY_TYPE)
+       {
+         tree index;
+         tree max_index;
+
+         /* If the bound of the array is known, take no more initializers
+            than are allowed.  */
+         max_index = (TYPE_DOMAIN (type) 
+                      ? array_type_nelts (type) : NULL_TREE);
+         /* Loop through the array elements, gathering initializers.  */
+         for (index = size_zero_node;
+              *initp && (!max_index || !tree_int_cst_lt (max_index, index));
+              index = size_binop (PLUS_EXPR, index, size_one_node))
+           {
+             tree element_init;
+
+             element_init = reshape_init (TREE_TYPE (type), initp);
+             TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
+             CONSTRUCTOR_ELTS (new_init) = element_init;
+             if (TREE_PURPOSE (element_init))
+               index = TREE_PURPOSE (element_init);
+           }
+       }
+      else
+       abort ();
+
+      /* The initializers were placed in reverse order in the
+        CONSTRUCTOR.  */
+      CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));
+
+      if (TREE_CODE (old_init) == TREE_LIST)
+       new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
+    }
+
+  /* If this was a brace-enclosed initializer and all of the
+     initializers were not used up, there is a problem.  */
+  if (brace_enclosed_p && *initp)
+    error ("too many initializers for `%T'", type);
+
+  return new_init;
+}
+
 /* Verify INIT (the initializer for DECL), and record the
-   initialization in DECL_INITIAL, if appropriate.  Returns a new
-   value for INIT.  */
+   initialization in DECL_INITIAL, if appropriate.  
+
+   If the return value is non-NULL, it is an expression that must be
+   evaluated dynamically to initialize DECL.  */
 
 static tree
-check_initializer (decl, init)
-     tree decl;
-     tree init;
+check_initializer (tree decl, tree init, int flags)
 {
   tree type = TREE_TYPE (decl);
 
@@ -7790,22 +7999,49 @@ check_initializer (decl, init)
     init = grok_reference_init (decl, type, init);
   else if (init)
     {
+      if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+       init = reshape_init (type, &init);
+
+      /* If DECL has an array type without a specific bound, deduce the
+        array size from the initializer.  */
+      maybe_deduce_size_from_array_init (decl, init);
+      type = TREE_TYPE (decl);
+      if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+       TREE_TYPE (init) = type;
+
       if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
        {
          if (TREE_CODE (type) == ARRAY_TYPE)
-           init = digest_init (type, init, (tree *) 0);
+           goto initialize_aggr;
          else if (TREE_CODE (init) == CONSTRUCTOR
                   && TREE_HAS_CONSTRUCTOR (init))
            {
              if (TYPE_NON_AGGREGATE_CLASS (type))
                {
                  error ("`%D' must be initialized by constructor, not by `{...}'",
-                           decl);
+                        decl);
                  init = error_mark_node;
                }
              else
                goto dont_use_constructor;
            }
+         else
+           {
+             int saved_stmts_are_full_exprs_p;
+
+           initialize_aggr:
+             saved_stmts_are_full_exprs_p = 0;
+             if (building_stmt_tree ())
+               {
+                 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
+                 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+               }
+             init = build_aggr_init (decl, init, flags);
+             if (building_stmt_tree ())
+               current_stmt_tree ()->stmts_are_full_exprs_p =
+                 saved_stmts_are_full_exprs_p;
+             return init;
+           }
        }
       else
        {
@@ -7816,25 +8052,26 @@ check_initializer (decl, init)
     }
   else if (DECL_EXTERNAL (decl))
     ;
-  else if (TYPE_P (type)
-          && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
+  else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
+    goto initialize_aggr;
+  else if (IS_AGGR_TYPE (type))
     {
       tree core_type = strip_array_types (type);
 
-      if (! TYPE_NEEDS_CONSTRUCTING (core_type))
-       {
-         if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
-           error ("structure `%D' with uninitialized const members", decl);
-         if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
-           error ("structure `%D' with uninitialized reference members",
-                     decl);
-       }
+      if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
+       error ("structure `%D' with uninitialized const members", decl);
+      if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
+       error ("structure `%D' with uninitialized reference members",
+              decl);
 
       check_for_uninitialized_const_var (decl);
     }
   else
     check_for_uninitialized_const_var (decl);
 
+  if (init && init != error_mark_node)
+    init = build (INIT_EXPR, type, decl, init);
+
   return init;
 }
 
@@ -7968,35 +8205,25 @@ maybe_inject_for_scope_var (decl)
 
 /* Generate code to initialize DECL (a local variable).  */
 
-void
-initialize_local_var (decl, init, flags)
+static void
+initialize_local_var (decl, init)
      tree decl;
      tree init;
-     int flags;
 {
   tree type = TREE_TYPE (decl);
 
-  /* If the type is bogus, don't bother initializing the variable.  */
-  if (type == error_mark_node)
-    return;
+  my_friendly_assert (TREE_CODE (decl) == VAR_DECL
+                     || TREE_CODE (decl) == RESULT_DECL, 
+                     20021010);
+  my_friendly_assert (!TREE_STATIC (decl), 20021010);
 
-  if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
+  if (DECL_SIZE (decl) == NULL_TREE)
     {
       /* If we used it already as memory, it must stay in memory.  */
       DECL_INITIAL (decl) = NULL_TREE;
       TREE_ADDRESSABLE (decl) = TREE_USED (decl);
     }
 
-  /* Local statics are handled differently from ordinary automatic
-     variables.  */
-  if (TREE_STATIC (decl))
-    {
-      if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
-         || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
-       expand_static_init (decl, init);
-      return;
-    }
-
   if (DECL_SIZE (decl) && type != error_mark_node)
     {
       int already_used;
@@ -8004,14 +8231,15 @@ initialize_local_var (decl, init, flags)
       /* Compute and store the initial value.  */
       already_used = TREE_USED (decl) || TREE_USED (type);
 
-      if (init || TYPE_NEEDS_CONSTRUCTING (type))
+      /* Perform the initialization.  */
+      if (init)
        {
          int saved_stmts_are_full_exprs_p;
 
          my_friendly_assert (building_stmt_tree (), 20000906);
          saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
          current_stmt_tree ()->stmts_are_full_exprs_p = 1;
-         finish_expr_stmt (build_aggr_init (decl, init, flags));
+         finish_expr_stmt (init);
          current_stmt_tree ()->stmts_are_full_exprs_p =
            saved_stmts_are_full_exprs_p;
        }
@@ -8030,39 +8258,19 @@ initialize_local_var (decl, init, flags)
       else if (already_used)
        TREE_USED (decl) = 1;
     }
-}
-
-/* Generate code to destroy DECL (a local variable).  */
-
-static void
-destroy_local_var (decl)
-     tree decl;
-{
-  tree type = TREE_TYPE (decl);
-  tree cleanup;
-
-  /* Only variables get cleaned up.  */
-  if (TREE_CODE (decl) != VAR_DECL)
-    return;
-
-  /* And only things with destructors need cleaning up.  */
-  if (type == error_mark_node
-      || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
-    return;
 
-  if (TREE_CODE (decl) == VAR_DECL &&
-      (DECL_EXTERNAL (decl) || TREE_STATIC (decl)))
-    /* We don't clean up things that aren't defined in this
-       translation unit, or that need a static cleanup.  The latter
-       are handled by finish_file.  */
-    return;
-
-  /* Compute the cleanup.  */
-  cleanup = cxx_maybe_build_cleanup (decl);
+  /* Generate a cleanup, if necessary.  */
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+    {
+      tree cleanup;
 
-  /* Record the cleanup required for this declaration.  */
-  if (DECL_SIZE (decl) && cleanup)
-    finish_decl_cleanup (decl, cleanup);
+      /* Compute the cleanup.  */
+      cleanup = cxx_maybe_build_cleanup (decl);
+      
+      /* Record the cleanup required for this declaration.  */
+      if (DECL_SIZE (decl) && cleanup)
+       finish_decl_cleanup (decl, cleanup);
+    }
 }
 
 /* Finish processing of a declaration;
@@ -8193,7 +8401,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
       make_decl_rtl (decl, asmspec);
     }
   else if (TREE_CODE (decl) == RESULT_DECL)
-    init = check_initializer (decl, init);
+    init = check_initializer (decl, init, flags);
   else if (TREE_CODE (decl) == VAR_DECL)
     {
       /* Only PODs can have thread-local storage.  Other types may require
@@ -8205,12 +8413,12 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
         already initialized DECL.  */
       if (!DECL_INITIALIZED_P (decl)
          /* If !DECL_EXTERNAL then DECL is being defined.  In the
-            case of a static data memberm initialized inside the
+            case of a static data member initialized inside the
             class-specifier, there can be an initializer even if DECL
             is *not* defined.  */
          && (!DECL_EXTERNAL (decl) || init))
        {
-         init = check_initializer (decl, init);
+         init = check_initializer (decl, init, flags);
          /* Thread-local storage cannot be dynamically initialized.  */
          if (DECL_THREAD_LOCAL (decl) && init)
            {
@@ -8218,15 +8426,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
                     "initialized", decl);
              init = NULL_TREE;
            }
-         /* If DECL has an array type without a specific bound, deduce the
-            array size from the initializer.  Note that this must be done
-            after check_initializer is called because of cases like this:
-            
-              struct S { int a; int b; };
-              struct S a[] = { 1, 2 };
-        
-            which creates a one-element array, not a two-element array.  */
-         maybe_deduce_size_from_array_init (decl, init);
          /* Handle:
             
             [dcl.init]
@@ -8283,7 +8482,9 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
       else
        abstract_virtuals_error (decl, strip_array_types (type));
 
-      if (TREE_CODE (decl) == FUNCTION_DECL)
+      if (TREE_CODE (decl) == FUNCTION_DECL 
+         || TREE_TYPE (decl) == error_mark_node)
+       /* No initialization required.  */
        ;
       else if (DECL_EXTERNAL (decl)
               && ! (DECL_LANG_SPECIFIC (decl)
@@ -8292,35 +8493,25 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
          if (init)
            DECL_INITIAL (decl) = init;
        }
-      else if (TREE_CODE (CP_DECL_CONTEXT (decl)) == FUNCTION_DECL)
+      else
        {
-         /* This is a local declaration.  */
-         if (doing_semantic_analysis_p ())
-           maybe_inject_for_scope_var (decl);
-         /* Initialize the local variable.  But, if we're building a
-            statement-tree, we'll do the initialization when we
-            expand the tree.  */
-         if (processing_template_decl)
+         /* A variable definition.  */
+         if (DECL_FUNCTION_SCOPE_P (decl))
            {
-             if (init || DECL_INITIAL (decl) == error_mark_node)
-               DECL_INITIAL (decl) = init;
-           }
-         else
-           {
-             /* If we're not building RTL, then we need to do so
-                now.  */
-             my_friendly_assert (building_stmt_tree (), 20000906);
-             /* Initialize the variable.  */
-             initialize_local_var (decl, init, flags);
-             /* Clean up the variable.  */
-             destroy_local_var (decl);
+             /* This is a local declaration.  */
+             if (doing_semantic_analysis_p ())
+               maybe_inject_for_scope_var (decl);
+             /* Initialize the local variable.  */
+             if (processing_template_decl)
+               {
+                 if (init || DECL_INITIAL (decl) == error_mark_node)
+                   DECL_INITIAL (decl) = init;
+               }
+             else if (!TREE_STATIC (decl))
+               initialize_local_var (decl, init);
            }
-       }
-      else if (TREE_STATIC (decl) && type != error_mark_node)
-       {
-         /* Cleanups for static variables are handled by `finish_file'.  */
-         if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
-             || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+
+         if (TREE_STATIC (decl))
            expand_static_init (decl, init);
        }
     finish_end0:
@@ -8600,12 +8791,27 @@ register_dtor_fn (decl)
   finish_expr_stmt (build_function_call (get_atexit_node (), args));
 }
 
-void
+/* DECL is a VAR_DECL with static storage duration.  INIT, if present,
+   is its initializer.  Generate code to handle the construction
+   and destruction of DECL.  */
+
+static void
 expand_static_init (decl, init)
      tree decl;
      tree init;
 {
-  tree oldstatic = value_member (decl, static_aggregates);
+  tree oldstatic;
+
+  my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
+  my_friendly_assert (TREE_STATIC (decl), 20021010);
+
+  /* Some variables require no initialization.  */
+  if (!init 
+      && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+      && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+    return;
+
+  oldstatic = value_member (decl, static_aggregates);
 
   if (oldstatic)
     {
@@ -8655,15 +8861,7 @@ expand_static_init (decl, init)
       then_clause = begin_compound_stmt (/*has_no_scope=*/0);
 
       /* Do the initialization itself.  */
-      if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
-         || (init && TREE_CODE (init) == TREE_LIST))
-       assignment = build_aggr_init (decl, init, 0);
-      else if (init)
-       /* The initialization we're doing here is just a bitwise
-          copy.  */
-       assignment = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
-      else
-       assignment = NULL_TREE;
+      assignment = init ? init : NULL_TREE;
 
       /* Once the assignment is complete, set TEMP to 1.  Since the
         construction of the static object is complete at this point,
index cab1c01..afa65a0 100644 (file)
@@ -2508,34 +2508,24 @@ finish_static_initialization_or_destruction (guard_if_stmt)
   DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
 }
 
-/* Generate code to do the static initialization of DECL.  The
-   initialization is INIT.  If DECL may be initialized more than once
-   in different object files, GUARD is the guard variable to 
-   check.  PRIORITY is the priority for the initialization.  */
+/* Generate code to do the initialization of DECL, a VAR_DECL with
+   static storage duration.  The initialization is INIT.  */
 
 static void
 do_static_initialization (decl, init)
      tree decl;
      tree init;
 {
-  tree expr;
   tree guard_if_stmt;
 
   /* Set up for the initialization.  */
   guard_if_stmt
     = start_static_initialization_or_destruction (decl,
                                                  /*initp=*/1);
-  
-  /* Do the initialization itself.  */
-  if (IS_AGGR_TYPE (TREE_TYPE (decl))
-      || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
-    expr = build_aggr_init (decl, init, 0);
-  else
-    {
-      expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
-      TREE_SIDE_EFFECTS (expr) = 1;
-    }
-  finish_expr_stmt (expr);
+
+  /* Perform the initialization.  */
+  if (init)
+    finish_expr_stmt (init);
 
   /* If we're using __cxa_atexit, register a a function that calls the
      destructor for the object.  */
@@ -2567,7 +2557,7 @@ do_static_destruction (decl)
 
   /* Actually do the destruction.  */
   guard_if_stmt = start_static_initialization_or_destruction (decl,
-                                                              /*initp=*/0);
+                                                             /*initp=*/0);
   finish_expr_stmt (build_cleanup (decl));
   finish_static_initialization_or_destruction (guard_if_stmt);
 }
index 156822f..051548e 100644 (file)
@@ -1041,8 +1041,6 @@ expand_member_init (tree name, tree init)
    The virtual function table pointer cannot be set up here, because
    we do not really know its type.
 
-   Virtual baseclass pointers are also set up here.
-
    This never calls operator=().
 
    When initializing, nothing is CONST.
@@ -1144,10 +1142,8 @@ build_init (decl, init, flags)
       || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
     expr = build_aggr_init (decl, init, flags);
   else
-    {
-      expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
-      TREE_SIDE_EFFECTS (expr) = 1;
-    }
+    expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
+
   return expr;
 }
 
@@ -1184,9 +1180,17 @@ expand_default_init (binfo, true_exp, exp, init, flags)
           have already built up the constructor call so we could wrap it
           in an exception region.  */;
       else if (TREE_CODE (init) == CONSTRUCTOR)
-       /* A brace-enclosed initializer has whatever type is
-          required.  There's no need to convert it.  */
-       ;
+       {
+         if (!TYPE_HAS_CONSTRUCTOR (type))
+           /* A brace-enclosed initializer has whatever type is
+              required.  There's no need to convert it.  */
+           ;
+         else
+           init = ocp_convert (type, 
+                               TREE_VALUE (CONSTRUCTOR_ELTS (init)),
+                               CONV_IMPLICIT | CONV_FORCE_TEMP, 
+                               flags);
+       }
       else
        init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
 
@@ -1259,6 +1263,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
   tree type = TREE_TYPE (exp);
 
   my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);
+  my_friendly_assert (building_stmt_tree (), 20021010);
 
   /* Use a function returning the desired type to initialize EXP for us.
      If the function is a constructor, and its first argument is
@@ -1273,12 +1278,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
       /* If store_init_value returns NULL_TREE, the INIT has been
         record in the DECL_INITIAL for EXP.  That means there's
         nothing more we have to do.  */
-      if (!store_init_value (exp, init))
-       {
-         if (!building_stmt_tree ())
-           expand_decl_init (exp);
-       }
-      else
+      if (store_init_value (exp, init))
        finish_expr_stmt (build (INIT_EXPR, type, exp, init));
       return;
     }
@@ -2725,10 +2725,6 @@ build_vec_init (base, init, from_array)
   if (maxindex == error_mark_node)
     return error_mark_node;
 
-  /* For g++.ext/arrnew.C.  */
-  if (init && TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == NULL_TREE)
-    init = digest_init (atype, init, 0);
-      
   if (init
       && (from_array == 2
          ? (!CLASS_TYPE_P (type) || !TYPE_HAS_COMPLEX_ASSIGN_REF (type))
@@ -2745,7 +2741,6 @@ build_vec_init (base, init, from_array)
         store_constructor will handle the semantics for us.  */
 
       stmt_expr = build (INIT_EXPR, atype, base, init);
-      TREE_SIDE_EFFECTS (stmt_expr) = 1;
       return stmt_expr;
     }
 
index b404e6a..104c4a7 100644 (file)
@@ -1351,21 +1351,12 @@ new_initializer:
                  error ("`%T' is not a valid expression", $2.t);
                  $$ = error_mark_node;
                }
-       /* GNU extension so people can use initializer lists.  Note that
-          this alters the meaning of `new int = 1', which was previously
-          syntactically valid but semantically invalid.
-           This feature is now deprecated and will be removed in a future
-           release.  */
        | '=' init
                {
-                 if (pedantic)
-                   pedwarn ("ISO C++ forbids initialization of new expression with `='");
-                 cp_deprecated ("new initializer lists extension");
-                 if (TREE_CODE ($2) != TREE_LIST
-                     && TREE_CODE ($2) != CONSTRUCTOR)
-                   $$ = build_tree_list (NULL_TREE, $2);
-                 else
-                   $$ = $2;
+                 /* This was previously allowed as an extension, but
+                    was removed in G++ 3.3.  */
+                 error ("initialization of new expression with `='");
+                 $$ = error_mark_node;
                }
        ;
 
index 1d692fc..d6ddf13 100644 (file)
@@ -1096,10 +1096,12 @@ get_pseudo_ti_init (type, var_desc, non_public_p)
               base_init = tree_cons (NULL_TREE, offset, base_init);
               base_init = tree_cons (NULL_TREE, tinfo, base_init);
               base_init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_init);
+             TREE_HAS_CONSTRUCTOR (base_init) = 1;
               base_inits = tree_cons (NULL_TREE, base_init, base_inits);
             }
          base_inits = build (CONSTRUCTOR,
                              NULL_TREE, NULL_TREE, base_inits);
+         TREE_HAS_CONSTRUCTOR (base_inits) = 1;
          base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
          /* Prepend the number of bases.  */
          base_inits = tree_cons (NULL_TREE,
@@ -1163,7 +1165,7 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
   /* Create the pseudo type.  */
   pseudo_type = make_aggr_type (RECORD_TYPE);
   finish_builtin_type (pseudo_type, pseudo_name, fields, ix, ptr_type_node);
-  TYPE_HAS_CONSTRUCTOR (pseudo_type) = 1;
+  CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
 
   result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
   TINFO_REAL_NAME (result) = get_identifier (real_name);
index fa7f705..cc712b9 100644 (file)
@@ -367,15 +367,8 @@ store_init_value (decl, init)
 
   /* End of special C++ code.  */
 
-  /* We might have already run this bracketed initializer through
-     digest_init.  Don't do so again.  */
-  if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)
-      && TREE_TYPE (init)
-      && TYPE_MAIN_VARIANT (TREE_TYPE (init)) == TYPE_MAIN_VARIANT (type))
-    value = init;
-  else
-    /* Digest the specified initializer into an expression.  */
-    value = digest_init (type, init, (tree *) 0);
+  /* Digest the specified initializer into an expression.  */
+  value = digest_init (type, init, (tree *) 0);
 
   /* Store the expression if valid; else report error.  */
 
@@ -439,8 +432,7 @@ digest_init (type, init, tail)
   enum tree_code code = TREE_CODE (type);
   tree element = NULL_TREE;
   tree old_tail_contents = NULL_TREE;
-  /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
-     tree node which has no TREE_TYPE.  */
+  /* Nonzero if INIT is a braced grouping.  */
   int raw_constructor;
 
   /* By default, assume we use one element from a list.
@@ -471,10 +463,8 @@ digest_init (type, init, tail)
   if (TREE_CODE (init) == NON_LVALUE_EXPR)
     init = TREE_OPERAND (init, 0);
 
-  if (TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == type)
-    return init;
-
-  raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
+  raw_constructor = (TREE_CODE (init) == CONSTRUCTOR 
+                    && TREE_HAS_CONSTRUCTOR (init));
 
   if (raw_constructor
       && CONSTRUCTOR_ELTS (init) != 0
index d04c554..4fbef9b 100644 (file)
@@ -1,3 +1,13 @@
+2002-10-11  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/init/array1.C: Remove invalid braces.
+       * g++.dg/init/brace1.C: New test.
+       * g++.dg/init/copy2.C: Likewise.
+       * g++.dg/init/copy3.C: Likewise.
+       * g++.old-deja/g++.ext/arrnew.C: Change WARNING to ERROR.
+       * g++.old-deja/g++.mike/p9129.C: Add ERROR on invalid use of
+       braces.
+       
 2002-10-11  Neil Booth  <neil@daikokuya.co.uk>
 
        * gcc.dg/cpp/assembler.S: Don't use -ansi.
index 8618e1e..5847247 100644 (file)
@@ -6,15 +6,15 @@
 typedef int iArr[];
 
 const iArr array4={
-  {1},{2},{3},{4}
+  1, 2, 3, 4
 };
 
 const iArr array3={
-  {1},{2},{3}
+  1, 2, 3
 };
 
 const iArr array5={
-  {1},{2},{3},{4},{5}
+  1, 2, 3, 4, 5
 };
 
 int main()
diff --git a/gcc/testsuite/g++.dg/init/brace1.C b/gcc/testsuite/g++.dg/init/brace1.C
new file mode 100644 (file)
index 0000000..a819fa2
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-do compile }
+
+int i[4] = { { 3 } }; // { dg-error "brace" }
+
diff --git a/gcc/testsuite/g++.dg/init/copy2.C b/gcc/testsuite/g++.dg/init/copy2.C
new file mode 100644 (file)
index 0000000..9a662d4
--- /dev/null
@@ -0,0 +1,5 @@
+// { dg-do compile }
+
+struct S { S (); };
+
+volatile S s[1] = { S () };
diff --git a/gcc/testsuite/g++.dg/init/copy3.C b/gcc/testsuite/g++.dg/init/copy3.C
new file mode 100644 (file)
index 0000000..fa6a6ea
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-do run }
+// { dg-options "-fno-elide-constructors" }
+
+int copies;
+
+struct S { 
+  S () {}
+  S (const S&) { ++copies; }
+};
+
+S s[1] = { S () };
+
+int main () {
+  if (copies != 1)
+    return 1;
+}
index 0ecb877..53030e0 100644 (file)
@@ -3,5 +3,5 @@
 // Special g++ Options:
 
 int *f(){
-  return new int[1] = { 1 };   // WARNING - deprecated
+  return new int[1] = { 1 };   // ERROR - removed
 }
index d66dab5..a986104 100644 (file)
@@ -7,6 +7,6 @@ public:
   int DoSomething();
 };
 
-int (Foo::*pA)() = { &Foo::DoSomething };      
+int (Foo::*pA)() = { &Foo::DoSomething };      // ERROR - 
 int (Foo::*X[1])(int) = { { &Foo::DoSomething } };                 // ERROR - 
 int (Foo::*Y[])(int) = { { &Foo::DoSomething, &Foo::DoSomething, 0 } }; // ERROR -