OSDN Git Service

H
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 1b040b1..91e3510 100644 (file)
@@ -151,13 +151,17 @@ tree intQI_type_node;
 tree intHI_type_node;
 tree intSI_type_node;
 tree intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
 tree intTI_type_node;
+#endif
 
 tree unsigned_intQI_type_node;
 tree unsigned_intHI_type_node;
 tree unsigned_intSI_type_node;
 tree unsigned_intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
 tree unsigned_intTI_type_node;
+#endif
 
 /* a VOID_TYPE node.  */
 
@@ -464,6 +468,10 @@ int flag_no_nonansi_builtin;
 
 int flag_traditional;
 
+/* Nonzero means use the ISO C9x dialect of C.  */
+
+int flag_isoc9x = 0;
+
 /* Nonzero means that we have builtin functions, and main is an int */
 
 int flag_hosted = 1;
@@ -498,7 +506,7 @@ int mesg_implicit_function_declaration;
    to get extra warnings from them.  These warnings will be too numerous
    to be useful, except in thoroughly ANSIfied programs.  */
 
-int warn_write_strings;
+int flag_const_strings;
 
 /* Nonzero means warn about pointer casts that can drop a type qualifier
    from the pointer target type.  */
@@ -511,6 +519,10 @@ int warn_cast_qual;
 
 int warn_bad_function_cast;
 
+/* Warn about functions which might be candidates for attribute noreturn. */
+
+int warn_missing_noreturn;
+
 /* Warn about traditional constructs whose meanings changed in ANSI C.  */
 
 int warn_traditional;
@@ -597,7 +609,7 @@ int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
    
 int
 c_decode_option (argc, argv)
-     int argc;
+     int argc ATTRIBUTE_UNUSED;
      char **argv;
 {
   int strings_processed;
@@ -640,6 +652,8 @@ c_decode_option (argc, argv)
       flag_traditional = 0;
       flag_writable_strings = 0;
     }
+  else if (!strcmp (p, "-flang-isoc9x"))
+    flag_isoc9x = 1;
   else if (!strcmp (p, "-fdollars-in-identifiers"))
     dollars_in_ident = 1;
   else if (!strcmp (p, "-fno-dollars-in-identifiers"))
@@ -713,9 +727,9 @@ c_decode_option (argc, argv)
   else if (!strcmp (p, "-Wno-long-long"))
     warn_long_long = 0;
   else if (!strcmp (p, "-Wwrite-strings"))
-    warn_write_strings = 1;
+    flag_const_strings = 1;
   else if (!strcmp (p, "-Wno-write-strings"))
-    warn_write_strings = 0;
+    flag_const_strings = 0;
   else if (!strcmp (p, "-Wcast-qual"))
     warn_cast_qual = 1;
   else if (!strcmp (p, "-Wno-cast-qual"))
@@ -724,6 +738,10 @@ c_decode_option (argc, argv)
     warn_bad_function_cast = 1;
   else if (!strcmp (p, "-Wno-bad-function-cast"))
     warn_bad_function_cast = 0;
+  else if (!strcmp (p, "-Wmissing-noreturn"))
+    warn_missing_noreturn = 1;
+  else if (!strcmp (p, "-Wno-missing-noreturn"))
+    warn_missing_noreturn = 0;
   else if (!strcmp (p, "-Wpointer-arith"))
     warn_pointer_arith = 1;
   else if (!strcmp (p, "-Wno-pointer-arith"))
@@ -942,7 +960,7 @@ kept_level_p ()
 
 void
 declare_parm_level (definition_flag)
-     int definition_flag;
+     int definition_flag ATTRIBUTE_UNUSED;
 {
   current_binding_level->parm_flag = 1;
 }
@@ -1934,6 +1952,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
 
          DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+         DECL_NO_CHECK_MEMORY_USAGE (newdecl)
+           |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
        }
 
       pop_obstacks ();
@@ -2020,7 +2040,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
          if (DECL_INLINE (newdecl))
-           DECL_ABSTRACT_ORIGIN (newdecl) = olddecl;
+           DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ORIGIN (olddecl);
        }
     }
   if (different_binding_level)
@@ -2384,7 +2404,7 @@ pushdecl (x)
                      DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
                      DECL_RESULT (x) = DECL_RESULT (oldglobal);
                      TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
-                     DECL_ABSTRACT_ORIGIN (x) = oldglobal;
+                     DECL_ABSTRACT_ORIGIN (x) = DECL_ORIGIN (oldglobal);
                    }
                  /* Inner extern decl is built-in if global one is.  */
                  if (DECL_BUILT_IN (oldglobal))
@@ -3041,8 +3061,10 @@ init_decl_processing ()
   intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
 
+#if HOST_BITS_PER_WIDE_INT >= 64
   intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
+#endif
 
   unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
@@ -3056,8 +3078,10 @@ init_decl_processing ()
   unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
 
+#if HOST_BITS_PER_WIDE_INT >= 64
   unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+#endif
 
   float_type_node = make_node (REAL_TYPE);
   TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
@@ -3291,8 +3315,8 @@ init_decl_processing ()
   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_cfa", ptr_ftype_void,
+                   BUILT_IN_DWARF_CFA, NULL_PTR);
   builtin_function ("__builtin_dwarf_fp_regnum",
                    build_function_type (unsigned_type_node, endlink),
                    BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
@@ -3302,24 +3326,16 @@ init_decl_processing ()
                    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_old", ptr_ftype_void,
-                   BUILT_IN_EH_STUB_OLD, NULL_PTR);
-  builtin_function ("__builtin_eh_stub", ptr_ftype_void,
-                   BUILT_IN_EH_STUB, NULL_PTR);
   builtin_function
-    ("__builtin_set_eh_regs",
+    ("__builtin_eh_return",
      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);
+                                               tree_cons (NULL_TREE,
+                                                          ptr_type_node,
+                                                          endlink)))),
+     BUILT_IN_EH_RETURN, NULL_PTR);
 
   builtin_function ("__builtin_alloca",
                    build_function_type (ptr_type_node,
@@ -4312,7 +4328,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   tree type = NULL_TREE;
   int longlong = 0;
   int constp;
+  int restrictp;
   int volatilep;
+  int type_quals = TYPE_UNQUALIFIED;
   int inlinep;
   int explicit_int = 0;
   int explicit_char = 0;
@@ -4622,19 +4640,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        type = build_complex_type (type);
     }
 
-  /* Set CONSTP if this declaration is `const', whether by
-     explicit specification or via a typedef.
-     Likewise for VOLATILEP.  */
-
+  /* Figure out the type qualifiers for the declaration.  There are
+     two ways a declaration can become qualified.  One is something
+     like `const int i' where the `const' is explicit.  Another is
+     something like `typedef const int CI; CI i' where the type of the
+     declaration contains the `const'.  */
   constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (type);
+  restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type);
   volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
   inlinep = !! (specbits & (1 << (int) RID_INLINE));
   if (constp > 1)
     pedwarn ("duplicate `const'");
+  if (restrictp > 1)
+    pedwarn ("duplicate `restrict'");
   if (volatilep > 1)
     pedwarn ("duplicate `volatile'");
-  if (! flag_gen_aux_info && (TYPE_READONLY (type) || TYPE_VOLATILE (type)))
+  if (! flag_gen_aux_info && (TYPE_QUALS (type)))
     type = TYPE_MAIN_VARIANT (type);
+  type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+               | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+               | (volatilep ? TYPE_QUAL_VOLATILE : 0));
 
   /* Warn if two storage classes are given. Default to `auto'.  */
 
@@ -4868,13 +4893,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             is set correctly.  */
 
          type = build_array_type (type, itype);
-         if (constp || volatilep)
-           type = c_build_type_variant (type, constp, volatilep);
+         if (type_quals)
+           type = c_build_qualified_type (type, type_quals);
 
 #if 0  /* don't clear these; leave them set so that the array type
           or the variable is itself const or volatile.  */
-         constp = 0;
-         volatilep = 0;
+         type_quals = TYPE_UNQUALIFIED;
 #endif
 
          if (size_varies)
@@ -4939,12 +4963,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                                      flag_traditional 
                                      ? NULL_TREE : arg_types);
 #endif
-         /* ANSI seems to say that `const int foo ();'
-            does not make the function foo const.  */
-         if (constp || volatilep)
-           type = c_build_type_variant (type, constp, volatilep);
-         constp = 0;
-         volatilep = 0;
+         /* Type qualifiers before the return type of the function
+            qualify the return type, not the function type.  */
+         if (type_quals)
+           type = c_build_qualified_type (type, type_quals);
+         type_quals = TYPE_UNQUALIFIED;
 
          type = build_function_type (type, arg_types);
          declarator = TREE_OPERAND (declarator, 0);
@@ -4968,12 +4991,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             for the pointer.  */
 
          if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-             && (constp || volatilep))
-           pedwarn ("ANSI C forbids const or volatile function types");
-         if (constp || volatilep)
-           type = c_build_type_variant (type, constp, volatilep);
-         constp = 0;
-         volatilep = 0;
+             && type_quals)
+           pedwarn ("ANSI C forbids qualified function types");
+         if (type_quals)
+           type = c_build_qualified_type (type, type_quals);
+         type_quals = TYPE_UNQUALIFIED;
          size_varies = 0;
 
          type = build_pointer_type (type);
@@ -4985,13 +5007,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            {
              register tree typemodlist;
              int erred = 0;
+
+             constp = 0;
+             volatilep = 0;
+             restrictp = 0;
              for (typemodlist = TREE_TYPE (declarator); typemodlist;
                   typemodlist = TREE_CHAIN (typemodlist))
                {
-                 if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
+                 tree qualifier = TREE_VALUE (typemodlist);
+
+                 if (qualifier == ridpointers[(int) RID_CONST])
                    constp++;
-                 else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
+                 else if (qualifier == ridpointers[(int) RID_VOLATILE])
                    volatilep++;
+                 else if (qualifier == ridpointers[(int) RID_RESTRICT])
+                   restrictp++;
                  else if (!erred)
                    {
                      erred = 1;
@@ -5002,6 +5032,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                pedwarn ("duplicate `const'");
              if (volatilep > 1)
                pedwarn ("duplicate `volatile'");
+             if (restrictp > 1)
+               pedwarn ("duplicate `restrict'");
+
+             type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+                           | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+                           | (volatilep ? TYPE_QUAL_VOLATILE : 0));
            }
 
          declarator = TREE_OPERAND (declarator, 0);
@@ -5028,10 +5064,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       /* Note that the grammar rejects storage classes
         in typenames, fields or parameters */
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-         && (constp || volatilep))
-       pedwarn ("ANSI C forbids const or volatile function types");
-      if (constp || volatilep)
-       type = c_build_type_variant (type, constp, volatilep);
+         && type_quals)
+       pedwarn ("ANSI C forbids qualified function types");
+      if (type_quals)
+       type = c_build_qualified_type (type, type_quals);
       decl = build_decl (TYPE_DECL, declarator, type);
       if ((specbits & (1 << (int) RID_SIGNED))
          || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
@@ -5063,10 +5099,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       /* Note that the grammar rejects storage classes
         in typenames, fields or parameters */
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-         && (constp || volatilep))
+         && type_quals)
        pedwarn ("ANSI C forbids const or volatile function types");
-      if (constp || volatilep)
-       type = c_build_type_variant (type, constp, volatilep);
+      if (type_quals)
+       type = c_build_qualified_type (type, type_quals);
       pop_obstacks ();
       return type;
     }
@@ -5106,20 +5142,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          {
            /* Transfer const-ness of array into that of type pointed to.  */
            type = TREE_TYPE (type);
-           if (constp || volatilep)
-             type = c_build_type_variant (type, constp, volatilep);
+           if (type_quals)
+             type = c_build_qualified_type (type, type_quals);
            type = build_pointer_type (type);
-           volatilep = constp = 0;
+           type_quals = TYPE_UNQUALIFIED;
            size_varies = 0;
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE)
          {
-           if (pedantic && (constp || volatilep))
-             pedwarn ("ANSI C forbids const or volatile function types");
-           if (constp || volatilep)
-             type = c_build_type_variant (type, constp, volatilep);
+           if (pedantic && type_quals)
+             pedwarn ("ANSI C forbids qualified function types");
+           if (type_quals)
+             type = c_build_qualified_type (type, type_quals);
            type = build_pointer_type (type);
-           volatilep = constp = 0;
+           type_quals = TYPE_UNQUALIFIED;
          }
 
        decl = build_decl (PARM_DECL, declarator, type);
@@ -5167,13 +5203,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            type = error_mark_node;
          }
        /* Move type qualifiers down to element of an array.  */
-       if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+       if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
          {
-           type = build_array_type (c_build_type_variant (TREE_TYPE (type),
-                                                          constp, volatilep),
+           type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+                                                            type_quals),
                                     TYPE_DOMAIN (type));
 #if 0 /* Leave the field const or volatile as well.  */
-           constp = volatilep = 0;
+           type_quals = TYPE_UNQUALIFIED;
 #endif
          }
        decl = build_decl (FIELD_DECL, declarator, type);
@@ -5212,18 +5248,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        decl = build_decl (FUNCTION_DECL, declarator, type);
        decl = build_decl_attribute_variant (decl, decl_machine_attr);
 
-       if (pedantic && (constp || volatilep)
-           && ! DECL_IN_SYSTEM_HEADER (decl))
-         pedwarn ("ANSI C forbids const or volatile functions");
+       if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
+         pedwarn ("ANSI C forbids qualified function types");
 
        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))))
+           && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
            && ! DECL_IN_SYSTEM_HEADER (decl))
-         pedwarn ("ANSI C forbids const or volatile void function return type");
+         pedwarn ("ANSI C forbids qualified void function return type");
 
-       if (volatilep
+       /* GNU C interprets a `volatile void' return type to indicate
+          that the function does not return.  */
+       if ((type_quals & TYPE_QUAL_VOLATILE)
            && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
          warning ("`noreturn' function returns non-void value");
 
@@ -5253,13 +5289,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
 
        /* Move type qualifiers down to element of an array.  */
-       if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+       if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
          {
-           type = build_array_type (c_build_type_variant (TREE_TYPE (type),
-                                                          constp, volatilep),
+           type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+                                                            type_quals),
                                     TYPE_DOMAIN (type));
 #if 0 /* Leave the variable const or volatile as well.  */
-           constp = volatilep = 0;
+           type_quals = TYPE_UNQUALIFIED;
 #endif
          }
 
@@ -5306,14 +5342,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       DECL_REGISTER (decl) = 1;
 
     /* Record constancy and volatility.  */
+    c_apply_type_quals_to_decl (type_quals, decl);
 
-    if (constp)
-      TREE_READONLY (decl) = 1;
-    if (volatilep)
-      {
-       TREE_SIDE_EFFECTS (decl) = 1;
-       TREE_THIS_VOLATILE (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.  */
@@ -6431,6 +6461,10 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
      except for defining how to inline.  So set DECL_EXTERNAL in that case.  */
   DECL_EXTERNAL (decl1) = current_extern_inline;
 
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+  SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
+#endif
+  
   /* This function exists in static storage.
      (This does not mean `static' in the C sense!)  */
   TREE_STATIC (decl1) = 1;
@@ -7186,6 +7220,12 @@ finish_function (nested)
 
   current_function_returns_null |= can_reach_end;
 
+  if (warn_missing_noreturn
+      && !TREE_THIS_VOLATILE (fndecl)
+      && !current_function_returns_null
+      && !current_function_returns_value)
+    warning ("function might be possible candidate for attribute `noreturn'");
+
   if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
     warning ("`noreturn' function does return");
   else if (warn_return_type && can_reach_end