PATCH RFA: c99 inline patch for gcc 4.2

Ian Lance Taylor iant@google.com
Mon Mar 12 04:57:00 GMT 2007


This is the gcc 4.2 version of the c99 inline patch.  This patch
backports the relevant documentation and support from mainline.  The
goal is to issue a warning for the use of inline in c99 and gnu99
mode, since the behaviour is changing in 4.3.

This does the following:

* Add option -fgnu89-inline which indicates that GNU89 style inline
  should be used.

* Reject -fno-gnu89-inline with an error.

* Define __GNUC_GNU_EXTERN_INLINE__ to indicate that GNU style inline
  is in effect.

* Add attribute "gnu_inline" for inline functions.  This makes the
  function a traditional GNU inline function.

* If we see a non-static inline function:
  + In C99 mode, issue a warning controlled by -fgnu89-inline.
  + In all cases, apply GNU89 semantics.

Comments on the warning message particularly desired.  Sample:

foo.c:1: warning: C99 inline functions are not supported; using GNU89
foo.c:1: warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute

Tested with bootstrap and testsuite run on i686-pc-linux-gnu.

OK for 4.2 branch?

Ian


gcc/ChangeLog:
2007-03-11  Ian Lance Taylor  <iant@google.com>

	* c.opt (fgnu89-inline): New option.
	* c-opts.c (c_common_post_options): Warn about -fno-gnu89-inline.
	* c-common.c (c_common_attributes): Add gnu_inline attribyte.
	(handle_gnu_inline_attribute): New static function.
	* c-decl.c (start_function): Warn if we see a non-static inline
	function in C99 mode.
	* c-cppbuiltin.c (c_cpp_builtins): Define __GNUC_GNU_INLINE__.
	* doc/invoke.texi (Option Summary): Mention -fgnu89-inline.
	(C Dialect Options): Document -fgnu89-inline.
	* doc/extend.texi (Function Attributes): Document gnu_inline.
	* doc/cpp.texi (Common Predefined Macros): Document
	__GNUC_GNU_INLINE__ and __GNUC_STDC_INLINE__.

gcc/testsuite/ChangeLog:
2007-03-11  Ian Lance Taylor  <iant@google.com>

	* gcc.dg/inline-7.c: Add -fgnu89-inline.
	* gcc.dg/inline-13.c: New test.
	* gcc.dg/inline-17.c: New test.
	* gcc.dg/inline-18.c: New test.
	* gcc.dg/inline-19.c: New test.
	* gcc.dg/inline-21.c: New test.


Index: gcc/doc/cpp.texi
===================================================================
--- gcc/doc/cpp.texi	(revision 122770)
+++ gcc/doc/cpp.texi	(working copy)
@@ -2014,6 +2014,28 @@ functions.  You should not use these mac
 sure that programs will execute with the same effect whether or not they
 are defined.  If they are defined, their value is 1.
 
+@item __GNUC_GNU_INLINE__
+GCC defines this macro if functions declared @code{inline} will be
+handled in GCC's traditional gnu89 mode.  In this mode an @code{extern
+inline} function will never be compiled as a standalone function, and
+an @code{inline} function which is neither @code{extern} nor
+@code{static} will always be compiled as a standalone function.
+
+@item __GNUC_STDC_INLINE__
+GCC defines this macro if functions declared @code{inline} will be
+handled according to the ISO C99 standard.  In this mode an
+@code{extern inline} function will always be compiled as a standalone
+externally visible function, and an @code{inline} function which is
+neither @code{extern} nor @code{static} will never be compiled as a
+standalone function.
+
+If this macro is defined, GCC supports the @code{gnu_inline} function
+attribute as a way to always get the gnu89 behaviour.  Support for
+this and @code{__GNUC_GNU_INLINE__} was added in GCC 4.1.3.  If
+neither macro is defined, an older version of GCC is being used:
+@code{inline} functions will be compiled in gnu89 mode, and the
+@code{gnu_inline} function attribute will not be recognized.
+
 @item __CHAR_UNSIGNED__
 GCC defines this macro if and only if the data type @code{char} is
 unsigned on the target machine.  It exists to cause the standard header
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 122770)
+++ gcc/doc/extend.texi	(working copy)
@@ -1581,8 +1581,8 @@ attributes are currently defined for fun
 @code{format}, @code{format_arg}, @code{no_instrument_function},
 @code{section}, @code{constructor}, @code{destructor}, @code{used},
 @code{unused}, @code{deprecated}, @code{weak}, @code{malloc},
-@code{alias}, @code{warn_unused_result}, @code{nonnull}
-and @code{externally_visible}.  Several other
+@code{alias}, @code{warn_unused_result}, @code{nonnull},
+@code{gnu_inline} and @code{externally_visible}.  Several other
 attributes are defined for functions on particular target systems.  Other
 attributes, including @code{section} are supported for variables declarations
 (@pxref{Variable Attributes}) and for types (@pxref{Type Attributes}).
@@ -1620,6 +1620,45 @@ Generally, functions are not inlined unl
 For functions declared inline, this attribute inlines the function even
 if no optimization level was specified.
 
+@item gnu_inline
+@cindex @code{gnu_inline} function attribute
+This attribute should be used with a function which is also declared
+with the @code{inline} keyword.  It directs GCC to treat the function
+as if it were defined in gnu89 mode even when compiling in C99 or
+gnu99 mode.
+
+If the function is declared @code{extern}, then this definition of the
+function is used only for inlining.  In no case is the function
+compiled as a standalone function, not even if you take its address
+explicitly.  Such an address becomes an external reference, as if you
+had only declared the function, and had not defined it.  This has
+almost the effect of a macro.  The way to use this is to put a
+function definition in a header file with this attribute, and put
+another copy of the function, without @code{extern}, in a library
+file.  The definition in the header file will cause most calls to the
+function to be inlined.  If any uses of the function remain, they will
+refer to the single copy in the library.  Note that the two
+definitions of the functions need not be precisely the same, although
+if they do not have the same effect your program may behave oddly.
+
+If the function is neither @code{extern} nor @code{static}, then the
+function is compiled as a standalone function, as well as being
+inlined where possible.
+
+This is how GCC traditionally handled functions declared
+@code{inline}.  Since ISO C99 specifies a different semantics for
+@code{inline}, this function attribute is provided as a transition
+measure and as a useful feature in its own right.  This attribute is
+available in GCC 4.1.3 and later.  It is available if either of the
+preprocessor macros @code{__GNUC_GNU_INLINE__} or
+@code{__GNUC_STDC_INLINE__} are defined.  @xref{Inline,,An Inline
+Function is As Fast As a Macro}.
+
+Note that since the first version of GCC to support C99 inline
+semantics is 4.3, earlier versions of GCC which accept this attribute
+effectively ignore it.  Its only effect is to disable warnings about
+using inline functions in C99 mode.
+
 @cindex @code{flatten} function attribute
 @item flatten
 Generally, inlining into a function is limited.  For a function marked with
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 122770)
+++ gcc/doc/invoke.texi	(working copy)
@@ -164,7 +164,8 @@ in the following sections.
 
 @item C Language Options
 @xref{C Dialect Options,,Options Controlling C Dialect}.
-@gccoptlist{-ansi  -std=@var{standard}  -aux-info @var{filename} @gol
+@gccoptlist{-ansi  -std=@var{standard}  -fgnu89-inline @gol
+-aux-info @var{filename} @gol
 -fno-asm  -fno-builtin  -fno-builtin-@var{function} @gol
 -fhosted  -ffreestanding -fopenmp -fms-extensions @gol
 -trigraphs  -no-integrated-cpp  -traditional  -traditional-cpp @gol
@@ -1212,6 +1213,26 @@ the @code{inline} keyword in ISO C99) ar
 @xref{Standards,,Language Standards Supported by GCC}, for details of
 these standard versions.
 
+@item -fgnu89-inline
+@opindex fgnu89-inline
+The option @option{-fgnu89-inline} tells GCC to use the traditional
+GNU semantics for @code{inline} functions when in C99 mode.
+@xref{Inline,,An Inline Function is As Fast As a Macro}.  This option
+is accepted and ignored by GCC versions 4.1.3 up to but not including
+4.3.  In GCC versions 4.3 and later it changes the behavior of GCC in
+C99 mode.  Using this option is roughly equivalent to adding the
+@code{gnu_inline} function attribute to all inline functions
+(@pxref{Function Attributes}).
+
+The option @option{-fno-gnu89-inline} is not supported in versions of
+GCC before 4.3.  It will be supported only in C99 or gnu99 mode, not
+in C89 or gnu89 mode.
+
+The preprocesor macros @code{__GNUC_GNU_INLINE__} and
+@code{__GNUC_STDC_INLINE__} may be used to check which semantics are
+in effect for @code{inline} functions.  @xref{Common Predefined
+Macros,,,cpp.info,The C Preprocessor}.
+
 @item -aux-info @var{filename}
 @opindex aux-info
 Output to the given filename prototyped declarations for all functions
Index: gcc/c-cppbuiltin.c
===================================================================
--- gcc/c-cppbuiltin.c	(revision 122770)
+++ gcc/c-cppbuiltin.c	(working copy)
@@ -484,6 +484,8 @@ c_cpp_builtins (cpp_reader *pfile)
   /* Misc.  */
   builtin_define_with_value ("__VERSION__", version_string, 1);
 
+  cpp_define (pfile, "__GNUC_GNU_INLINE__");
+
   /* Definitions for LP64 model.  */
   if (TYPE_PRECISION (long_integer_type_node) == 64
       && POINTER_SIZE == 64
Index: gcc/testsuite/gcc.dg/inline-17.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-17.c	(revision 0)
+++ gcc/testsuite/gcc.dg/inline-17.c	(revision 0)
@@ -0,0 +1,24 @@
+/* Test __attribute__((gnu_inline)).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler-not "func2" } } */
+/* { dg-final { scan-assembler "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+
+#if __STDC_VERSION__ >= 199901L
+# define inline __attribute__((gnu_inline)) inline
+#endif
+
+extern inline int func1 (void) { return 0; }
+inline int func1 (void) { return 1; }
+
+extern int func2 (void);
+extern inline int func2 (void) { return 2; }
+
+inline int func3 (void);
+inline int func3 (void) { return 3; }
+
+extern int func4 (void);
+extern inline int func4 (void) { return 4; }
+int func4 (void) { return 5; }
Index: gcc/testsuite/gcc.dg/inline-19.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-19.c	(revision 0)
+++ gcc/testsuite/gcc.dg/inline-19.c	(revision 0)
@@ -0,0 +1,28 @@
+/* Test -fgnu89-extern-inline.  */
+/* { dg-do compile } */
+/* { dg-options "-fgnu89-inline" } */
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler-not "func2" } } */
+/* { dg-final { scan-assembler "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+
+#ifndef __GNUC_GNU_INLINE__
+#error __GNUC_GNU_INLINE__ is not defined
+#endif
+
+#ifdef __GNUC_STDC_INLINE__
+#error __GNUC_STDC_INLINE__ is defined
+#endif
+
+extern inline int func1 (void) { return 0; }
+inline int func1 (void) { return 1; }
+
+extern int func2 (void);
+extern inline int func2 (void) { return 2; }
+
+inline int func3 (void);
+inline int func3 (void) { return 3; }
+
+extern int func4 (void);
+extern inline int func4 (void) { return 4; }
+int func4 (void) { return 5; }
Index: gcc/testsuite/gcc.dg/inline-21.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-21.c	(revision 0)
+++ gcc/testsuite/gcc.dg/inline-21.c	(revision 0)
@@ -0,0 +1,4 @@
+/* Test -fno-gnu89-inline.  */
+/* { dg-do compile } */
+/* { dg-options "-fno-gnu89-inline" } */
+/* { dg-error "is not supported" "" { target *-*-* } 0 } */
Index: gcc/testsuite/gcc.dg/inline-7.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-7.c	(revision 122770)
+++ gcc/testsuite/gcc.dg/inline-7.c	(working copy)
@@ -1,6 +1,6 @@
 /* Test duplicate inline, gnu99 mode.  */
 /* Origin: Joseph Myers <jsm@polyomino.org.uk> */
 /* { dg-do compile } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99 -fgnu89-inline" } */
 
 inline inline void f (void) {}
Index: gcc/testsuite/gcc.dg/inline-18.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-18.c	(revision 0)
+++ gcc/testsuite/gcc.dg/inline-18.c	(revision 0)
@@ -0,0 +1,28 @@
+/* Test -fgnu89-extern-inline.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -fgnu89-inline" } */
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler-not "func2" } } */
+/* { dg-final { scan-assembler "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+
+#ifndef __GNUC_GNU_INLINE__
+#error __GNUC_GNU_INLINE__ is not defined
+#endif
+
+#ifdef __GNUC_STDC_INLINE__
+#error __GNUC_STDC_INLINE__ is defined
+#endif
+
+extern inline int func1 (void) { return 0; }
+inline int func1 (void) { return 1; }
+
+extern int func2 (void);
+extern inline int func2 (void) { return 2; }
+
+inline int func3 (void);
+inline int func3 (void) { return 3; }
+
+extern int func4 (void);
+extern inline int func4 (void) { return 4; }
+int func4 (void) { return 5; }
Index: gcc/testsuite/gcc.dg/inline-13.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-13.c	(revision 0)
+++ gcc/testsuite/gcc.dg/inline-13.c	(revision 0)
@@ -0,0 +1,15 @@
+/* Verify basic C99 inline functionality.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+static inline int func2 (void)
+{
+}
+
+inline int dontgenerate1 (void)
+{ /* { dg-warning "inline" "" } */
+  func2 ();
+  return 1;
+}
+
+extern inline int func1 (void) { return 1; }  /* { dg-warning "inline" "" } */
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 122770)
+++ gcc/c-decl.c	(working copy)
@@ -6139,6 +6139,29 @@ start_function (struct c_declspecs *decl
      except for defining how to inline.  So set DECL_EXTERNAL in that case.  */
   DECL_EXTERNAL (decl1) = current_extern_inline;
 
+  /* C99 specified different behaviour for non-static inline
+     functions, compared with the traditional GNU behaviour.  We don't
+     support the C99 behaviour, but we do warn about non-static inline
+     functions here.  The warning can be disabled via an explicit use
+     of -fgnu89-inline, or by using the gnu_inline attribute.  */
+  if (DECL_DECLARED_INLINE_P (decl1)
+      && TREE_PUBLIC (decl1)
+      && flag_isoc99
+      && flag_gnu89_inline != 1
+      && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1)))
+    {
+      static bool info = false;
+
+      warning (0, "C99 inline functions are not supported; using GNU89");
+      if (!info)
+	{
+	  warning (0,
+		   "to disable this warning use -fgnu89-inline or "
+		   "the gnu_inline function attribute");
+	  info = true;
+	}
+    }
+
   /* This function exists in static storage.
      (This does not mean `static' in the C sense!)  */
   TREE_STATIC (decl1) = 1;
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 122770)
+++ gcc/c.opt	(working copy)
@@ -531,6 +531,10 @@ fgnu-runtime
 ObjC ObjC++
 Generate code for GNU runtime environment
 
+fgnu89-inline
+C Var(flag_gnu89_inline) Init(-1)
+Use traditional GNU semantics for inline functions
+
 fguiding-decls
 C++ ObjC++
 
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c	(revision 122770)
+++ gcc/c-opts.c	(working copy)
@@ -1004,6 +1004,12 @@ c_common_post_options (const char **pfil
   if (flag_inline_functions)
     flag_inline_trees = 2;
 
+  /* We recognize -fgnu89-inline in preparation for 4.3 where the
+     option will be meaningful.  Here we just reject
+     -fno-gnu89-inline, since we don't support it.  */
+  if (!flag_gnu89_inline)
+    error ("-fno-gnu89-inline is not supported");
+
   /* If we are given more than one input file, we must use
      unit-at-a-time mode.  */
   if (num_in_fnames > 1)
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 122770)
+++ gcc/c-common.c	(working copy)
@@ -505,6 +505,8 @@ static tree handle_noreturn_attribute (t
 static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
 static tree handle_always_inline_attribute (tree *, tree, tree, int,
 					    bool *);
+static tree handle_gnu_inline_attribute (tree *, tree, tree, int,
+					 bool *);
 static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
 static tree handle_used_attribute (tree *, tree, tree, int, bool *);
 static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
@@ -573,6 +575,8 @@ const struct attribute_spec c_common_att
 			      handle_noinline_attribute },
   { "always_inline",          0, 0, true,  false, false,
 			      handle_always_inline_attribute },
+  { "gnu_inline",             0, 0, true,  false, false,
+			      handle_gnu_inline_attribute },
   { "flatten",                0, 0, true,  false, false,
 			      handle_flatten_attribute },
   { "used",                   0, 0, true,  false, false,
@@ -4213,6 +4217,29 @@ handle_always_inline_attribute (tree *no
   return NULL_TREE;
 }
 
+/* Handle a "gnu_inline" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_gnu_inline_attribute (tree *node, tree name,
+			     tree ARG_UNUSED (args),
+			     int ARG_UNUSED (flags),
+			     bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
+    {
+      /* Do nothing else, just set the attribute.  We'll get at
+	 it later with lookup_attribute.  */
+    }
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "flatten" attribute; arguments as in
    struct attribute_spec.handler.  */
 



More information about the Gcc-patches mailing list