]> gcc.gnu.org Git - gcc.git/commitdiff
cp-tree.h (strip_array_types): New function.
authorMark Mitchell <mark@codesourcery.com>
Sun, 29 Aug 1999 01:39:04 +0000 (01:39 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 29 Aug 1999 01:39:04 +0000 (01:39 +0000)
* cp-tree.h (strip_array_types): New function.
* decl.c (maybe_deduce_size_from_array_init): New function, split
out from cp_finish_decl.
(layout_var_decl): Likewise.
(maybe_commonize_var): Likewise.
(maybe_inject_for_scope_var): Likewise.
(initialize_local_var): Likewise.
(build_cleanup_on_safe_obstack): Likewise.
(check_initializer): Likewise.
(make_rtl_for_nonlocal_decl): Likewise.
(cp_finish_decl): Use them.
* typeck.c (strip_array_types): New function.

From-SVN: r28956

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/typeck.c

index 509251e75b47864c79d9c8763d0942759e7343c3..be4bbdbabc059aa7403232534e570db777741198 100644 (file)
@@ -4,6 +4,19 @@
 
 1999-08-28  Mark Mitchell  <mark@codesourcery.com>
 
+       * cp-tree.h (strip_array_types): New function.
+       * decl.c (maybe_deduce_size_from_array_init): New function, split
+       out from cp_finish_decl.
+       (layout_var_decl): Likewise.
+       (maybe_commonize_var): Likewise.
+       (maybe_inject_for_scope_var): Likewise.
+       (initialize_local_var): Likewise.
+       (build_cleanup_on_safe_obstack): Likewise.
+       (check_initializer): Likewise.
+       (make_rtl_for_nonlocal_decl): Likewise.
+       (cp_finish_decl): Use them.
+       * typeck.c (strip_array_types): New function.
+       
        * cp-tree.def (LABEL_STMT): New tree node.
        * cp-tree.h (LABEL_STMT_LABEL): New macro.
        (shadow_label): Remove.
index 5c32998fc9ade67d4813134c2ee52cf4a7dfd623..901d25298ff36c0cbab58d5137b316862e519c11 100644 (file)
@@ -3574,6 +3574,7 @@ extern tree c_expand_start_case                   PROTO((tree));
 extern int comp_ptr_ttypes                     PROTO((tree, tree));
 extern int ptr_reasonably_similar              PROTO((tree, tree));
 extern tree build_ptrmemfunc                   PROTO((tree, tree, int));
+extern tree strip_array_types                   PROTO((tree));
 extern int cp_type_quals                        PROTO((tree));
 extern int cp_has_mutable_p                     PROTO((tree));
 extern int at_least_as_qualified_p              PROTO((tree, tree));
index 350eb8e5a0e51a9709742bbbb090af1110042c21..8ca2f57a7ecc77592fe4e14bc7b377ed1847affd 100644 (file)
@@ -193,6 +193,14 @@ static void add_decl_to_level PROTO((tree, struct binding_level *));
 static tree make_label_decl PROTO((tree, int));
 static void pop_label PROTO((tree));
 static void pop_labels PROTO((tree));
+static void maybe_deduce_size_from_array_init PROTO((tree, tree));
+static void layout_var_decl PROTO((tree, tree *));
+static void maybe_commonize_var PROTO((tree));
+static void maybe_inject_for_scope_var PROTO((tree));
+static void initialize_local_var PROTO((tree, tree, tree, int));
+static tree build_cleanup_on_safe_obstack PROTO((tree));
+static void check_initializer PROTO((tree, tree *));
+static void make_rtl_for_nonlocal_decl PROTO((tree, tree, const char *));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PROTO((void));
@@ -7315,6 +7323,207 @@ obscure_complex_init (decl, init)
   return init;
 }
 
+/* When parsing `int a[] = {1, 2};' we don't know the size of the
+   array until we finish parsing the initializer.  If that's the
+   situation we're in, update DECL accordingly.  */
+
+static void
+maybe_deduce_size_from_array_init (decl, init)
+     tree decl;
+     tree init;
+{
+  tree type = TREE_TYPE (decl);
+
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_DOMAIN (type) == NULL_TREE
+      && TREE_CODE (decl) != TYPE_DECL)
+    {
+      int do_default
+       = (TREE_STATIC (decl)
+          /* Even if pedantic, an external linkage array
+             may have incomplete type at first.  */
+          ? pedantic && ! DECL_EXTERNAL (decl)
+          : !DECL_EXTERNAL (decl));
+      tree initializer = init ? init : DECL_INITIAL (decl);
+      int failure = complete_array_type (type, initializer, do_default);
+
+      if (failure == 1)
+       cp_error ("initializer fails to determine size of `%D'", decl);
+
+      if (failure == 2)
+       {
+         if (do_default)
+           cp_error ("array size missing in `%D'", decl);
+         /* If a `static' var's size isn't known, make it extern as
+            well as static, so it does not get allocated.  If it's not
+            `static', then don't mark it extern; finish_incomplete_decl
+            will give it a default size and it will get allocated.  */
+         else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
+           DECL_EXTERNAL (decl) = 1;
+       }
+
+      if (pedantic && TYPE_DOMAIN (type) != NULL_TREE
+         && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+                             integer_zero_node))
+       cp_error ("zero-size array `%D'", decl);
+
+      layout_decl (decl, 0);
+    }
+}
+
+/* Set DECL_SIZE, DECL_ALIGN, etc. for DECL (a VAR_DECL), and issue
+   any appropriate error messages regarding the layout.  INITP is a
+   pointer to the initializer for DECL; the initializer may be
+   modified by this function.  */
+
+static void
+layout_var_decl (decl, initp)
+     tree decl;
+     tree *initp;
+{
+  tree ttype = target_type (TREE_TYPE (decl));
+
+  if (DECL_SIZE (decl) == NULL_TREE
+      && TYPE_SIZE (complete_type (TREE_TYPE (decl))) != NULL_TREE)
+    layout_decl (decl, 0);
+
+  if (TREE_STATIC (decl) && DECL_SIZE (decl) == NULL_TREE)
+    {
+      /* A static variable with an incomplete type:
+        that is an error if it is initialized.
+        Otherwise, let it through, but if it is not `extern'
+        then it may cause an error message later.  */
+      if (DECL_INITIAL (decl) != NULL_TREE)
+       cp_error ("storage size of `%D' isn't known", decl);
+      *initp = NULL_TREE;
+    }
+  else if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
+    {
+      /* An automatic variable with an incomplete type: that is an error.
+        Don't talk about array types here, since we took care of that
+        message in grokdeclarator.  */
+      cp_error ("storage size of `%D' isn't known", decl);
+      TREE_TYPE (decl) = error_mark_node;
+    }
+  else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
+    /* Let debugger know it should output info for this type.  */
+    note_debug_info_needed (ttype);
+
+  if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl))
+    note_debug_info_needed (DECL_CONTEXT (decl));
+
+  if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
+      && DECL_SIZE (decl) != NULL_TREE
+      && ! TREE_CONSTANT (DECL_SIZE (decl)))
+    {
+      if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
+       constant_expression_warning (DECL_SIZE (decl));
+      else
+       cp_error ("storage size of `%D' isn't constant", decl);
+    }
+}
+
+/* Return a cleanup for DECL, created on whatever obstack is
+   appropriate.  */
+
+static tree
+build_cleanup_on_safe_obstack (decl)
+     tree decl;
+{
+  tree cleanup;
+  tree type;
+  int need_pop;
+
+  type = TREE_TYPE (decl);
+
+  /* Only variables get cleaned up.  */
+  if (TREE_CODE (decl) != VAR_DECL)
+    return NULL_TREE;
+  
+  /* And only things with destructors need cleaning up.  */
+  if (!TYPE_NEEDS_DESTRUCTOR (type))
+    return NULL_TREE;
+
+  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 NULL_TREE;
+  
+  /* Switch to an obstack that will live until the point where the
+     cleanup code is actually expanded.  */
+  need_pop = suspend_momentary ();
+
+  /* Compute the cleanup.  */
+  cleanup = maybe_build_cleanup (decl);
+
+  /* Pop back to the obstack we were on before.  */
+  resume_momentary (need_pop);
+  
+  return cleanup;
+}
+
+/* If a local static variable is declared in an inline function, or if
+   we have a weak definition, we must endeavor to create only one
+   instance of the variable at link-time.  */
+
+static void
+maybe_commonize_var (decl)
+     tree decl;
+{
+  /* Static data in a function with comdat linkage also has comdat
+     linkage.  */
+  if (TREE_STATIC (decl)
+      /* Don't mess with __FUNCTION__.  */
+      && ! TREE_ASM_WRITTEN (decl)
+      && current_function_decl
+      && DECL_CONTEXT (decl) == current_function_decl
+      && (DECL_THIS_INLINE (current_function_decl)
+         || DECL_TEMPLATE_INSTANTIATION (current_function_decl))
+      && TREE_PUBLIC (current_function_decl))
+    {
+      /* Rather than try to get this right with inlining, we suppress
+        inlining of such functions.  */
+      current_function_cannot_inline
+       = "function with static variable cannot be inline";
+
+      /* If flag_weak, we don't need to mess with this, as we can just
+        make the function weak, and let it refer to its unique local
+        copy.  This works because we don't allow the function to be
+        inlined.  */
+      if (! flag_weak)
+       {
+         if (DECL_INTERFACE_KNOWN (current_function_decl))
+           {
+             TREE_PUBLIC (decl) = 1;
+             DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
+           }
+         else if (DECL_INITIAL (decl) == NULL_TREE
+                  || DECL_INITIAL (decl) == error_mark_node)
+           {
+             TREE_PUBLIC (decl) = 1;
+             DECL_COMMON (decl) = 1;
+           }
+         /* else we lose. We can only do this if we can use common,
+            which we can't if it has been initialized.  */
+
+         if (TREE_PUBLIC (decl))
+           DECL_ASSEMBLER_NAME (decl)
+             = build_static_name (current_function_decl, DECL_NAME (decl));
+         else if (! DECL_ARTIFICIAL (decl))
+           {
+             cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
+             cp_warning_at ("  you can work around this by removing the initializer", decl);
+           }
+       }
+    }
+  else if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
+    /* Set it up again; we might have set DECL_INITIAL since the last
+       time.  */
+    comdat_linkage (decl);
+}
+
 /* Issue an error message if DECL is an uninitialized const variable.  */
 
 static void
@@ -7334,6 +7543,327 @@ check_for_uninitialized_const_var (decl)
     cp_error ("uninitialized const `%D'", decl);
 }
 
+/* Verify INITP (the initializer for DECL), and record the
+   initialization in DECL_INITIAL, if appropriate.  The initializer
+   may be modified by this function.  */
+
+static void
+check_initializer (decl, initp)
+     tree decl;
+     tree *initp;
+{
+  tree init;
+  tree type;
+
+  if (TREE_CODE (decl) == FIELD_DECL)
+    return;
+
+  type = TREE_TYPE (decl);
+  init = *initp;
+
+  /* If `start_decl' didn't like having an initialization, ignore it now.  */
+  if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
+    init = NULL_TREE;
+  else if (DECL_EXTERNAL (decl))
+    ;
+  else if (TREE_CODE (type) == REFERENCE_TYPE)
+    {
+      if (TREE_STATIC (decl))
+       make_decl_rtl (decl, NULL_PTR, toplevel_bindings_p ());
+      grok_reference_init (decl, type, init);
+      init = NULL_TREE;
+    }
+
+  /* Check for certain invalid initializations.  */
+  if (init)
+    {
+      if (TYPE_SIZE (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
+       {
+         cp_error ("variable-sized object `%D' may not be initialized", decl);
+         init = NULL_TREE;
+       }
+      if (TREE_CODE (type) == ARRAY_TYPE
+         && !TYPE_SIZE (complete_type (TREE_TYPE (type))))
+       {
+         cp_error ("elements of array `%#D' have incomplete type", decl);
+         init = NULL_TREE;
+       }
+    }
+
+  if (TREE_CODE (decl) == CONST_DECL)
+    {
+      my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148);
+
+      DECL_INITIAL (decl) = init;
+
+      /* This will keep us from needing to worry about our obstacks.  */
+      my_friendly_assert (init != NULL_TREE, 149);
+      init = NULL_TREE;
+    }
+  else if (init)
+    {
+      if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
+       {
+         if (TREE_CODE (type) == ARRAY_TYPE)
+           init = digest_init (type, init, (tree *) 0);
+         else if (TREE_CODE (init) == CONSTRUCTOR
+                  && TREE_HAS_CONSTRUCTOR (init))
+           {
+             if (TYPE_NON_AGGREGATE_CLASS (type))
+               {
+                 cp_error ("`%D' must be initialized by constructor, not by `{...}'",
+                           decl);
+                 init = error_mark_node;
+               }
+             else
+               goto dont_use_constructor;
+           }
+       }
+      else
+       {
+       dont_use_constructor:
+         if (TREE_CODE (init) != TREE_VEC)
+           init = store_init_value (decl, init);
+       }
+
+      if (init)
+       /* We must hide the initializer so that expand_decl
+          won't try to do something it does not understand.  */
+       init = obscure_complex_init (decl, init);
+    }
+  else if (DECL_EXTERNAL (decl))
+    ;
+  else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
+          && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
+    {
+      tree core_type = strip_array_types (type);
+
+      if (! TYPE_NEEDS_CONSTRUCTING (core_type))
+       {
+         if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
+           cp_error ("structure `%D' with uninitialized const members", decl);
+         if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
+           cp_error ("structure `%D' with uninitialized reference members",
+                     decl);
+       }
+
+      check_for_uninitialized_const_var (decl);
+
+      if (TYPE_SIZE (type) != NULL_TREE
+         && TYPE_NEEDS_CONSTRUCTING (type))
+       init = obscure_complex_init (decl, NULL_TREE);
+
+    }
+  else
+    check_for_uninitialized_const_var (decl);
+  
+  /* Store the modified initializer for our caller.  */
+  *initp = init;
+}
+
+/* If DECL is not a local variable, give it RTL.  */
+
+static void
+make_rtl_for_nonlocal_decl (decl, init, asmspec)
+     tree decl;
+     tree init;
+     const char *asmspec;
+{
+  int was_temp;
+  int toplev;
+  tree type;
+
+  type = TREE_TYPE (decl);
+  toplev = toplevel_bindings_p ();
+  was_temp = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
+             && allocation_temporary_p ());
+  if (was_temp)
+    end_temporary_allocation ();
+
+  if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
+    make_decl_rtl (decl, NULL_PTR, toplev);
+  else if (TREE_CODE (decl) == VAR_DECL
+          && TREE_READONLY (decl)
+          && DECL_INITIAL (decl) != NULL_TREE
+          && DECL_INITIAL (decl) != error_mark_node
+          && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
+    {
+      DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
+
+      if (asmspec)
+       DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
+
+      if (! toplev
+         && TREE_STATIC (decl)
+         && ! TREE_SIDE_EFFECTS (decl)
+         && ! TREE_PUBLIC (decl)
+         && ! DECL_EXTERNAL (decl)
+         && ! TYPE_NEEDS_DESTRUCTOR (type)
+         && DECL_MODE (decl) != BLKmode)
+       {
+         /* If this variable is really a constant, then fill its DECL_RTL
+            slot with something which won't take up storage.
+            If something later should take its address, we can always give
+            it legitimate RTL at that time.  */
+         DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
+         store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0);
+         TREE_ASM_WRITTEN (decl) = 1;
+       }
+      else if (toplev && ! TREE_PUBLIC (decl))
+       {
+         /* If this is a static const, change its apparent linkage
+            if it belongs to a #pragma interface.  */
+         if (!interface_unknown)
+           {
+             TREE_PUBLIC (decl) = 1;
+             DECL_EXTERNAL (decl) = interface_only;
+           }
+         make_decl_rtl (decl, asmspec, toplev);
+       }
+      else
+       rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+    }
+  else if (TREE_CODE (decl) == VAR_DECL
+          && DECL_LANG_SPECIFIC (decl)
+          && DECL_IN_AGGR_P (decl))
+    {
+      my_friendly_assert (TREE_STATIC (decl), 19990828);
+
+      if (init == NULL_TREE
+#ifdef DEFAULT_STATIC_DEFS
+         /* If this code is dead, then users must
+            explicitly declare static member variables
+            outside the class def'n as well.  */
+         && TYPE_NEEDS_CONSTRUCTING (type)
+#endif
+         )
+       {
+         DECL_EXTERNAL (decl) = 1;
+         make_decl_rtl (decl, asmspec, 1);
+       }
+      else
+       rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+    }
+  else
+    rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+
+  if (was_temp)
+    resume_temporary_allocation ();
+}
+
+/* The old ARM scoping rules injected variables declared in the
+   initialization statement of a for-statement into the surrounding
+   scope.  We support this usage, in order to be backward-compatible.
+   DECL is a just-declared VAR_DECL; if necessary inject its
+   declaration into the surrounding scope.  */
+
+static void
+maybe_inject_for_scope_var (decl)
+     tree decl;
+{
+  if (current_binding_level->is_for_scope)
+    {
+      struct binding_level *outer 
+       = current_binding_level->level_chain;
+
+      /* Check to see if the same name is already bound at the outer
+        level, either because it was directly declared, or because a
+        dead for-decl got preserved.  In either case, the code would
+        not have been valid under the ARM scope rules, so clear
+        is_for_scope for the current_binding_level.
+
+        Otherwise, we need to preserve the temp slot for decl to last
+        into the outer binding level.  */
+
+      tree outer_binding 
+       = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+             
+      if (outer_binding && BINDING_LEVEL (outer_binding) == outer
+         && (TREE_CODE (BINDING_VALUE (outer_binding)) 
+             == VAR_DECL)
+         && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
+       {
+         BINDING_VALUE (outer_binding)
+           = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
+         current_binding_level->is_for_scope = 0;
+       }
+      else if (DECL_IN_MEMORY_P (decl))
+       preserve_temp_slots (DECL_RTL (decl));
+    }
+}
+
+/* Generate code to initialized DECL (a local variable).  */
+
+static void
+initialize_local_var (decl, init, cleanup, flags)
+     tree decl;
+     tree init;
+     tree cleanup;
+     int flags;
+{
+  tree type;
+
+  type = TREE_TYPE (decl);
+  expand_start_target_temps ();
+
+  if (DECL_SIZE (decl) && type != error_mark_node)
+    {
+      int already_used;
+  
+      /* Compute and store the initial value.  */
+      expand_decl_init (decl);
+      already_used = TREE_USED (decl) || TREE_USED (type);
+
+      if (init || TYPE_NEEDS_CONSTRUCTING (type))
+       {
+         emit_line_note (DECL_SOURCE_FILE (decl),
+                         DECL_SOURCE_LINE (decl));
+         /* We call push_momentary here so that when
+            finish_expr_stmt clears the momentary obstack it
+            doesn't destory any momentary expressions we may
+            have lying around.  Although cp_finish_decl is
+            usually called at the end of a declaration
+            statement, it may also be called for a temporary
+            object in the middle of an expression.  */
+         push_momentary ();
+         finish_expr_stmt (build_aggr_init (decl, init, flags));
+         pop_momentary ();
+       }
+
+      /* Set this to 0 so we can tell whether an aggregate which was
+        initialized was ever used.  Don't do this if it has a
+        destructor, so we don't complain about the 'resource
+        allocation is initialization' idiom.  */
+      /* Now set attribute((unused)) on types so decls of that type
+        will be marked used. (see TREE_USED, above.)  This avoids the
+        warning problems this particular code tried to work
+        around. */
+
+      if (TYPE_NEEDS_CONSTRUCTING (type)
+         && ! already_used
+         && cleanup == NULL_TREE
+         && DECL_NAME (decl))
+       TREE_USED (decl) = 0;
+
+      if (already_used)
+       TREE_USED (decl) = 1;
+    }
+
+  /* Cleanup any temporaries needed for the initial value.  */
+  expand_end_target_temps ();
+
+  if (DECL_SIZE (decl) && type != error_mark_node)
+    {
+      /* Store the cleanup, if there was one.  */
+      if (cleanup)
+       {
+         if (! expand_decl_cleanup (decl, cleanup))
+           cp_error ("parser lost in parsing declaration of `%D'",
+                     decl);
+       }
+    }
+}
+
 /* Finish processing of a declaration;
    install its line number and initial value.
    If the length of an array type is not known before,
@@ -7364,13 +7894,11 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
      int flags;
 {
   register tree type;
-  tree cleanup = NULL_TREE, ttype = NULL_TREE;
+  tree ttype = NULL_TREE;
   int was_incomplete;
   int temporary = allocation_temporary_p ();
   const char *asmspec = NULL;
   int was_readonly = 0;
-  int already_used = 0;
-  tree core_type;
 
   /* If this is 0, then we did not change obstacks.  */
   if (! decl)
@@ -7433,6 +7961,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       goto finish_end0;
     }
 
+  /* Parameters are handled by store_parm_decls, not cp_finish_decl.  */
+  my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
+
   /* Take care of TYPE_DECLs up front.  */
   if (TREE_CODE (decl) == TYPE_DECL)
     {
@@ -7478,122 +8009,19 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       TREE_READONLY (decl) = 0;
     }
 
-  if (TREE_CODE (decl) == FIELD_DECL)
+  if (TREE_CODE (decl) == FIELD_DECL && asmspec)
     {
-      if (init && init != error_mark_node)
-       my_friendly_assert (TREE_PERMANENT (init), 147);
-
-      if (asmspec)
-       {
-         /* This must override the asm specifier which was placed
-            by grokclassfn.  Lay this out fresh.  */
-         DECL_RTL (TREE_TYPE (decl)) = NULL_RTX;
-         DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
-         make_decl_rtl (decl, asmspec, 0);
-       }
-    }
-  /* If `start_decl' didn't like having an initialization, ignore it now.  */
-  else if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
-    init = NULL_TREE;
-  else if (DECL_EXTERNAL (decl))
-    ;
-  else if (TREE_CODE (type) == REFERENCE_TYPE)
-    {
-      if (TREE_STATIC (decl))
-       make_decl_rtl (decl, NULL_PTR, toplevel_bindings_p ());
-      grok_reference_init (decl, type, init);
-      init = NULL_TREE;
+      /* This must override the asm specifier which was placed by
+        grokclassfn.  Lay this out fresh.  */
+      DECL_RTL (TREE_TYPE (decl)) = NULL_RTX;
+      DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
+      make_decl_rtl (decl, asmspec, 0);
     }
 
-  /* Check for certain invalid initializations.  */
-  if (init)
-    {
-      if (TYPE_SIZE (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
-       {
-         cp_error ("variable-sized object `%D' may not be initialized", decl);
-         init = NULL_TREE;
-       }
-      if (TREE_CODE (type) == ARRAY_TYPE
-         && !TYPE_SIZE (complete_type (TREE_TYPE (type))))
-       {
-         cp_error ("elements of array `%#D' have incomplete type", decl);
-         init = NULL_TREE;
-       }
-    }
+  check_initializer (decl, &init);
 
   GNU_xref_decl (current_function_decl, decl);
 
-  core_type = type;
-  while (TREE_CODE (core_type) == ARRAY_TYPE)
-    core_type = TREE_TYPE (core_type);
-  
-  if (TREE_CODE (decl) == FIELD_DECL)
-    ;
-  else if (TREE_CODE (decl) == CONST_DECL)
-    {
-      my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148);
-
-      DECL_INITIAL (decl) = init;
-
-      /* This will keep us from needing to worry about our obstacks.  */
-      my_friendly_assert (init != NULL_TREE, 149);
-      init = NULL_TREE;
-    }
-  else if (init)
-    {
-      if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
-       {
-         if (TREE_CODE (type) == ARRAY_TYPE)
-           init = digest_init (type, init, (tree *) 0);
-         else if (TREE_CODE (init) == CONSTRUCTOR
-                  && TREE_HAS_CONSTRUCTOR (init))
-           {
-             if (TYPE_NON_AGGREGATE_CLASS (type))
-               {
-                 cp_error ("`%D' must be initialized by constructor, not by `{...}'",
-                           decl);
-                 init = error_mark_node;
-               }
-             else
-               goto dont_use_constructor;
-           }
-       }
-      else
-       {
-       dont_use_constructor:
-         if (TREE_CODE (init) != TREE_VEC)
-           init = store_init_value (decl, init);
-       }
-
-      if (init)
-       /* We must hide the initializer so that expand_decl
-          won't try to do something it does not understand.  */
-       init = obscure_complex_init (decl, init);
-    }
-  else if (DECL_EXTERNAL (decl))
-    ;
-  else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
-          && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
-    {
-      if (! TYPE_NEEDS_CONSTRUCTING (core_type))
-       {
-         if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
-           cp_error ("structure `%D' with uninitialized const members", decl);
-         if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
-           cp_error ("structure `%D' with uninitialized reference members",
-                     decl);
-       }
-
-      check_for_uninitialized_const_var (decl);
-
-      if (TYPE_SIZE (type) != NULL_TREE
-         && TYPE_NEEDS_CONSTRUCTING (type))
-       init = obscure_complex_init (decl, NULL_TREE);
-
-    }
-  else
-    check_for_uninitialized_const_var (decl);
-  
   /* For top-level declaration, the initial value was read in
      the temporary obstack.  MAXINDEX, rtl, etc. to be made below
      must go in the permanent obstack; but don't discard the
@@ -7603,102 +8031,10 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
     end_temporary_allocation ();
 
   /* Deduce size of array from initialization, if not already known.  */
-
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_DOMAIN (type) == NULL_TREE
-      && TREE_CODE (decl) != TYPE_DECL)
-    {
-      int do_default
-       = (TREE_STATIC (decl)
-          /* Even if pedantic, an external linkage array
-             may have incomplete type at first.  */
-          ? pedantic && ! DECL_EXTERNAL (decl)
-          : !DECL_EXTERNAL (decl));
-      tree initializer = init ? init : DECL_INITIAL (decl);
-      int failure = complete_array_type (type, initializer, do_default);
-
-      if (failure == 1)
-       cp_error ("initializer fails to determine size of `%D'", decl);
-
-      if (failure == 2)
-       {
-         if (do_default)
-           cp_error ("array size missing in `%D'", decl);
-         /* If a `static' var's size isn't known, make it extern as
-            well as static, so it does not get allocated.  If it's not
-            `static', then don't mark it extern; finish_incomplete_decl
-            will give it a default size and it will get allocated.  */
-         else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
-           DECL_EXTERNAL (decl) = 1;
-       }
-
-      if (pedantic && TYPE_DOMAIN (type) != NULL_TREE
-         && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
-                             integer_zero_node))
-       cp_error ("zero-size array `%D'", decl);
-
-      layout_decl (decl, 0);
-    }
+  maybe_deduce_size_from_array_init (decl, init);
 
   if (TREE_CODE (decl) == VAR_DECL)
-    {
-      if (DECL_SIZE (decl) == NULL_TREE
-         && TYPE_SIZE (complete_type (TREE_TYPE (decl))) != NULL_TREE)
-       layout_decl (decl, 0);
-
-      if (TREE_STATIC (decl) && DECL_SIZE (decl) == NULL_TREE)
-       {
-         /* A static variable with an incomplete type:
-            that is an error if it is initialized.
-            Otherwise, let it through, but if it is not `extern'
-            then it may cause an error message later.  */
-         if (DECL_INITIAL (decl) != NULL_TREE)
-           cp_error ("storage size of `%D' isn't known", decl);
-         init = NULL_TREE;
-       }
-      else if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
-       {
-         /* An automatic variable with an incomplete type: that is an error.
-            Don't talk about array types here, since we took care of that
-            message in grokdeclarator.  */
-         cp_error ("storage size of `%D' isn't known", decl);
-         TREE_TYPE (decl) = error_mark_node;
-       }
-      else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
-       /* Let debugger know it should output info for this type.  */
-       note_debug_info_needed (ttype);
-
-      if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl))
-       note_debug_info_needed (DECL_CONTEXT (decl));
-
-      if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
-         && DECL_SIZE (decl) != NULL_TREE
-         && ! TREE_CONSTANT (DECL_SIZE (decl)))
-       {
-         if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
-           constant_expression_warning (DECL_SIZE (decl));
-         else
-           cp_error ("storage size of `%D' isn't constant", decl);
-       }
-
-      if (! DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)
-         /* Cleanups for static variables are handled by `finish_file'.  */
-         && ! TREE_STATIC (decl))
-       {
-         int yes = suspend_momentary ();
-         cleanup = maybe_build_cleanup (decl);
-         resume_momentary (yes);
-       }
-    }
-  /* PARM_DECLs get cleanups, too.  */
-  else if (TREE_CODE (decl) == PARM_DECL && TYPE_NEEDS_DESTRUCTOR (type))
-    {
-      if (temporary)
-       end_temporary_allocation ();
-      cleanup = maybe_build_cleanup (decl);
-      if (temporary)
-       resume_temporary_allocation ();
-    }
+    layout_var_decl (decl, &init);
 
   /* Output the assembler code and/or RTL code for variables and functions,
      unless the type is an undefined structure or union.
@@ -7711,146 +8047,18 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
     {
       /* ??? FIXME: What about nested classes?  */
       int toplev = toplevel_bindings_p ();
-      int was_temp
-       = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
-          && allocation_temporary_p ());
 
-      if (was_temp)
-       end_temporary_allocation ();
-
-      /* Static data in a function with comdat linkage also has comdat
-         linkage.  */
-      if (TREE_CODE (decl) == VAR_DECL
-         && TREE_STATIC (decl)
-         /* Don't mess with __FUNCTION__.  */
-         && ! TREE_ASM_WRITTEN (decl)
-         && current_function_decl
-         && DECL_CONTEXT (decl) == current_function_decl
-         && (DECL_THIS_INLINE (current_function_decl)
-             || DECL_TEMPLATE_INSTANTIATION (current_function_decl))
-         && TREE_PUBLIC (current_function_decl))
-       {
-         /* Rather than try to get this right with inlining, we suppress
-            inlining of such functions.  */
-         current_function_cannot_inline
-           = "function with static variable cannot be inline";
-
-         /* If flag_weak, we don't need to mess with this, as we can just
-            make the function weak, and let it refer to its unique local
-            copy.  This works because we don't allow the function to be
-            inlined.  */
-         if (! flag_weak)
-           {
-             if (DECL_INTERFACE_KNOWN (current_function_decl))
-               {
-                 TREE_PUBLIC (decl) = 1;
-                 DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
-               }
-             else if (DECL_INITIAL (decl) == NULL_TREE
-                      || DECL_INITIAL (decl) == error_mark_node)
-               {
-                 TREE_PUBLIC (decl) = 1;
-                 DECL_COMMON (decl) = 1;
-               }
-             /* else we lose. We can only do this if we can use common,
-                 which we can't if it has been initialized.  */
-
-             if (TREE_PUBLIC (decl))
-               DECL_ASSEMBLER_NAME (decl)
-                 = build_static_name (current_function_decl, DECL_NAME (decl));
-             else if (! DECL_ARTIFICIAL (decl))
-               {
-                 cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
-                 cp_warning_at ("  you can work around this by removing the initializer", decl);
-               }
-           }
-       }
-
-      else if (TREE_CODE (decl) == VAR_DECL
-              && DECL_LANG_SPECIFIC (decl)
-              && DECL_COMDAT (decl))
-       /* Set it up again; we might have set DECL_INITIAL since the
-          last time.  */
-       comdat_linkage (decl);
-
-      if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
-       make_decl_rtl (decl, NULL_PTR, toplev);
-      else if (TREE_CODE (decl) == VAR_DECL
-              && TREE_READONLY (decl)
-              && DECL_INITIAL (decl) != NULL_TREE
-              && DECL_INITIAL (decl) != error_mark_node
-              && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
-       {
-         DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
-
-         if (asmspec)
-           DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
-
-         if (! toplev
-             && TREE_STATIC (decl)
-             && ! TREE_SIDE_EFFECTS (decl)
-             && ! TREE_PUBLIC (decl)
-             && ! DECL_EXTERNAL (decl)
-             && ! TYPE_NEEDS_DESTRUCTOR (type)
-             && DECL_MODE (decl) != BLKmode)
-           {
-             /* If this variable is really a constant, then fill its DECL_RTL
-                slot with something which won't take up storage.
-                If something later should take its address, we can always give
-                it legitimate RTL at that time.  */
-             DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
-             store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0);
-             TREE_ASM_WRITTEN (decl) = 1;
-           }
-         else if (toplev && ! TREE_PUBLIC (decl))
-           {
-             /* If this is a static const, change its apparent linkage
-                if it belongs to a #pragma interface.  */
-             if (!interface_unknown)
-               {
-                 TREE_PUBLIC (decl) = 1;
-                 DECL_EXTERNAL (decl) = interface_only;
-               }
-             make_decl_rtl (decl, asmspec, toplev);
-           }
-         else
-           rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
-       }
-      else if (TREE_CODE (decl) == VAR_DECL
-              && DECL_LANG_SPECIFIC (decl)
-              && DECL_IN_AGGR_P (decl))
-       {
-         if (TREE_STATIC (decl))
-           {
-             if (init == NULL_TREE
-#ifdef DEFAULT_STATIC_DEFS
-                 /* If this code is dead, then users must
-                    explicitly declare static member variables
-                    outside the class def'n as well.  */
-                 && TYPE_NEEDS_CONSTRUCTING (type)
-#endif
-                 )
-               {
-                 DECL_EXTERNAL (decl) = 1;
-                 make_decl_rtl (decl, asmspec, 1);
-               }
-             else
-               rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
-           }
-         else
-           /* Just a constant field.  Should not need any rtl.  */
-           goto finish_end0;
-       }
-      else
-       rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+      if (TREE_CODE (decl) == VAR_DECL)
+       maybe_commonize_var (decl);
 
-      if (was_temp)
-       resume_temporary_allocation ();
+      make_rtl_for_nonlocal_decl (decl, init, asmspec);
 
-      if (!abstract_virtuals_error (decl, core_type)
-         && (TREE_CODE (type) == FUNCTION_TYPE
-             || TREE_CODE (type) == METHOD_TYPE))
-       abstract_virtuals_error (decl, TREE_TYPE (type));
+      if (TREE_CODE (type) == FUNCTION_TYPE 
+         || TREE_CODE (type) == METHOD_TYPE)
+       abstract_virtuals_error (decl, 
+                                strip_array_types (TREE_TYPE (type)));
+      else 
+       abstract_virtuals_error (decl, strip_array_types (type));
 
       if (TREE_CODE (decl) == FUNCTION_DECL)
        ;
@@ -7870,6 +8078,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
        }
       else if (! toplev)
        {
+         tree cleanup = build_cleanup_on_safe_obstack (decl);
+
          /* This is a declared decl which must live until the
             end of the binding contour.  It may need a cleanup.  */
 
@@ -7904,93 +8114,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
                }
            }
 
-         if (current_binding_level->is_for_scope)
-           {
-             struct binding_level *outer 
-               = current_binding_level->level_chain;
-
-             /* Check to see if the same name is already bound at
-                the outer level, either because it was directly declared,
-                or because a dead for-decl got preserved.  In either case,
-                the code would not have been valid under the ARM
-                scope rules, so clear is_for_scope for the
-                current_binding_level.
-
-                Otherwise, we need to preserve the temp slot for decl
-                to last into the outer binding level.  */
-
-             tree outer_binding 
-               = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
-             
-             if (outer_binding && BINDING_LEVEL (outer_binding) == outer
-                 && (TREE_CODE (BINDING_VALUE (outer_binding)) 
-                     == VAR_DECL)
-                 && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
-               {
-                 BINDING_VALUE (outer_binding)
-                   = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
-                 current_binding_level->is_for_scope = 0;
-               }
-             else if (DECL_IN_MEMORY_P (decl))
-               preserve_temp_slots (DECL_RTL (decl));
-           }
-
-         expand_start_target_temps ();
-
-         if (DECL_SIZE (decl) && type != error_mark_node)
-           {
-             /* Compute and store the initial value.  */
-             expand_decl_init (decl);
-                     already_used = TREE_USED (decl) || TREE_USED (type);
-
-             if (init || TYPE_NEEDS_CONSTRUCTING (type))
-               {
-                 emit_line_note (DECL_SOURCE_FILE (decl),
-                                 DECL_SOURCE_LINE (decl));
-                 /* We call push_momentary here so that when
-                    finish_expr_stmt clears the momentary obstack it
-                    doesn't destory any momentary expressions we may
-                    have lying around.  Although cp_finish_decl is
-                    usually called at the end of a declaration
-                    statement, it may also be called for a temporary
-                    object in the middle of an expression.  */
-                 push_momentary ();
-                 finish_expr_stmt (build_aggr_init (decl, init, flags));
-                 pop_momentary ();
-               }
-
-             /* Set this to 0 so we can tell whether an aggregate which
-                was initialized was ever used.  Don't do this if it has a
-                destructor, so we don't complain about the 'resource
-                allocation is initialization' idiom.  */
-             /* Now set attribute((unused)) on types so decls of
-                that type will be marked used. (see TREE_USED, above.) 
-                This avoids the warning problems this particular code
-                tried to work around. */
-
-             if (TYPE_NEEDS_CONSTRUCTING (type)
-                 && ! already_used
-                 && cleanup == NULL_TREE
-                 && DECL_NAME (decl))
-               TREE_USED (decl) = 0;
-
-             if (already_used)
-               TREE_USED (decl) = 1;
-           }
-
-         /* Cleanup any temporaries needed for the initial value.  */
-         expand_end_target_temps ();
-
-         if (DECL_SIZE (decl) && type != error_mark_node)
-           {
-             /* Store the cleanup, if there was one.  */
-             if (cleanup)
-               {
-                 if (! expand_decl_cleanup (decl, cleanup))
-                   cp_error ("parser lost in parsing declaration of `%D'",
-                             decl);
-               }
-           }
+         maybe_inject_for_scope_var (decl);
+         initialize_local_var (decl, init, cleanup, flags);
        }
     finish_end0:
 
@@ -8035,12 +8160,10 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
     }
 
   if (need_pop)
-    {
-      /* Resume permanent allocation, if not within a function.  */
-      /* The corresponding push_obstacks_nochange is in start_decl,
-        start_method, groktypename, and in grokfield.  */
-      pop_obstacks ();
-    }
+    /* Resume permanent allocation, if not within a function.  The
+       corresponding push_obstacks_nochange is in start_decl,
+       start_method, groktypename, and in grokfield.  */
+    pop_obstacks ();
 
   if (was_readonly)
     TREE_READONLY (decl) = 1;
index a6435166fbbc03b5d8498e34bc393df09838dee7..e41d450046aabe717b9f6b8230644a9a9eabb268 100644 (file)
@@ -7167,16 +7167,26 @@ comp_ptr_ttypes_reinterpret (to, from)
     }
 }
 
-/* Returns the type-qualifier set corresponding to TYPE.  */
+/* Recursively examines the array elements of TYPE, until a non-array
+   element type is found.  */
 
-int
-cp_type_quals (type)
+tree
+strip_array_types (type)
      tree type;
 {
   while (TREE_CODE (type) == ARRAY_TYPE)
     type = TREE_TYPE (type);
 
-  return TYPE_QUALS (type);
+  return type;
+}
+
+/* Returns the type-qualifier set corresponding to TYPE.  */
+
+int
+cp_type_quals (type)
+     tree type;
+{
+  return TYPE_QUALS (strip_array_types (type));
 }
 
 /* Returns non-zero if the TYPE contains a mutable member */
This page took 0.112824 seconds and 5 git commands to generate.