OSDN Git Service

* c-decl.c (warn_if_shadowing): Don't warn if shadowed
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 357522b..44358a8 100644 (file)
@@ -2369,7 +2369,25 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
          DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
          C_DECL_DECLARED_BUILTIN (newdecl) = 1;
          if (new_is_prototype)
-           C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+           {
+             C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+             if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
+               {
+                 enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+                 switch (fncode)
+                   {
+                     /* If a compatible prototype of these builtin functions
+                        is seen, assume the runtime implements it with the
+                        expected semantics.  */
+                   case BUILT_IN_STPCPY:
+                     if (builtin_decl_explicit_p (fncode))
+                       set_builtin_decl_implicit_p (fncode, true);
+                     break;
+                   default:
+                     break;
+                   }
+               }
+           }
          else
            C_DECL_BUILTIN_PROTOTYPE (newdecl)
              = C_DECL_BUILTIN_PROTOTYPE (olddecl);
@@ -2516,7 +2534,10 @@ warn_if_shadowing (tree new_decl)
 
   /* Is anything being shadowed?  Invisible decls do not count.  */
   for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed)
-    if (b->decl && b->decl != new_decl && !b->invisible)
+    if (b->decl && b->decl != new_decl && !b->invisible
+       && (b->decl == error_mark_node
+           || diagnostic_report_warnings_p (global_dc,
+                                            DECL_SOURCE_LOCATION (b->decl))))
       {
        tree old_decl = b->decl;
 
@@ -2769,7 +2790,15 @@ pushdecl (tree x)
 
  skip_external_and_shadow_checks:
   if (TREE_CODE (x) == TYPE_DECL)
-    set_underlying_type (x);
+    {
+      /* So this is a typedef, set its underlying type.  */
+      set_underlying_type (x);
+
+      /* If X is a typedef defined in the current function, record it
+        for the purpose of implementing the -Wunused-local-typedefs
+        warning.  */
+      record_locally_defined_typedef (x);
+    }
 
   bind (name, x, scope, /*invisible=*/false, nested, locus);
 
@@ -3435,7 +3464,10 @@ lookup_name (tree name)
 {
   struct c_binding *b = I_SYMBOL_BINDING (name);
   if (b && !b->invisible)
-    return b->decl;
+    {
+      maybe_record_typedef_use (b->decl);
+      return b->decl;
+    }
   return 0;
 }
 
@@ -3678,6 +3710,17 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
              warned = 1;
              pending_xref_error ();
            }
+         else if (declspecs->typespec_kind != ctsk_tagdef
+                   && declspecs->typespec_kind != ctsk_tagfirstref
+                  && declspecs->alignas_p)
+           {
+             if (warned != 1)
+               pedwarn (input_location, 0,
+                        "empty declaration with %<_Alignas%> "
+                         "does not redeclare tag");
+             warned = 1;
+             pending_xref_error ();
+           }
          else
            {
              pending_invalid_xref = 0;
@@ -3714,6 +3757,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
       warned = 1;
     }
 
+  if (declspecs->noreturn_p)
+    {
+      error ("%<_Noreturn%> in empty declaration");
+      warned = 1;
+    }
+
   if (current_scope == file_scope && declspecs->storage_class == csc_auto)
     {
       error ("%<auto%> in file-scope empty declaration");
@@ -3747,6 +3796,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
       warned = 2;
     }
 
+  if (!warned && !in_system_header && declspecs->alignas_p)
+    {
+      warning (0, "useless %<_Alignas%> in empty declaration");
+      warned = 2;
+    }
+
   if (warned != 1)
     {
       if (!found_tag)
@@ -3780,6 +3835,7 @@ quals_from_declspecs (const struct c_declspecs *specs)
              && !specs->unsigned_p
              && !specs->complex_p
              && !specs->inline_p
+             && !specs->noreturn_p
              && !specs->thread_p);
   return quals;
 }
@@ -4306,7 +4362,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
     }
 
   /* If this is a function and an assembler name is specified, reset DECL_RTL
-     so we can give it its new name.  Also, update built_in_decls if it
+     so we can give it its new name.  Also, update builtin_decl if it
      was a normal built-in.  */
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
@@ -4357,6 +4413,8 @@ finish_decl (tree decl, location_t init_loc, tree init,
               when a tentative file-scope definition is seen.
               But at end of compilation, do output code for them.  */
            DECL_DEFER_OUTPUT (decl) = 1;
+         if (asmspec && C_DECL_REGISTER (decl))
+           DECL_HARD_REGISTER (decl) = 1;
          rest_of_decl_compilation (decl, true, 0);
        }
       else
@@ -4464,6 +4522,8 @@ finish_decl (tree decl, location_t init_loc, tree init,
               && C_TYPE_FIELDS_READONLY (type))
        diagnose_uninitialized_cst_member (decl, type);
     }
+
+       invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl);
 }
 
 /* Given a parsed parameter declaration, decode it into a PARM_DECL.
@@ -4854,6 +4914,7 @@ grokdeclarator (const struct c_declarator *declarator,
   tree expr_dummy;
   bool expr_const_operands_dummy;
   enum c_declarator_kind first_non_attr_kind;
+  unsigned int alignas_align = 0;
 
   if (TREE_CODE (type) == ERROR_MARK)
     return error_mark_node;
@@ -5697,6 +5758,46 @@ grokdeclarator (const struct c_declarator *declarator,
   if (bitfield)
     check_bitfield_type_and_width (&type, width, name);
 
+  /* Reject invalid uses of _Alignas.  */
+  if (declspecs->alignas_p)
+    {
+      if (storage_class == csc_typedef)
+       error_at (loc, "alignment specified for typedef %qE", name);
+      else if (storage_class == csc_register)
+       error_at (loc, "alignment specified for %<register%> object %qE",
+                 name);
+      else if (decl_context == PARM)
+       {
+         if (name)
+           error_at (loc, "alignment specified for parameter %qE", name);
+         else
+           error_at (loc, "alignment specified for unnamed parameter");
+       }
+      else if (bitfield)
+       {
+         if (name)
+           error_at (loc, "alignment specified for bit-field %qE", name);
+         else
+           error_at (loc, "alignment specified for unnamed bit-field");
+       }
+      else if (TREE_CODE (type) == FUNCTION_TYPE)
+       error_at (loc, "alignment specified for function %qE", name);
+      else if (declspecs->align_log != -1)
+       {
+         alignas_align = 1U << declspecs->align_log;
+         if (alignas_align < TYPE_ALIGN_UNIT (type))
+           {
+             if (name)
+               error_at (loc, "%<_Alignas%> specifiers cannot reduce "
+                         "alignment of %qE", name);
+             else
+               error_at (loc, "%<_Alignas%> specifiers cannot reduce "
+                         "alignment of unnamed field");
+             alignas_align = 0;
+           }
+       }
+    }
+
   /* Did array size calculations overflow?  */
 
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -5730,6 +5831,8 @@ grokdeclarator (const struct c_declarator *declarator,
        C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
       if (declspecs->inline_p)
        pedwarn (loc, 0,"typedef %q+D declared %<inline%>", decl);
+      if (declspecs->noreturn_p)
+       pedwarn (loc, 0,"typedef %q+D declared %<_Noreturn%>", decl);
 
       if (warn_cxx_compat && declarator->u.id != NULL_TREE)
        {
@@ -5761,7 +5864,7 @@ grokdeclarator (const struct c_declarator *declarator,
       /* Note that the grammar rejects storage classes in typenames
         and fields.  */
       gcc_assert (storage_class == csc_none && !threadp
-                 && !declspecs->inline_p);
+                 && !declspecs->inline_p && !declspecs->noreturn_p);
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
          && type_quals)
        pedwarn (loc, OPT_pedantic,
@@ -5858,13 +5961,15 @@ grokdeclarator (const struct c_declarator *declarator,
        DECL_ARG_TYPE (decl) = promoted_type;
        if (declspecs->inline_p)
          pedwarn (loc, 0, "parameter %q+D declared %<inline%>", decl);
+       if (declspecs->noreturn_p)
+         pedwarn (loc, 0, "parameter %q+D declared %<_Noreturn%>", decl);
       }
     else if (decl_context == FIELD)
       {
        /* Note that the grammar rejects storage classes in typenames
           and fields.  */
        gcc_assert (storage_class == csc_none && !threadp
-                   && !declspecs->inline_p);
+                   && !declspecs->inline_p && !declspecs->noreturn_p);
 
        /* Structure field.  It may not be a function.  */
 
@@ -5956,15 +6061,34 @@ grokdeclarator (const struct c_declarator *declarator,
        if (declspecs->default_int_p)
          C_FUNCTION_IMPLICIT_INT (decl) = 1;
 
-       /* Record presence of `inline', if it is reasonable.  */
+       /* Record presence of `inline' and `_Noreturn', if it is
+          reasonable.  */
        if (flag_hosted && MAIN_NAME_P (declarator->u.id))
          {
            if (declspecs->inline_p)
              pedwarn (loc, 0, "cannot inline function %<main%>");
+           if (declspecs->noreturn_p)
+             pedwarn (loc, 0, "%<main%> declared %<_Noreturn%>");
+         }
+       else
+         {
+           if (declspecs->inline_p)
+             /* Record that the function is declared `inline'.  */
+             DECL_DECLARED_INLINE_P (decl) = 1;
+           if (declspecs->noreturn_p)
+             {
+               if (!flag_isoc1x)
+                 {
+                   if (flag_isoc99)
+                     pedwarn (loc, OPT_pedantic,
+                              "ISO C99 does not support %<_Noreturn%>");
+                   else
+                     pedwarn (loc, OPT_pedantic,
+                              "ISO C90 does not support %<_Noreturn%>");
+                 }
+               TREE_THIS_VOLATILE (decl) = 1;
+             }
          }
-       else if (declspecs->inline_p)
-         /* Record that the function is declared `inline'.  */
-         DECL_DECLARED_INLINE_P (decl) = 1;
       }
     else
       {
@@ -6000,6 +6124,8 @@ grokdeclarator (const struct c_declarator *declarator,
 
        if (declspecs->inline_p)
          pedwarn (loc, 0, "variable %q+D declared %<inline%>", decl);
+       if (declspecs->noreturn_p)
+         pedwarn (loc, 0, "variable %q+D declared %<_Noreturn%>", decl);
 
        /* At file scope, an initialized extern declaration may follow
           a static declaration.  In that case, DECL_EXTERNAL will be
@@ -6052,6 +6178,13 @@ grokdeclarator (const struct c_declarator *declarator,
     /* Record constancy and volatility.  */
     c_apply_type_quals_to_decl (type_quals, decl);
 
+    /* Apply _Alignas specifiers.  */
+    if (alignas_align)
+      {
+       DECL_ALIGN (decl) = alignas_align * BITS_PER_UNIT;
+       DECL_USER_ALIGN (decl) = 1;
+      }
+
     /* If a type has volatile components, it should be stored in memory.
        Otherwise, the fact that those components are volatile
        will be ignored, and would even crash the compiler.
@@ -8156,6 +8289,9 @@ store_parm_decls (void)
   /* Initialize the RTL code for the function.  */
   allocate_struct_function (fndecl, false);
 
+  if (warn_unused_local_typedefs)
+    cfun->language = ggc_alloc_cleared_language_function ();
+
   /* Begin the statement tree for this function.  */
   DECL_SAVED_TREE (fndecl) = push_stmt_list ();
 
@@ -8263,6 +8399,10 @@ finish_function (void)
                      "parameter %qD set but not used", decl);
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
@@ -8308,6 +8448,12 @@ finish_function (void)
   if (!decl_function_context (fndecl))
     undef_nested_function = false;
 
+  if (cfun->language != NULL)
+    {
+      ggc_free (cfun->language);
+      cfun->language = NULL;
+    }
+
   /* We're leaving the context of this function, so zap cfun.
      It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
      tree_rest_of_compilation.  */
@@ -8419,9 +8565,11 @@ check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
 void
 c_push_function_context (void)
 {
-  struct language_function *p;
-  p = ggc_alloc_language_function ();
-  cfun->language = p;
+  struct language_function *p = cfun->language;
+  /* cfun->language might have been already allocated by the use of
+     -Wunused-local-typedefs.  In that case, just re-use it.  */
+  if (p == NULL)
+    cfun->language = p = ggc_alloc_cleared_language_function ();
 
   p->base.x_stmt_tree = c_stmt_tree;
   c_stmt_tree.x_cur_stmt_list
@@ -8447,7 +8595,11 @@ c_pop_function_context (void)
 
   pop_function_context ();
   p = cfun->language;
-  cfun->language = NULL;
+  /* When -Wunused-local-typedefs is in effect, cfun->languages is
+     used to store data throughout the life time of the current cfun,
+     So don't deallocate it.  */
+  if (!warn_unused_local_typedefs)
+    cfun->language = NULL;
 
   if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
       && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
@@ -8499,6 +8651,14 @@ identifier_global_value  (tree t)
   return 0;
 }
 
+/* In C, the only C-linkage public declaration is at file scope.  */
+
+tree
+c_linkage_bindings (tree name)
+{
+  return identifier_global_value (name);
+}
+
 /* Record a builtin type for C.  If NAME is non-NULL, it is the name used;
    otherwise the name is found in ridpointers from RID_INDEX.  */
 
@@ -8617,6 +8777,7 @@ build_null_declspecs (void)
   ret->expr = 0;
   ret->decl_attr = 0;
   ret->attrs = 0;
+  ret->align_log = -1;
   ret->typespec_word = cts_none;
   ret->storage_class = csc_none;
   ret->expr_const_operands = true;
@@ -8634,11 +8795,13 @@ build_null_declspecs (void)
   ret->unsigned_p = false;
   ret->complex_p = false;
   ret->inline_p = false;
+  ret->noreturn_p = false;
   ret->thread_p = false;
   ret->const_p = false;
   ret->volatile_p = false;
   ret->restrict_p = false;
   ret->saturating_p = false;
+  ret->alignas_p = false;
   ret->address_space = ADDR_SPACE_GENERIC;
   return ret;
 }
@@ -9355,6 +9518,11 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
       dupe = false;
       specs->inline_p = true;
       break;
+    case RID_NORETURN:
+      /* Duplicate _Noreturn is permitted.  */
+      dupe = false;
+      specs->noreturn_p = true;
+      break;
     case RID_THREAD:
       dupe = specs->thread_p;
       if (specs->storage_class == csc_auto)
@@ -9424,6 +9592,22 @@ declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
   return specs;
 }
 
+/* Add an _Alignas specifier (expression ALIGN, or type whose
+   alignment is ALIGN) to the declaration specifiers SPECS, returning
+   SPECS.  */
+struct c_declspecs *
+declspecs_add_alignas (struct c_declspecs *specs, tree align)
+{
+  int align_log;
+  specs->alignas_p = true;
+  if (align == error_mark_node)
+    return specs;
+  align_log = check_user_alignment (align, true);
+  if (align_log > specs->align_log)
+    specs->align_log = align_log;
+  return specs;
+}
+
 /* Combine "long", "short", "signed", "unsigned" and "_Complex" type
    specifiers with any other type specifier to determine the resulting
    type.  This is where ISO C checks on complex types are made, since