C99 inline function diagnostics

Geoffrey Keating gkeating@apple.com
Thu May 4 21:40:00 GMT 2006


This patch makes GCC's inline function support more like the C99
support.  To be precise, it implements 6.7.4 paragraph 3, which
basically says that you shouldn't reference static variables or
functions from an inline function definition that doesn't produce an
externally visible copy.

Note that although this patch implements the warning, the actual
syntax for inline functions is different in GCC (especially in gnu89
mode) and so the testcases are not valid C99.  However, the semantics
are equivalent.

This patch only produces a pedwarn, not an error, since obviously the
compiler can go ahead and generate code.  However, it is on by
default, for two reasons:

- I can't think of a reason why you would do this intentionally
  as compared to having one copy of the variable or function; and
- what GCC does for C is incompatible with C++.

I am holding this patch for 4.3 since 4.2 is in stage3.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/gcc-externinlinestaticwarn.patch==========
Index: ChangeLog
2006-05-03  Geoffrey Keating  <geoffk@apple.com>

	* c-typeck.c (build_external_ref): Warn about static variables
	used in extern inline functions.
	* c-decl.c (start_decl): Warn about static variables declared
	in extern inline functions.

Index: testsuite/ChangeLog
2006-05-03  Geoffrey Keating  <geoffk@apple.com>

	* gcc.dg/inline6.c: New.
	* gcc.dg/inline7.c: New.

Index: testsuite/gcc.dg/inline6.c
===================================================================
--- testsuite/gcc.dg/inline6.c	(revision 0)
+++ testsuite/gcc.dg/inline6.c	(revision 0)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu89" } */
+static int i;
+extern int j;
+extern inline int func1 (void) {
+  return i++;  /* { dg-warning "static" } */
+}
+extern inline int func2 (void) {
+  return j++;
+}
+inline int func3 (void) 
+{
+  return i++;
+}
Index: testsuite/gcc.dg/inline7.c
===================================================================
--- testsuite/gcc.dg/inline7.c	(revision 0)
+++ testsuite/gcc.dg/inline7.c	(revision 0)
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu89" } */
+extern inline void func1 (void) {
+  static int i;  /* { dg-warning "static" } */
+}
+inline void func3 (void) 
+{
+  static int i;
+}
Index: c-decl.c
===================================================================
--- c-decl.c	(revision 113500)
+++ c-decl.c	(working copy)
@@ -3275,6 +3275,17 @@
     warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
 	     decl);
 
+  /* C99 6.7.4p3: An inline definition of a function with external
+     linkage shall not contain a definition of a modifiable object
+     with static storage duration...  */
+  if (TREE_CODE (decl) == VAR_DECL
+      && current_scope != file_scope
+      && TREE_STATIC (decl)
+      && DECL_DECLARED_INLINE_P (current_function_decl)
+      && DECL_EXTERNAL (current_function_decl))
+    pedwarn ("%q+D is static but declared in inline function %qD "
+	     "which is not static", decl, current_function_decl);
+
   /* Add this decl to the current scope.
      TEM may equal DECL or it may be a previous decl of the same name.  */
   tem = pushdecl (decl);
Index: c-typeck.c
===================================================================
--- c-typeck.c	(revision 113500)
+++ c-typeck.c	(working copy)
@@ -2043,6 +2043,17 @@
       if (context != 0 && context != current_function_decl)
 	DECL_NONLOCAL (ref) = 1;
     }
+  /* C99 6.7.4p3: An inline definition of a function with external
+     linkage ... shall not contain a reference to an identifier with
+     internal linkage.  */
+  else if (current_function_decl != 0
+	   && DECL_DECLARED_INLINE_P (current_function_decl)
+	   && DECL_EXTERNAL (current_function_decl)
+	   && VAR_OR_FUNCTION_DECL_P (ref)
+	   && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
+	   && ! TREE_PUBLIC (ref))
+    pedwarn ("%H%qD is static but used in inline function %qD "
+	     "which is not static", &loc, ref, current_function_decl);
 
   return ref;
 }
============================================================



More information about the Gcc-patches mailing list