This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH RFA: c99 inline patch for gcc 4.2


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.  */
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]