OSDN Git Service

PR c/39556
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 26 Apr 2009 13:40:19 +0000 (13:40 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 26 Apr 2009 13:40:19 +0000 (13:40 +0000)
* c-tree.h (enum c_inline_static_type): New.
(record_inline_static): Declare.
* c-decl.c (struct c_inline_static, c_inline_statics,
record_inline_static, check_inline_statics): New.
(pop_file_scope): Call check_inline_statics.
(start_decl): Call record_inline_static instead of pedwarning
directly for static in inline function.
* c-typeck.c (build_external_ref): Call record_inline_static
instead of pedwarning directly for static referenced in inline
function.

testsuite:
* gcc.dg/inline-34.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146800 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-decl.c
gcc/c-tree.h
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/inline-34.c [new file with mode: 0644]

index b5887e8..26e6d31 100644 (file)
@@ -1,3 +1,17 @@
+2009-04-26  Joseph Myers  <joseph@codesourcery.com>
+
+       PR c/39556
+       * c-tree.h (enum c_inline_static_type): New.
+       (record_inline_static): Declare.
+       * c-decl.c (struct c_inline_static, c_inline_statics,
+       record_inline_static, check_inline_statics): New.
+       (pop_file_scope): Call check_inline_statics.
+       (start_decl): Call record_inline_static instead of pedwarning
+       directly for static in inline function.
+       * c-typeck.c (build_external_ref): Call record_inline_static
+       instead of pedwarning directly for static referenced in inline
+       function.
+
 2009-04-26  Steven Bosscher  <steven@gcc.gnu.org>
 
        * df-scan.c (df_insn_rescan): Salvage insn's LUID if the insn is
index 7732d5a..b87fee5 100644 (file)
@@ -393,6 +393,32 @@ static GTY((deletable)) struct c_binding *binding_freelist;
   t_->to##_last = f_->from##_last;                             \
 } while (0)
 
+/* A c_inline_static structure stores details of a static identifier
+   referenced in a definition of a function that may be an inline
+   definition if no subsequent declaration of that function uses
+   "extern" or does not use "inline".  */
+
+struct GTY((chain_next ("%h.next"))) c_inline_static {
+  /* The location for a diagnostic.  */
+  location_t location;
+
+  /* The function that may be an inline definition.  */
+  tree function;
+
+  /* The object or function referenced.  */
+  tree static_decl;
+
+  /* What sort of reference this is.  */
+  enum c_inline_static_type type;
+
+  /* The next such structure or NULL.  */
+  struct c_inline_static *next;
+};
+
+/* List of static identifiers used or referenced in functions that may
+   be inline definitions.  */
+static GTY(()) struct c_inline_static *c_inline_statics;
+
 /* True means unconditionally make a BLOCK for the next scope pushed.  */
 
 static bool keep_next_level_flag;
@@ -555,6 +581,53 @@ c_finish_incomplete_decl (tree decl)
     }
 }
 \f
+/* Record that inline function FUNC contains a reference (location
+   LOC) to static DECL (file-scope or function-local according to
+   TYPE).  */
+
+void
+record_inline_static (location_t loc, tree func, tree decl,
+                     enum c_inline_static_type type)
+{
+  struct c_inline_static *csi = GGC_NEW (struct c_inline_static);
+  csi->location = loc;
+  csi->function = func;
+  csi->static_decl = decl;
+  csi->type = type;
+  csi->next = c_inline_statics;
+  c_inline_statics = csi;
+}
+
+/* Check for references to static declarations in inline functions at
+   the end of the translation unit and diagnose them if the functions
+   are still inline definitions.  */
+
+static void
+check_inline_statics (void)
+{
+  struct c_inline_static *csi;
+  for (csi = c_inline_statics; csi; csi = csi->next)
+    {
+      if (DECL_EXTERNAL (csi->function))
+       switch (csi->type)
+         {
+         case csi_internal:
+           pedwarn (csi->location, 0,
+                    "%qD is static but used in inline function %qD "
+                    "which is not static", csi->static_decl, csi->function);
+           break;
+         case csi_modifiable:
+           pedwarn (csi->location, 0,
+                    "%q+D is static but declared in inline function %qD "
+                    "which is not static", csi->static_decl, csi->function);
+           break;
+         default:
+           gcc_unreachable ();
+         }
+    }
+  c_inline_statics = NULL;
+}
+\f
 /* The Objective-C front-end often needs to determine the current scope.  */
 
 void *
@@ -944,6 +1017,8 @@ pop_file_scope (void)
      still works without it.  */
   finish_fname_decls ();
 
+  check_inline_statics ();
+
   /* This is the point to write out a PCH if we're doing that.
      In that case we do not want to do anything else.  */
   if (pch_file)
@@ -3324,9 +3399,8 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
       && !TREE_READONLY (decl)
       && DECL_DECLARED_INLINE_P (current_function_decl)
       && DECL_EXTERNAL (current_function_decl))
-    pedwarn (input_location, 0,
-            "%q+D is static but declared in inline function %qD "
-            "which is not static", decl, current_function_decl);
+    record_inline_static (input_location, current_function_decl,
+                         decl, csi_modifiable);
 
   /* Add this decl to the current scope.
      TEM may equal DECL or it may be a previous decl of the same name.  */
index 64e491e..0bfcdfe 100644 (file)
@@ -467,6 +467,18 @@ struct c_enum_contents
   int enum_overflow;
 };
 
+/* A type of reference to a static identifier in an inline
+   function.  */
+enum c_inline_static_type {
+  /* Identifier with internal linkage used in function that may be an
+     inline definition (i.e., file-scope static).  */
+  csi_internal,
+  /* Modifiable object with static storage duration defined in
+     function that may be an inline definition (i.e., local
+     static).  */
+  csi_modifiable
+};
+
 \f
 /* in c-parser.c */
 extern void c_parse_init (void);
@@ -483,6 +495,8 @@ extern int global_bindings_p (void);
 extern void push_scope (void);
 extern tree pop_scope (void);
 
+extern void record_inline_static (location_t, tree, tree,
+                                 enum c_inline_static_type);
 extern void c_init_decl_processing (void);
 extern void c_dup_lang_specific_decl (tree);
 extern void c_print_identifier (FILE *, tree, int);
index dc7d731..b2d2109 100644 (file)
@@ -2285,8 +2285,8 @@ build_external_ref (tree id, int fun, location_t loc, tree *type)
           && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
           && ! TREE_PUBLIC (ref)
           && DECL_CONTEXT (ref) != current_function_decl)
-    pedwarn (loc, 0, "%qD is static but used in inline function %qD "
-            "which is not static", ref, current_function_decl);
+    record_inline_static (loc, current_function_decl, ref,
+                         csi_internal);
 
   return ref;
 }
index 36b1a49..79f0ff7 100644 (file)
@@ -1,3 +1,8 @@
+2009-04-26  Joseph Myers  <joseph@codesourcery.com>
+
+       PR c/39556
+       * gcc.dg/inline-34.c: New test.
+
 2009-04-25  Joseph Myers  <joseph@codesourcery.com>
 
        * gcc.dg/enum-const-1.c, gcc.dg/enum-const-2.c,
diff --git a/gcc/testsuite/gcc.dg/inline-34.c b/gcc/testsuite/gcc.dg/inline-34.c
new file mode 100644 (file)
index 0000000..f257792
--- /dev/null
@@ -0,0 +1,19 @@
+/* Diagnostics for bad references to static objects and functions from
+   inline definitions must take account of declarations after the
+   definition which make it not an inline definition.  PR 39556.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+static int a1;
+inline int f1 (void) { return a1; }
+int f1 (void);
+
+static int a2;
+inline int f2 (void) { return a2; }
+extern inline int f2 (void);
+
+inline void f3 (void) { static int a3; }
+void f3 (void);
+
+inline void f4 (void) { static int a4; }
+extern inline void f4 (void);