OSDN Git Service

* libF77/signal_.c (G77_signal_0): Make return type sig_pf as well.
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 13d6887..5774f75 100644 (file)
@@ -1,5 +1,5 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1988, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -454,6 +454,10 @@ int flag_no_nonansi_builtin;
 
 int flag_traditional;
 
+/* Nonzero means that we have builtin functions, and main is an int */
+
+int flag_hosted = 1;
+
 /* Nonzero means to allow single precision math even if we're generally
    being traditional.  */
 int flag_allow_single_precision = 0;
@@ -545,9 +549,14 @@ int warn_parentheses;
 
 int warn_missing_braces;
 
-/* Warn about comparison of signed and unsigned values.  */
+/* Warn if main is suspicious.  */
+
+int warn_main;
+
+/* Warn about comparison of signed and unsigned values.
+   If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified.  */
 
-int warn_sign_compare;
+int warn_sign_compare = -1;
 
 /* Nonzero means `$' can be in an identifier.  */
 
@@ -571,6 +580,19 @@ c_decode_option (p)
     }
   else if (!strcmp (p, "-fallow-single-precision"))
     flag_allow_single_precision = 1;
+  else if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
+    {
+      flag_hosted = 1;
+      flag_no_builtin = 0;
+    }
+  else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted"))
+    {
+      flag_hosted = 0;
+      flag_no_builtin = 1;
+      /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */
+      if (warn_main == 2)
+       warn_main = 0;
+    }
   else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional"))
     {
       flag_traditional = 0;
@@ -702,6 +724,10 @@ c_decode_option (p)
     ; /* cpp handles this one.  */
   else if (!strcmp (p, "-Wno-trigraphs"))
     ; /* cpp handles this one.  */
+  else if (!strcmp (p, "-Wundef"))
+    ; /* cpp handles this one.  */
+  else if (!strcmp (p, "-Wno-undef"))
+    ; /* cpp handles this one.  */
   else if (!strcmp (p, "-Wimport"))
     ; /* cpp handles this one.  */
   else if (!strcmp (p, "-Wno-import"))
@@ -710,6 +736,10 @@ c_decode_option (p)
     warn_missing_braces = 1;
   else if (!strcmp (p, "-Wno-missing-braces"))
     warn_missing_braces = 0;
+  else if (!strcmp (p, "-Wmain"))
+    warn_main = 1;
+  else if (!strcmp (p, "-Wno-main"))
+    warn_main = 0;
   else if (!strcmp (p, "-Wsign-compare"))
     warn_sign_compare = 1;
   else if (!strcmp (p, "-Wno-sign-compare"))
@@ -729,7 +759,9 @@ c_decode_option (p)
       warn_char_subscripts = 1;
       warn_parentheses = 1;
       warn_missing_braces = 1;
-      warn_sign_compare = 1;
+      /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
+        it off only if it's not explicit.  */
+      warn_main = 2;
     }
   else
     return 0;
@@ -1003,7 +1035,7 @@ poplevel (keep, reverse, functionbody)
        if (DECL_ABSTRACT_ORIGIN (decl) != 0
            && DECL_ABSTRACT_ORIGIN (decl) != decl)
          TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
-       else
+       else if (DECL_SAVED_INSNS (decl) != 0)
          {
            push_function_context ();
            output_inline_function (decl);
@@ -1324,6 +1356,10 @@ pushtag (name, type)
      tagged type.  */
 
   TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
+
+  /* An approximation for now, so we can tell this is a function-scope tag.
+     This will be updated in poplevel.  */
+  TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
 }
 \f
 /* Handle when a new declaration NEWDECL
@@ -1906,6 +1942,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
            DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
+         if (DECL_INLINE (newdecl))
+           DECL_ABSTRACT_ORIGIN (newdecl) = olddecl;
        }
     }
   if (different_binding_level)
@@ -2811,7 +2849,7 @@ init_decl_processing ()
   tree traditional_ptr_type_node;
   /* Data types of memcpy and strlen.  */
   tree memcpy_ftype, memset_ftype, strlen_ftype;
-  tree void_ftype_any;
+  tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr;
   int wchar_type_size;
   tree temp;
   tree array_domain_type;
@@ -3127,6 +3165,11 @@ init_decl_processing ()
                                                            sizetype,
                                                            endlink))));
 
+  ptr_ftype_void = build_function_type (ptr_type_node, endlink);
+  ptr_ftype_ptr
+    = build_function_type (ptr_type_node,
+                          tree_cons (NULL_TREE, ptr_type_node, endlink));
+
   builtin_function ("__builtin_constant_p", default_function_type,
                    BUILT_IN_CONSTANT_P, NULL_PTR);
 
@@ -3144,6 +3187,42 @@ init_decl_processing ()
                                                    endlink)),
                    BUILT_IN_FRAME_ADDRESS, NULL_PTR);
 
+  builtin_function ("__builtin_aggregate_incoming_address",
+                   build_function_type (ptr_type_node, NULL_TREE),
+                   BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR);
+
+  /* Hooks for the DWARF 2 __throw routine.  */
+  builtin_function ("__builtin_unwind_init",
+                   build_function_type (void_type_node, endlink),
+                   BUILT_IN_UNWIND_INIT, NULL_PTR);
+  builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
+  builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
+  builtin_function ("__builtin_dwarf_fp_regnum",
+                   build_function_type (unsigned_type_node, endlink),
+                   BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
+  builtin_function ("__builtin_dwarf_reg_size", int_ftype_int,
+                   BUILT_IN_DWARF_REG_SIZE, NULL_PTR);             
+  builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
+                   BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
+  builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
+                   BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
+  builtin_function ("__builtin_set_return_addr_reg",
+                   build_function_type (void_type_node, 
+                                        tree_cons (NULL_TREE,
+                                                   ptr_type_node,
+                                                   endlink)),
+                   BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
+  builtin_function ("__builtin_eh_stub", ptr_ftype_void,
+                   BUILT_IN_EH_STUB, NULL_PTR);
+  builtin_function
+    ("__builtin_set_eh_regs",
+     build_function_type (void_type_node,
+                         tree_cons (NULL_TREE, ptr_type_node,
+                                    tree_cons (NULL_TREE,
+                                               type_for_mode (ptr_mode, 0),
+                                               endlink))),
+     BUILT_IN_SET_EH_REGS, NULL_PTR);
+
   builtin_function ("__builtin_alloca",
                    build_function_type (ptr_type_node,
                                         tree_cons (NULL_TREE,
@@ -3536,6 +3615,9 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   /* The corresponding pop_obstacks is in finish_decl.  */
   push_obstacks_nochange ();
 
+  if (warn_main && !strcmp (IDENTIFIER_POINTER (declarator), "main"))
+    warning_with_decl (decl, "`%s' is usually a function");
+
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
        If not, set INITIALIZED to zero, which will indirectly
@@ -4066,12 +4148,6 @@ complete_array_type (type, initial_value, do_default)
       TYPE_DOMAIN (type) = build_index_type (maxindex);
       if (!TREE_TYPE (maxindex))
        TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
-#if 0 /* I took out this change
-        together with the change in build_array_type. --rms  */
-      change_main_variant (type,
-                          build_array_type (TREE_TYPE (type),
-                                            TYPE_DOMAIN (type)));
-#endif
     }
 
   /* Lay out the type now that we can get the real answer.  */
@@ -4277,10 +4353,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   if (type == 0)
     {
-      if (funcdef_flag && warn_return_type
-         && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
-                           | (1 << (int) RID_SIGNED) | (1 << (int) RID_UNSIGNED))))
-       warn_about_return_type = 1;
+      if (! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
+                        | (1 << (int) RID_SIGNED)
+                        | (1 << (int) RID_UNSIGNED))))
+       {
+         /* C9x will probably require a diagnostic here.
+            For now, issue a warning if -Wreturn-type and this is a function,
+            or if -Wimplicit; prefer the former warning since it is more
+            explicit.  */
+         if ((warn_implicit || warn_return_type) && funcdef_flag)
+           warn_about_return_type = 1;
+         else if (warn_implicit)
+           warning ("type defaults to `int' in declaration of `%s'", name);
+       }
+
       defaulted_int = 1;
       type = integer_type_node;
     }
@@ -4290,7 +4376,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   /* Long double is a special combination.  */
 
-  if ((specbits & 1 << (int) RID_LONG)
+  if ((specbits & 1 << (int) RID_LONG) && ! longlong
       && TYPE_MAIN_VARIANT (type) == double_type_node)
     {
       specbits &= ~ (1 << (int) RID_LONG);
@@ -4304,11 +4390,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     {
       int ok = 0;
 
-      if (TREE_CODE (type) != INTEGER_TYPE)
-       error ("long, short, signed or unsigned invalid for `%s'", name);
-      else if ((specbits & 1 << (int) RID_LONG)
-              && (specbits & 1 << (int) RID_SHORT))
-       error ("long and short specified together for `%s'", name);
+      if ((specbits & 1 << (int) RID_LONG)
+         && (specbits & 1 << (int) RID_SHORT))
+       error ("both long and short specified for `%s'", name);
       else if (((specbits & 1 << (int) RID_LONG)
                || (specbits & 1 << (int) RID_SHORT))
               && explicit_char)
@@ -4316,10 +4400,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (((specbits & 1 << (int) RID_LONG)
                || (specbits & 1 << (int) RID_SHORT))
               && TREE_CODE (type) == REAL_TYPE)
-       error ("long or short specified with floating type for `%s'", name);
+       {
+         static int already = 0;
+
+         error ("long or short specified with floating type for `%s'", name);
+         if (! already && ! pedantic)
+           {
+             error ("the only valid combination is `long double'");
+             already = 1;
+           }
+       }
       else if ((specbits & 1 << (int) RID_SIGNED)
               && (specbits & 1 << (int) RID_UNSIGNED))
-       error ("signed and unsigned given together for `%s'", name);
+       error ("both signed and unsigned specified for `%s'", name);
+      else if (TREE_CODE (type) != INTEGER_TYPE)
+       error ("long, short, signed or unsigned invalid for `%s'", name);
       else
        {
          ok = 1;
@@ -4985,6 +5080,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            && ! DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ANSI C forbids const or volatile functions");
 
+       if (pedantic
+           && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
+           && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (decl)))
+               || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (decl))))
+           && ! DECL_IN_SYSTEM_HEADER (decl))
+         pedwarn ("ANSI C forbids const or volatile void function return type");
+
        if (volatilep
            && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
          warning ("`noreturn' function returns non-void value");
@@ -5324,7 +5426,7 @@ parmlist_tags_warning ()
       enum tree_code code = TREE_CODE (TREE_VALUE (elt));
       /* An anonymous union parm type is meaningful as a GNU extension.
         So don't warn for that.  */
-      if (code == UNION_TYPE && !pedantic)
+      if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic)
        continue;
       if (TREE_PURPOSE (elt) != 0)
        warning ("`%s %s' declared inside parameter list",
@@ -6201,6 +6303,67 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
   if (current_function_decl != 0)
     TREE_PUBLIC (decl1) = 0;
 
+  /* Warn for unlikely, improbable, or stupid declarations of `main'. */
+  if (warn_main
+      && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
+    {
+      tree args;
+      int argct = 0;
+
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
+          != integer_type_node)
+       pedwarn_with_decl (decl1, "return type of `%s' is not `int'");
+
+      for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
+          args = TREE_CHAIN (args))
+       {
+         tree type = args ? TREE_VALUE (args) : 0;
+
+         if (type == void_type_node)
+           break;
+
+         ++argct;
+         switch (argct)
+           {
+           case 1:
+             if (TYPE_MAIN_VARIANT (type) != integer_type_node)
+               pedwarn_with_decl (decl1,
+                                  "first argument of `%s' should be `int'");
+             break;
+
+           case 2:
+             if (TREE_CODE (type) != POINTER_TYPE
+                 || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
+                 || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
+                     != char_type_node))
+               pedwarn_with_decl (decl1,
+                              "second argument of `%s' should be `char **'");
+             break;
+
+           case 3:
+             if (TREE_CODE (type) != POINTER_TYPE
+                 || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
+                 || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
+                     != char_type_node))
+               pedwarn_with_decl (decl1,
+                  "third argument of `%s' should probably be `char **'");
+             break;
+           }
+       }
+
+      /* It is intentional that this message does not mention the third
+        argument, which is warned for only pedantically, because it's
+        blessed by mention in an appendix of the standard. */
+      if (argct > 0 && (argct < 2 || argct > 3))
+       pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments");
+
+      if (argct == 3 && pedantic)
+       pedwarn_with_decl (decl1, "third argument of `%s' is deprecated");
+
+      if (! TREE_PUBLIC (decl1))
+       pedwarn_with_decl (decl1, "`%s' is normally a non-static function");
+    }
+
   /* Record the decl so that the function name is defined.
      If we already have a decl for this name, and it is a FUNCTION_DECL,
      use the old decl.  */
@@ -6857,7 +7020,16 @@ finish_function (nested)
     {
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
          != integer_type_node)
-       pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
+       {
+         /* You would expect the sense of this test to be the other way
+            around, but if warn_main is set, we will already have warned,
+            so this would be a duplicate.  This is the warning you get
+            in some environments even if you *don't* ask for it, because
+            these are environments where it may be more of a problem than
+            usual.  */
+         if (! warn_main)
+           pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
+       }
       else
        {
 #ifdef DEFAULT_MAIN_RETURN