OSDN Git Service

Index: gcc/ChangeLog
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index cfcb101..2d21a43 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001 Free Software Foundation, Inc.
+   2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -439,6 +439,18 @@ int warn_multichar = 1;
 #endif
 int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
 
+/* States indicating how grokdeclarator() should handle declspecs marked
+   with __attribute__((deprecated)).  An object declared as
+   __attribute__((deprecated)) suppresses warnings of uses of other
+   deprecated items.  */
+   
+enum deprecated_states {
+  DEPRECATED_NORMAL,
+  DEPRECATED_SUPPRESS
+};
+
+static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+
 /* Decode the string P as a language-specific option for C.
    Return the number of strings consumed.  Should not complain
    if it does not recognise the option.  */
@@ -1974,10 +1986,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          /* If either decl says `inline', this fn is inline,
             unless its definition was passed already.  */
          if (DECL_DECLARED_INLINE_P (newdecl)
-             && DECL_DECLARED_INLINE_P (olddecl) == 0)
-           DECL_DECLARED_INLINE_P (olddecl) = 1;
-
-         DECL_DECLARED_INLINE_P (newdecl) = DECL_DECLARED_INLINE_P (olddecl);
+             || DECL_DECLARED_INLINE_P (olddecl))
+           DECL_DECLARED_INLINE_P (newdecl) = 1;
 
          DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
            = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
@@ -2003,9 +2013,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
              DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
            }
        }
+
       /* Also preserve various other info from the definition.  */
-      else if (! new_is_definition)
-       DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
       if (! new_is_definition)
        {
          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
@@ -2016,12 +2025,27 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
            DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
          DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+         DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
-         if (DECL_INLINE (newdecl))
-           DECL_ABSTRACT_ORIGIN (newdecl)
-             = (different_binding_level
-                ? DECL_ORIGIN (olddecl)
-                : DECL_ABSTRACT_ORIGIN (olddecl));
+
+         /* Set DECL_INLINE on the declaration if we've got a body
+            from which to instantiate.  */
+         if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
+           {
+             DECL_INLINE (newdecl) = 1;
+             DECL_ABSTRACT_ORIGIN (newdecl)
+               = (different_binding_level
+                  ? DECL_ORIGIN (olddecl)
+                  : DECL_ABSTRACT_ORIGIN (olddecl));
+           }
+       }
+      else
+       {
+         /* If a previous declaration said inline, mark the
+            definition as inlinable.  */
+         if (DECL_DECLARED_INLINE_P (newdecl)
+             && ! DECL_UNINLINABLE (newdecl))
+           DECL_INLINE (newdecl) = 1;
        }
     }
   if (different_binding_level)
@@ -3359,11 +3383,19 @@ tree
 groktypename (typename)
      tree typename;
 {
+  tree specs, attrs;
+
   if (TREE_CODE (typename) != TREE_LIST)
     return typename;
-  return grokdeclarator (TREE_VALUE (typename),
-                        TREE_PURPOSE (typename),
-                        TYPENAME, 0);
+
+  split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+
+  typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0);
+
+  /* Apply attributes.  */
+  decl_attributes (&typename, attrs, 0);
+
+  return typename;
 }
 
 /* Return a PARM_DECL node for a given pair of specs and declarator.  */
@@ -3400,9 +3432,18 @@ start_decl (declarator, declspecs, initialized, attributes)
      int initialized;
      tree attributes;
 {
-  tree decl = grokdeclarator (declarator, declspecs,
-                             NORMAL, initialized);
+  tree decl;
   tree tem;
+  
+  /* An object declared as __attribute__((deprecated)) suppresses
+     warnings of uses of other deprecated items.  */
+  if (lookup_attribute ("deprecated", attributes))
+    deprecated_state = DEPRECATED_SUPPRESS;
+
+  decl = grokdeclarator (declarator, declspecs,
+                        NORMAL, initialized);
+  
+  deprecated_state = DEPRECATED_NORMAL;
 
   if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
       && MAIN_NAME_P (DECL_NAME (decl)))
@@ -3828,6 +3869,7 @@ build_compound_literal (type, init)
      the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT.  */
   tree decl = build_decl (VAR_DECL, NULL_TREE, type);
   tree complit;
+  tree stmt;
   DECL_EXTERNAL (decl) = 0;
   TREE_PUBLIC (decl) = 0;
   TREE_STATIC (decl) = (current_binding_level == global_binding_level);
@@ -3847,7 +3889,8 @@ build_compound_literal (type, init)
   if (type == error_mark_node || !COMPLETE_TYPE_P (type))
     return error_mark_node;
 
-  complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), decl);
+  stmt = build_stmt (DECL_STMT, decl);
+  complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
   TREE_SIDE_EFFECTS (complit) = 1;
 
   layout_decl (decl, 0);
@@ -4069,6 +4112,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     {
       tree id = TREE_VALUE (spec);
 
+      /* If the entire declaration is itself tagged as deprecated then
+         suppress reports of deprecated items.  */
+      if (id && TREE_DEPRECATED (id))
+        {
+         if (deprecated_state != DEPRECATED_SUPPRESS)
+           warn_deprecated_use (id);
+        }
+
       if (id == ridpointers[(int) RID_INT])
        explicit_int = 1;
       if (id == ridpointers[(int) RID_CHAR])
@@ -5039,16 +5090,23 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        else if (inlinep)
          {
            /* Assume that otherwise the function can be inlined.  */
-           DECL_INLINE (decl) = 1;
            DECL_DECLARED_INLINE_P (decl) = 1;
 
-           if (specbits & (1 << (int) RID_EXTERN))
-             current_extern_inline = 1;
+           /* Do not mark bare declarations as DECL_INLINE.  Doing so
+              in the presence of multiple declarations can result in
+              the abstract origin pointing between the declarations,
+              which will confuse dwarf2out.  */
+           if (initialized)
+             {
+               DECL_INLINE (decl) = 1;
+               if (specbits & (1 << (int) RID_EXTERN))
+                 current_extern_inline = 1;
+             }
          }
        /* If -finline-functions, assume it can be inlined.  This does
           two things: let the function be deferred until it is actually
           needed, and let dwarf2 know that the function is inlinable.  */
-       else if (flag_inline_trees == 2)
+       else if (flag_inline_trees == 2 && initialized)
          {
            DECL_INLINE (decl) = 1;
            DECL_DECLARED_INLINE_P (decl) = 0;
@@ -5635,11 +5693,10 @@ finish_struct (t, fieldlist, attributes)
         field widths.  */
       if (DECL_INITIAL (x))
        {
-         int max_width;
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node)
-           max_width = CHAR_TYPE_SIZE;
-         else
-           max_width = TYPE_PRECISION (TREE_TYPE (x));
+         int max_width
+           = (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node
+              ? CHAR_TYPE_SIZE : TYPE_PRECISION (TREE_TYPE (x)));
+
          if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
            error_with_decl (x, "negative width in bit-field `%s'");
          else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
@@ -5650,7 +5707,7 @@ finish_struct (t, fieldlist, attributes)
            {
              /* The test above has assured us that TREE_INT_CST_HIGH is 0.  */
              unsigned HOST_WIDE_INT width
-               = TREE_INT_CST_LOW (DECL_INITIAL (x));
+               = tree_low_cst (DECL_INITIAL (x), 1);
 
              if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
                  && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),