OSDN Git Service

2010-12-02 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index c7babb5..b1055b0 100644 (file)
@@ -118,12 +118,6 @@ static GTY(()) struct stmt_tree_s c_stmt_tree;
 tree c_break_label;
 tree c_cont_label;
 
-/* Linked list of TRANSLATION_UNIT_DECLS for the translation units
-   included in this invocation.  Note that the current translation
-   unit is not included in this list.  */
-
-static GTY(()) tree all_translation_units;
-
 /* A list of decls to be made automatically visible in each file scope.  */
 static GTY(()) tree visible_builtins;
 
@@ -1072,10 +1066,7 @@ pop_scope (void)
     context = current_function_decl;
   else if (scope == file_scope)
     {
-      tree file_decl = build_decl (UNKNOWN_LOCATION,
-                                  TRANSLATION_UNIT_DECL, 0, 0);
-      DECL_CHAIN (file_decl) = all_translation_units;
-      all_translation_units = file_decl;
+      tree file_decl = build_translation_unit_decl (NULL_TREE);
       context = file_decl;
     }
   else
@@ -1212,15 +1203,14 @@ pop_scope (void)
              DECL_CHAIN (extp) = BLOCK_VARS (block);
              BLOCK_VARS (block) = extp;
            }
-         /* If this is the file scope, and we are processing more
-            than one translation unit in this compilation, set
-            DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
-            This makes same_translation_unit_p work, and causes
-            static declarations to be given disambiguating suffixes.  */
-         if (scope == file_scope && num_in_fnames > 1)
+         /* If this is the file scope set DECL_CONTEXT of each decl to
+            the TRANSLATION_UNIT_DECL.  This makes same_translation_unit_p
+            work.  */
+         if (scope == file_scope)
            {
              DECL_CONTEXT (p) = context;
-             if (TREE_CODE (p) == TYPE_DECL)
+             if (TREE_CODE (p) == TYPE_DECL
+                 && TREE_TYPE (p) != error_mark_node)
                set_type_context (TREE_TYPE (p), context);
            }
 
@@ -2971,7 +2961,8 @@ undeclared_variable (location_t loc, tree id)
     }
   else
     {
-      error_at (loc, "%qE undeclared (first use in this function)", id);
+      if (!objc_diagnose_private_ivar (id))
+        error_at (loc, "%qE undeclared (first use in this function)", id);
       if (!already)
        {
           inform (loc, "each undeclared identifier is reported only"
@@ -3022,7 +3013,7 @@ lookup_label (tree name)
   tree label;
   struct c_label_vars *label_vars;
 
-  if (current_function_decl == 0)
+  if (current_function_scope == 0)
     {
       error ("label %qE referenced outside of any function", name);
       return 0;
@@ -3643,7 +3634,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
                  warned = 1;
                }
            }
-         else if (!declspecs->tag_defined_p
+         else if (declspecs->typespec_kind != ctsk_tagdef
+                   && declspecs->typespec_kind != ctsk_tagfirstref
                   && declspecs->storage_class != csc_none)
            {
              if (warned != 1)
@@ -3653,7 +3645,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
              warned = 1;
              pending_xref_error ();
            }
-         else if (!declspecs->tag_defined_p
+         else if (declspecs->typespec_kind != ctsk_tagdef
+                   && declspecs->typespec_kind != ctsk_tagfirstref
                   && (declspecs->const_p
                       || declspecs->volatile_p
                       || declspecs->restrict_p
@@ -4082,6 +4075,11 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
     record_inline_static (input_location, current_function_decl,
                          decl, csi_modifiable);
 
+  if (c_dialect_objc () 
+      && (TREE_CODE (decl) == VAR_DECL
+          || TREE_CODE (decl) == FUNCTION_DECL))
+      objc_check_global_decl (decl);
+
   /* Add this decl to the current scope.
      TEM may equal DECL or it may be a previous decl of the same name.  */
   tem = pushdecl (decl);
@@ -4584,7 +4582,9 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const)
 void
 check_compound_literal_type (location_t loc, struct c_type_name *type_name)
 {
-  if (warn_cxx_compat && type_name->specs->tag_defined_p)
+  if (warn_cxx_compat
+      && (type_name->specs->typespec_kind == ctsk_tagdef
+          || type_name->specs->typespec_kind == ctsk_tagfirstref))
     warning_at (loc, OPT_Wc___compat,
                "defining a type in a compound literal is invalid in C++");
 }
@@ -5458,6 +5458,7 @@ grokdeclarator (const struct c_declarator *declarator,
                if (size && integer_zerop (size))
                  {
                    gcc_assert (itype);
+                   type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
                    TYPE_SIZE (type) = bitsize_zero_node;
                    TYPE_SIZE_UNIT (type) = size_zero_node;
                    SET_TYPE_STRUCTURAL_EQUALITY (type);
@@ -5466,6 +5467,7 @@ grokdeclarator (const struct c_declarator *declarator,
                  {
                    gcc_assert (itype);
                    /* The type is complete.  C99 6.7.5.2p4  */
+                   type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
                    TYPE_SIZE (type) = bitsize_zero_node;
                    TYPE_SIZE_UNIT (type) = size_zero_node;
                    SET_TYPE_STRUCTURAL_EQUALITY (type);
@@ -6617,15 +6619,15 @@ grokfield (location_t loc,
         is the anonymous union extension.  Similarly for struct.
 
         If this is something of the form "struct foo;", then
-          If MS extensions are enabled, this is handled as an
-            anonymous struct.
+          If MS or Plan 9 extensions are enabled, this is handled as
+            an anonymous struct.
           Otherwise this is a forward declaration of a structure tag.
 
         If this is something of the form "foo;" and foo is a TYPE_DECL, then
           If foo names a structure or union without a tag, then this
             is an anonymous struct (this is permitted by C1X).
-          If MS extensions are enabled and foo names a structure, then
-            again this is an anonymous struct.
+          If MS or Plan 9 extensions are enabled and foo names a
+            structure, then again this is an anonymous struct.
           Otherwise this is an error.
 
         Oh what a horrid tangled web we weave.  I wonder if MS consciously
@@ -6639,7 +6641,7 @@ grokfield (location_t loc,
 
       if (type_ok)
        {
-         if (flag_ms_extensions)
+         if (flag_ms_extensions || flag_plan9_extensions)
            ok = true;
          else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL)
            ok = true;
@@ -6691,6 +6693,50 @@ grokfield (location_t loc,
   return value;
 }
 \f
+/* Subroutine of detect_field_duplicates: return whether X and Y,
+   which are both fields in the same struct, have duplicate field
+   names.  */
+
+static bool
+is_duplicate_field (tree x, tree y)
+{
+  if (DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y))
+    return true;
+
+  /* When using -fplan9-extensions, an anonymous field whose name is a
+     typedef can duplicate a field name.  */
+  if (flag_plan9_extensions
+      && (DECL_NAME (x) == NULL_TREE || DECL_NAME (y) == NULL_TREE))
+    {
+      tree xt, xn, yt, yn;
+
+      xt = TREE_TYPE (x);
+      if (DECL_NAME (x) != NULL_TREE)
+       xn = DECL_NAME (x);
+      else if ((TREE_CODE (xt) == RECORD_TYPE || TREE_CODE (xt) == UNION_TYPE)
+              && TYPE_NAME (xt) != NULL_TREE
+              && TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL)
+       xn = DECL_NAME (TYPE_NAME (xt));
+      else
+       xn = NULL_TREE;
+
+      yt = TREE_TYPE (y);
+      if (DECL_NAME (y) != NULL_TREE)
+       yn = DECL_NAME (y);
+      else if ((TREE_CODE (yt) == RECORD_TYPE || TREE_CODE (yt) == UNION_TYPE)
+              && TYPE_NAME (yt) != NULL_TREE
+              && TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL)
+       yn = DECL_NAME (TYPE_NAME (yt));
+      else
+       yn = NULL_TREE;
+
+      if (xn != NULL_TREE && xn == yn)
+       return true;
+    }
+
+  return false;
+}
+
 /* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
    to HTAB, giving errors for any duplicates.  */
 
@@ -6713,7 +6759,22 @@ detect_field_duplicates_hash (tree fieldlist, htab_t htab)
       }
     else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
             || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
-      detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
+      {
+       detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
+
+       /* When using -fplan9-extensions, an anonymous field whose
+          name is a typedef can duplicate a field name.  */
+       if (flag_plan9_extensions
+           && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
+           && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)
+         {
+           tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x)));
+           slot = htab_find_slot (htab, xn, INSERT);
+           if (*slot)
+             error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x)));
+           *slot = xn;
+         }
+      }
 }
 
 /* Generate an error for any duplicate field names in FIELDLIST.  Munge
@@ -6725,6 +6786,17 @@ detect_field_duplicates (tree fieldlist)
   tree x, y;
   int timeout = 10;
 
+  /* If the struct is the list of instance variables of an Objective-C
+     class, then we need to add all the instance variables of
+     superclasses before checking for duplicates (since you can't have
+     an instance variable in a subclass with the same name as an
+     instance variable in a superclass).  objc_get_interface_ivars()
+     leaves fieldlist unchanged if we are not in this case, so in that
+     case nothing changes compared to C.
+  */
+  if (c_dialect_objc ())
+    fieldlist = objc_get_interface_ivars (fieldlist);
+
   /* First, see if there are more than "a few" fields.
      This is trivially true if there are zero or one fields.  */
   if (!fieldlist)
@@ -6747,10 +6819,18 @@ detect_field_duplicates (tree fieldlist)
   if (timeout > 0)
     {
       for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x))
-       if (DECL_NAME (x))
+       /* When using -fplan9-extensions, we can have duplicates
+          between typedef names and fields.  */
+       if (DECL_NAME (x)
+           || (flag_plan9_extensions
+               && DECL_NAME (x) == NULL_TREE
+               && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+                   || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+               && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
+               && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL))
          {
            for (y = fieldlist; y != x; y = TREE_CHAIN (y))
-             if (DECL_NAME (y) == DECL_NAME (x))
+             if (is_duplicate_field (y, x))
                {
                  error ("duplicate member %q+D", x);
                  DECL_NAME (x) = NULL_TREE;
@@ -6801,7 +6881,8 @@ warn_cxx_compat_finish_struct (tree fieldlist)
 
       for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
        {
-         if (pointer_set_contains (tset, DECL_NAME (x)))
+         if (DECL_NAME (x) != NULL_TREE
+             && pointer_set_contains (tset, DECL_NAME (x)))
            {
              warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
                          ("using %qD as both field and typedef name is "
@@ -7423,9 +7504,8 @@ build_enumerator (location_t decl_loc, location_t loc,
 
   /* Set basis for default for next value.  */
   the_enum->enum_next_value
-    = build_binary_op
-         (EXPR_HAS_LOCATION (value) ? EXPR_LOCATION (value) : input_location,
-        PLUS_EXPR, value, integer_one_node, 0);
+    = build_binary_op (EXPR_LOC_OR_HERE (value),
+                      PLUS_EXPR, value, integer_one_node, 0);
   the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
 
   /* Now create a declaration for the enum value name.  */
@@ -7771,6 +7851,9 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
       if (b && B_IN_CURRENT_SCOPE (b))
        {
          decl = b->decl;
+         /* Skip erroneous parameters.  */
+         if (decl == error_mark_node)
+           continue;
          /* If we got something other than a PARM_DECL it is an error.  */
          if (TREE_CODE (decl) != PARM_DECL)
            error_at (DECL_SOURCE_LOCATION (decl),
@@ -8101,6 +8184,9 @@ void
 finish_function (void)
 {
   tree fndecl = current_function_decl;
+  
+  if (c_dialect_objc ())
+    objc_finish_function ();
 
   if (TREE_CODE (fndecl) == FUNCTION_DECL
       && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
@@ -8235,16 +8321,23 @@ finish_function (void)
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
    constraints.  If exactly one such decl is found, return it.  LOC is
-   the location of the opening parenthesis of the for loop.  */
+   the location of the opening parenthesis of the for loop.  The last
+   parameter allows you to control the "for loop initial declarations
+   are only allowed in C99 mode".  Normally, you should pass
+   flag_isoc99 as that parameter.  But in some cases (Objective-C
+   foreach loop, for example) we want to run the checks in this
+   function even if not in C99 mode, so we allow the caller to turn
+   off the error about not being in C99 mode.
+*/
 
 tree
-check_for_loop_decls (location_t loc)
+check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
 {
   struct c_binding *b;
   tree one_decl = NULL_TREE;
   int n_decls = 0;
 
-  if (!flag_isoc99)
+  if (!turn_off_iso_c99_error)
     {
       static bool hint = true;
       /* If we get here, declarations have been used in a for loop without
@@ -8530,10 +8623,9 @@ build_null_declspecs (void)
   ret->storage_class = csc_none;
   ret->expr_const_operands = true;
   ret->declspecs_seen_p = false;
-  ret->type_seen_p = false;
+  ret->typespec_kind = ctsk_none;
   ret->non_sc_seen_p = false;
   ret->typedef_p = false;
-  ret->tag_defined_p = false;
   ret->explicit_signed_p = false;
   ret->deprecated_p = false;
   ret->default_int_p = false;
@@ -8617,7 +8709,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
   tree type = spec.spec;
   specs->non_sc_seen_p = true;
   specs->declspecs_seen_p = true;
-  specs->type_seen_p = true;
+  specs->typespec_kind = spec.kind;
   if (TREE_DEPRECATED (type))
     specs->deprecated_p = true;
 
@@ -9220,8 +9312,6 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
     }
   else if (TREE_CODE (type) != ERROR_MARK)
     {
-      if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
-       specs->tag_defined_p = true;
       if (spec.kind == ctsk_typeof)
        {
          specs->typedef_p = true;
@@ -9237,6 +9327,11 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
        }
       specs->type = type;
     }
+  else
+    {
+      /* Set a dummy type here to avoid warning about implicit 'int'.  */
+      specs->type = integer_type_node;
+    }
 
   return specs;
 }
@@ -9662,8 +9757,9 @@ static void
 collect_all_refs (const char *source_file)
 {
   tree t;
+  unsigned i;
 
-  for (t = all_translation_units; t; t = TREE_CHAIN (t))
+  FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
     collect_ada_nodes (BLOCK_VARS (DECL_INITIAL (t)), source_file);
 }
 
@@ -9675,8 +9771,9 @@ for_each_global_decl (void (*callback) (tree decl))
   tree t;
   tree decls;
   tree decl;
+  unsigned i;
 
-  for (t = all_translation_units; t; t = TREE_CHAIN (t))
+  FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
     { 
       decls = DECL_INITIAL (t);
       for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl))
@@ -9691,11 +9788,18 @@ void
 c_write_global_declarations (void)
 {
   tree t;
+  unsigned i;
 
   /* We don't want to do this if generating a PCH.  */
   if (pch_file)
     return;
 
+  /* Do the Objective-C stuff.  This is where all the Objective-C
+     module stuff gets generated (symtab, class/protocol/selector
+     lists etc).  */
+  if (c_dialect_objc ())
+    objc_write_global_declarations ();
+
   /* Close the external scope.  */
   ext_block = pop_scope ();
   external_scope = 0;
@@ -9727,7 +9831,7 @@ c_write_global_declarations (void)
 
   /* Process all file scopes in this compilation, and the external_scope,
      through wrapup_global_declarations and check_global_declarations.  */
-  for (t = all_translation_units; t; t = DECL_CHAIN (t))
+  FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
   c_write_global_declarations_1 (BLOCK_VARS (ext_block));
 
@@ -9740,7 +9844,7 @@ c_write_global_declarations (void)
   if (!seen_error ())
     {
       timevar_push (TV_SYMOUT);
-      for (t = all_translation_units; t; t = DECL_CHAIN (t))
+      FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
        c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
       c_write_global_declarations_2 (BLOCK_VARS (ext_block));
       timevar_pop (TV_SYMOUT);