OSDN Git Service

* function.c (assign_parms): For a struct value address passed as
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 9c3b58f..2aa0ee7 100644 (file)
@@ -28,6 +28,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "intl.h"
 #include "tree.h"
 #include "tree-inline.h"
@@ -46,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "timevar.h"
 #include "c-common.h"
 #include "c-pragma.h"
+#include "cgraph.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -280,7 +283,7 @@ static tree grokdeclarator          PARAMS ((tree, tree, enum decl_context,
 static tree grokparms                  PARAMS ((tree, int));
 static void layout_array_type          PARAMS ((tree));
 static tree c_make_fname_decl           PARAMS ((tree, int));
-static void c_expand_body               PARAMS ((tree, int, int));
+static void c_expand_body_1             PARAMS ((tree, int));
 static void warn_if_shadowing          PARAMS ((tree, tree));
 static bool flexible_array_type_p      PARAMS ((tree));
 \f
@@ -1138,6 +1141,13 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
            }
        }
       error_with_decl (olddecl, "previous declaration of `%s'");
+
+      /* This is safer because the initializer might contain references
+        to variables that were declared between olddecl and newdecl. This
+        will make the initializer invalid for olddecl in case it gets
+        assigned to olddecl below.  */
+      if (TREE_CODE (newdecl) == VAR_DECL)
+       DECL_INITIAL (newdecl) = 0;
     }
   /* TLS cannot follow non-TLS declaration.  */
   else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
@@ -1474,9 +1484,10 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
         inline, make sure we emit debug info for the inline before we
         throw it away, in case it was inlined into a function that hasn't
         been written out yet.  */
-      if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
+      if (new_is_definition && DECL_INITIAL (olddecl))
        {
-         (*debug_hooks->outlining_inline_function) (olddecl);
+         if (TREE_USED (olddecl))
+           (*debug_hooks->outlining_inline_function) (olddecl);
 
          /* The new defn must not be inline.  */
          DECL_INLINE (newdecl) = 0;
@@ -1725,7 +1736,7 @@ pushdecl (x)
        }
 
       /* If we are processing a typedef statement, generate a whole new
-        ..._TYPE node (which will be just an variant of the existing
+        ..._TYPE node (which will be just a variant of the existing
         ..._TYPE node with identical properties) and then install the
         TYPE_DECL node generated to represent the typedef name as the
         TYPE_NAME of this brand new (duplicate) ..._TYPE node.
@@ -2542,6 +2553,18 @@ c_make_fname_decl (id, type_dep)
   DECL_INITIAL (decl) = init;
 
   TREE_USED (decl) = 1;
+
+  if (current_function_decl)
+    {
+      /* Add the decls to the outermost block.  */
+      struct binding_level *b = current_binding_level;
+      struct binding_level *old = b;
+      while (b->level_chain->parm_flag == 0)
+       b = b->level_chain;
+      current_binding_level = b;
+      pushdecl (decl);
+      current_binding_level = old;
+    }  
   
   finish_decl (decl, init, NULL_TREE);
 
@@ -2907,7 +2930,7 @@ start_decl (declarator, declspecs, initialized, attributes)
 
      Thread-local variables are never common, since there's no entrenched
      body of code to break, and it allows more efficient variable references
-     in the presense of dynamic linking.  */
+     in the presence of dynamic linking.  */
 
   if (TREE_CODE (decl) == VAR_DECL
       && !initialized
@@ -3211,6 +3234,8 @@ clear_parm_order ()
   current_binding_level->parm_order = NULL_TREE;
 }
 \f
+static GTY(()) int compound_literal_number;
+
 /* Build a COMPOUND_LITERAL_EXPR.  TYPE is the type given in the compound
    literal, which may be an incomplete array type completed by the
    initializer; INIT is a CONSTRUCTOR that initializes the compound
@@ -3258,10 +3283,10 @@ build_compound_literal (type, init)
       /* This decl needs a name for the assembler output.  We also need
         a unique suffix to be added to the name.  */
       char *name;
-      extern int var_labelno;
 
-      ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", var_labelno);
-      var_labelno++;
+      ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", 
+                              compound_literal_number);
+      compound_literal_number++;
       DECL_NAME (decl) = get_identifier (name);
       DECL_DEFER_OUTPUT (decl) = 1;
       DECL_COMDAT (decl) = 1;
@@ -4158,7 +4183,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            {
              /* Type qualifiers on a function return type are normally
                 permitted by the standard but have no effect, so give a
-                warning at -W.  Qualifiers on a void return type have
+                warning at -Wextra.  Qualifiers on a void return type have
                 meaning as a GNU extension, and are banned on function
                 definitions in ISO C.  FIXME: strictly we shouldn't
                 pedwarn for qualified void return types except on function
@@ -4543,6 +4568,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
           needed, and let dwarf2 know that the function is inlinable.  */
        else if (flag_inline_trees == 2 && initialized)
          {
+           if (!DECL_INLINE (decl))
+               DID_INLINE_FUNC (decl) = 1;
            DECL_INLINE (decl) = 1;
            DECL_DECLARED_INLINE_P (decl) = 0;
          }
@@ -4953,25 +4980,22 @@ start_struct (code, name)
     ref = lookup_tag (code, name, current_binding_level, 1);
   if (ref && TREE_CODE (ref) == code)
     {
-      C_TYPE_BEING_DEFINED (ref) = 1;
-      TYPE_PACKED (ref) = flag_pack_struct;
       if (TYPE_FIELDS (ref))
         {
          if (code == UNION_TYPE)
-           error ("redefinition of `union %s'",
-                  IDENTIFIER_POINTER (name));
+           error ("redefinition of `union %s'", IDENTIFIER_POINTER (name));
           else
-           error ("redefinition of `struct %s'",
-                  IDENTIFIER_POINTER (name));
+           error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
        }  
-
-      return ref;
     }
+  else
+    {
+      /* Otherwise create a forward-reference just so the tag is in scope.  */
 
-  /* Otherwise create a forward-reference just so the tag is in scope.  */
-
-  ref = make_node (code);
-  pushtag (name, ref);
+      ref = make_node (code);
+      pushtag (name, ref);
+    }
+  
   C_TYPE_BEING_DEFINED (ref) = 1;
   TYPE_PACKED (ref) = flag_pack_struct;
   return ref;
@@ -5010,7 +5034,7 @@ grokfield (filename, line, declarator, declspecs, width)
             again this is an anonymous struct.
           Otherwise this is an error.
 
-        Oh what a horrid tangled web we weave.  I wonder if MS consiously
+        Oh what a horrid tangled web we weave.  I wonder if MS consciously
         took this from Plan 9 or if it was an accident of implementation
         that took root before someone noticed the bug...  */
 
@@ -6392,10 +6416,62 @@ finish_function (nested, can_defer_p)
   free_after_compilation (cfun);
   cfun = NULL;
 
+  if (flag_unit_at_a_time && can_defer_p)
+    {
+      cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
+      current_function_decl = NULL;
+      return;
+    }
+
   if (! nested)
     {
-      /* Generate RTL for the body of this function.  */
-      c_expand_body (fndecl, nested, can_defer_p);
+      /* Function is parsed.
+        Generate RTL for the body of this function or defer
+        it for later expansion.  */
+      int uninlinable = 1;
+
+      /* There's no reason to do any of the work here if we're only doing
+        semantic analysis; this code just generates RTL.  */
+      if (flag_syntax_only)
+       {
+         current_function_decl = NULL;
+         DECL_SAVED_TREE (fndecl) = NULL_TREE;
+         return;
+       }
+
+      if (flag_inline_trees)
+       {
+         /* First, cache whether the current function is inlinable.  Some
+            predicates depend on cfun and current_function_decl to
+            function completely.  */
+         timevar_push (TV_INTEGRATION);
+         uninlinable = ! tree_inlinable_function_p (fndecl, 0);
+         
+         if (! uninlinable && can_defer_p
+             /* Save function tree for inlining.  Should return 0 if the
+                language does not support function deferring or the
+                function could not be deferred.  */
+             && defer_fn (fndecl))
+           {
+             /* Let the back-end know that this function exists.  */
+             (*debug_hooks->deferred_inline_function) (fndecl);
+             timevar_pop (TV_INTEGRATION);
+             current_function_decl = NULL;
+             return;
+           }
+         
+         /* Then, inline any functions called in it.  */
+         optimize_inline_calls (fndecl);
+         timevar_pop (TV_INTEGRATION);
+       }
+
+      c_expand_body (fndecl);
+
+      if (uninlinable)
+       {
+         /* Allow the body of the function to be garbage collected.  */
+         DECL_SAVED_TREE (fndecl) = NULL_TREE;
+       }
 
       /* Let the error reporting routines know that we're outside a
         function.  For a nested function, this value is used in
@@ -6414,7 +6490,13 @@ c_expand_deferred_function (fndecl)
      function was deferred, e.g. in duplicate_decls.  */
   if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
     {
-      c_expand_body (fndecl, 0, 0);
+      if (flag_inline_trees)
+       {
+         timevar_push (TV_INTEGRATION);
+         optimize_inline_calls (fndecl);
+         timevar_pop (TV_INTEGRATION);
+       }
+      c_expand_body (fndecl);
       current_function_decl = NULL;
     }
 }
@@ -6425,42 +6507,10 @@ c_expand_deferred_function (fndecl)
    generation of RTL.  */
 
 static void
-c_expand_body (fndecl, nested_p, can_defer_p)
+c_expand_body_1 (fndecl, nested_p)
      tree fndecl;
-     int nested_p, can_defer_p;
+     int nested_p;
 {
-  int uninlinable = 1;
-
-  /* There's no reason to do any of the work here if we're only doing
-     semantic analysis; this code just generates RTL.  */
-  if (flag_syntax_only)
-    return;
-
-  if (flag_inline_trees)
-    {
-      /* First, cache whether the current function is inlinable.  Some
-         predicates depend on cfun and current_function_decl to
-         function completely.  */
-      timevar_push (TV_INTEGRATION);
-      uninlinable = ! tree_inlinable_function_p (fndecl);
-      
-      if (! uninlinable && can_defer_p
-         /* Save function tree for inlining.  Should return 0 if the
-             language does not support function deferring or the
-             function could not be deferred.  */
-         && defer_fn (fndecl))
-       {
-         /* Let the back-end know that this function exists.  */
-         (*debug_hooks->deferred_inline_function) (fndecl);
-          timevar_pop (TV_INTEGRATION);
-         return;
-       }
-      
-      /* Then, inline any functions called in it.  */
-      optimize_inline_calls (fndecl);
-      timevar_pop (TV_INTEGRATION);
-    }
-
   timevar_push (TV_EXPAND);
 
   if (nested_p)
@@ -6476,6 +6526,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
   current_function_decl = fndecl;
   input_filename = DECL_SOURCE_FILE (fndecl);
   init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
+  lineno = DECL_SOURCE_LINE (fndecl);
 
   /* This function is being processed in whole-function mode.  */
   cfun->x_whole_function_mode_p = 1;
@@ -6499,11 +6550,6 @@ c_expand_body (fndecl, nested_p, can_defer_p)
 
   /* Generate the RTL for this function.  */
   expand_stmt (DECL_SAVED_TREE (fndecl));
-  if (uninlinable)
-    {
-      /* Allow the body of the function to be garbage collected.  */
-      DECL_SAVED_TREE (fndecl) = NULL_TREE;
-    }
 
   /* We hard-wired immediate_size_expand to zero above.
      expand_function_end will decrement this variable.  So, we set the
@@ -6530,7 +6576,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
   if (nested_p)
     ggc_pop_context ();
 
-  /* With just -W, complain only if function returns both with
+  /* With just -Wextra, complain only if function returns both with
      and without a value.  */
   if (extra_warnings
       && current_function_returns_value
@@ -6601,6 +6647,15 @@ c_expand_body (fndecl, nested_p, can_defer_p)
     pop_function_context ();
   timevar_pop (TV_EXPAND);
 }
+
+/* Like c_expand_body_1 but only for unnested functions.  */
+
+void
+c_expand_body (fndecl)
+     tree fndecl;
+{
+  c_expand_body_1 (fndecl, 0);
+}
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
    constraints.  */
@@ -6834,7 +6889,7 @@ c_expand_decl_stmt (t)
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_CONTEXT (decl) == current_function_decl
       && DECL_SAVED_TREE (decl))
-    c_expand_body (decl, /*nested_p=*/1, /*can_defer_p=*/0);
+    c_expand_body_1 (decl, 1);
 }
 
 /* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since