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]

Re: PATCH RFA: Patch for extern inline in mainline


Jakub Jelinek <jakub@redhat.com> writes:

> On Wed, Feb 28, 2007 at 10:00:54PM -0800, Ian Lance Taylor wrote:
> > I'm proposing this patch to fix the extern inline situation in
> > mainline.  This patch does the following:
> > 
> > * Adds an option -fgnu89-extern-inline which may be used in gnu99 or
> >   c99 mode to request the old GNU behaviour for inline functions.
> > 
> > * Defines either __GNUC_GNU_EXTERN_INLINE or __GNUC_STDC_EXTERN_INLINE
> >   to indicate which definition of "extern inline" is in effect.
> > 
> > * Documents all of this.
> 
> I still have a few nits:
> 1) IMHO the option should be -fgnu89-inline and the macros shouldn't
> have EXTERN_ in them either - gnu_inline attribute doesn't change just
> behavior of extern inline, but plain inline as well, and so should the
> option.  Otherwise people might be confused what it really does.
> 2) The documentation again shouldn't pretend e.g. gnu_inline implies
> extern, so should clearly say with that attribute if a function has extern
> keyword, it behaves this way and if it doesn't, behaves other way.
> 3) I think implementing internally flag_gnu89_inline by adding gnu_inline
> attribute to each inline function is too costly, it will unnecessarily
> consume memory and, furthermore, hide bugs.  gnu_inline attribute when
> present is required on all inline decls or none, if flag_gnu89_inline
> is implemented by adding that attribute transparently, suddenly GCC wouldn't
> diagnose extern inline __attribute__((gnu_inline)) int foo (void);
> extern inline int foo (void); with flag_gnu89_inline.
> Instead, I think if you set flag_gnu89_inline whenever !flag_isoc99, then
> you can just replace some uses of flag_isoc99 with !flag_gnu89_inline
> and others with a test for both flags.

Fair enough.  How about this version?

Ian


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

	* c.opt (fgnu89-inline): New option.
	* c-opts.c (c_common_post_options): Set default value for
	flag_gnu89_inline.
	* c-decl.c (WANT_C99_INLINE_SEMANTICS): Remove.
	(pop_scope): Check flag_gnu89_inline rather than flag_isoc99 for
	inline functions.
	(diagnose_mismatched_decls, merge_decls, start_decl): Likewise.
	(grokdeclarator, start_function): Likewise.
	* c-cppbuiltin.c (c_cpp_builtins): Define either
	__GNUC_GNU_INLINE__ or __GNUC_STDC_INLINE__.
	* doc/invoke.texi (Option Summary): Mention -fgnu89-inline.
	(C Dialect Options): Document -fgnu89-inline.
	* doc/extend.texi (Function Attributes): Explain what the
	gnu_inline attribute does.
	* doc/cpp.texi (Common Predefined Macros): Document
	__GNUC_GNU_INLINE__ and __GNUC_STDC_INLINE__.

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

	* gcc.dg/inline-18.c: New test.
	* gcc.dg/inline-19.c: New test.
	* gcc.dg/inline-20.c: New test.
	* gcc.dg/inline-21.c: New test.


Index: gcc/doc/cpp.texi
===================================================================
--- gcc/doc/cpp.texi	(revision 122421)
+++ 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 122421)
+++ gcc/doc/extend.texi	(working copy)
@@ -1618,8 +1618,37 @@ if no optimization level was specified.
 
 @item gnu_inline
 @cindex @code{gnu_inline} function attribute
-This attribute on an inline declaration results in the old GNU C89
-inline behavior even in the ISO C99 mode.
+This attribute should be used with a function with 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}.
 
 @cindex @code{flatten} function attribute
 @item flatten
@@ -3846,10 +3875,11 @@ also direct GCC to try to integrate all 
 into their callers with the option @option{-finline-functions}.
 
 GCC implements three different semantics of declaring a function
-inline.  One is available with @option{-std=gnu89} or when @code{gnu_inline}
-attribute is present on all inline declarations, another when
-@option{-std=c99} or @option{-std=gnu99}, and the third is used when
-compiling C++.
+inline.  One is available with @option{-std=gnu89} or
+@option{-fgnu89-inline} or when @code{gnu_inline} attribute is present
+on all inline declarations, another when @option{-std=c99} or
+@option{-std=gnu99} (without @option{-fgnu89-inline}), and the third
+is used when compiling C++.
 
 To declare a function inline, use the @code{inline} keyword in its
 declaration, like this:
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 122421)
+++ gcc/doc/invoke.texi	(working copy)
@@ -166,7 +166,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
@@ -1351,6 +1352,27 @@ 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} explicitly tells GCC to use the
+C99 semantics for @code{inline} when in C99 or gnu99 mode (i.e., it
+specifies the default behavior).  This option was first supported in
+GCC 4.3.  This option is not supported 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 122421)
+++ gcc/c-cppbuiltin.c	(working copy)
@@ -1,5 +1,6 @@
 /* Define builtin-in macros for the C family front ends.
-   Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -495,6 +496,11 @@ c_cpp_builtins (cpp_reader *pfile)
   /* Misc.  */
   builtin_define_with_value ("__VERSION__", version_string, 1);
 
+  if (flag_gnu89_inline)
+    cpp_define (pfile, "__GNUC_GNU_INLINE__");
+  else
+    cpp_define (pfile, "__GNUC_STDC_INLINE__");
+
   /* Definitions for LP64 model.  */
   if (TYPE_PRECISION (long_integer_type_node) == 64
       && POINTER_SIZE == 64
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-extern-inline.  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu89 -fno-gnu89-inline" } */
+/* { dg-error "only supported in GNU99 or C99 mode" "" { target *-*-* } 0 } */
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-20.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-20.c	(revision 0)
+++ gcc/testsuite/gcc.dg/inline-20.c	(revision 0)
@@ -0,0 +1,64 @@
+/* Test -fno-gnu89-extern-inline.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -fno-gnu89-inline" } */
+/* { dg-final { scan-assembler-not "dontgenerate" } } */
+/* { dg-final { scan-assembler "func1" } } */
+/* { dg-final { scan-assembler "func2" } } */
+/* { dg-final { scan-assembler "func3" } } */
+/* { dg-final { scan-assembler "func4" } } */
+/* { dg-final { scan-assembler "func5" } } */
+/* { dg-final { scan-assembler "func6" } } */
+/* { dg-final { scan-assembler "func7" } } */
+/* { dg-final { scan-assembler "func8" } } */
+/* { dg-final { scan-assembler "func9" } } */
+
+#ifdef __GNUC_GNU_INLINE__
+#error __GNUC_GNU_INLINE__ is defined
+#endif
+
+#ifndef __GNUC_STDC_INLINE__
+#error __GNUC_STDC_INLINE__ is not defined
+#endif
+
+inline int dontgenerate1 (void)
+{
+  return 1;
+}
+
+inline int dontgenerate2 (void);
+inline int dontgenerate2 (void)
+{
+  return 2;
+}
+
+inline int dontgenerate3 (void)
+{
+  return 3;
+}
+inline int dontgenerate3 (void);
+
+extern inline int func1 (void) { return 1; }
+
+extern inline int func2 (void);
+inline int func2 (void) { return 2; }
+
+inline int func3 (void) { return 3; }
+extern inline int func3 (void);
+
+inline int func4 (void);
+extern inline int func4 (void) { return 4; }
+
+extern inline int func5 (void) { return 5; }
+inline int func5 (void);
+
+extern int func6 (void);
+inline int func6 (void) { return 6; }
+
+inline int func7 (void) { return 7; }
+extern int func7 (void);
+
+inline int func8 (void);
+extern int func8 (void) { return 8; }
+
+extern int func9 (void) { return 9; }
+inline int func9 (void);
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 122421)
+++ gcc/c-decl.c	(working copy)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -62,12 +62,6 @@ Software Foundation, 51 Franklin Street,
 #include "langhooks-def.h"
 #include "pointer-set.h"
 
-/* Set this to 1 if you want the standard ISO C99 semantics of 'inline'
-   when you specify -std=c99 or -std=gnu99, and to 0 if you want
-   behavior compatible with the nonstandard semantics implemented by
-   GCC 2.95 through 4.2.  */
-#define WANT_C99_INLINE_SEMANTICS 1
-
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
 { NORMAL,			/* Ordinary declaration */
@@ -803,7 +797,7 @@ pop_scope (void)
 	  else if (DECL_DECLARED_INLINE_P (p)
 		   && TREE_PUBLIC (p)
 		   && !DECL_INITIAL (p)
-		   && flag_isoc99)
+		   && !flag_gnu89_inline)
 	    pedwarn ("inline function %q+D declared but never defined", p);
 
 	  goto common_symbol;
@@ -1330,15 +1324,13 @@ diagnose_mismatched_decls (tree newdecl,
 		 unit.  */
 	      if ((!DECL_EXTERN_INLINE (olddecl)
 		   || DECL_EXTERN_INLINE (newdecl)
-#if WANT_C99_INLINE_SEMANTICS
-		   || (flag_isoc99
+		   || (!flag_gnu89_inline
 		       && (!DECL_DECLARED_INLINE_P (olddecl)
 			   || !lookup_attribute ("gnu_inline",
 						 DECL_ATTRIBUTES (olddecl)))
 		       && (!DECL_DECLARED_INLINE_P (newdecl)
 			   || !lookup_attribute ("gnu_inline",
 						 DECL_ATTRIBUTES (newdecl))))
-#endif /* WANT_C99_INLINE_SEMANTICS */
 		  )
 		  && same_translation_unit_p (newdecl, olddecl))
 		{
@@ -1553,7 +1545,7 @@ diagnose_mismatched_decls (tree newdecl,
 	 we still shouldn't warn.)  */
       if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl)
 	  && same_translation_unit_p (olddecl, newdecl)
-	  && ! flag_isoc99)
+	  && flag_gnu89_inline)
 	{
 	  if (TREE_USED (olddecl))
 	    {
@@ -1783,12 +1775,11 @@ merge_decls (tree newdecl, tree olddecl,
 	}
     }
 
-#if WANT_C99_INLINE_SEMANTICS
   /* In c99, 'extern' declaration before (or after) 'inline' means this
      function is not DECL_EXTERNAL, unless 'gnu_inline' attribute
      is present.  */
   if (TREE_CODE (newdecl) == FUNCTION_DECL
-      && flag_isoc99
+      && !flag_gnu89_inline
       && (DECL_DECLARED_INLINE_P (newdecl)
 	  || DECL_DECLARED_INLINE_P (olddecl))
       && (!DECL_DECLARED_INLINE_P (newdecl)
@@ -1797,7 +1788,6 @@ merge_decls (tree newdecl, tree olddecl,
       && DECL_EXTERNAL (newdecl)
       && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl)))
     DECL_EXTERNAL (newdecl) = 0;
-#endif /* WANT_C99_INLINE_SEMANTICS */
 
   if (DECL_EXTERNAL (newdecl))
     {
@@ -3309,10 +3299,9 @@ start_decl (struct c_declarator *declara
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
   decl_attributes (&decl, attributes, 0);
 
-#if WANT_C99_INLINE_SEMANTICS
   /* Handle gnu_inline attribute.  */
   if (declspecs->inline_p
-      && flag_isoc99
+      && !flag_gnu89_inline
       && TREE_CODE (decl) == FUNCTION_DECL
       && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl)))
     {
@@ -3321,7 +3310,6 @@ start_decl (struct c_declarator *declara
       else if (declspecs->storage_class != csc_static)
 	DECL_EXTERNAL (decl) = !DECL_EXTERNAL (decl);
     }
-#endif /* WANT_C99_INLINE_SEMANTICS */
 
   if (TREE_CODE (decl) == FUNCTION_DECL
       && targetm.calls.promote_prototypes (TREE_TYPE (decl)))
@@ -4819,11 +4807,8 @@ grokdeclarator (const struct c_declarato
 	   in this file, C99 6.7.4p6.  In GNU C89, a function declared
 	   'extern inline' is an external reference.  */
 	else if (declspecs->inline_p && storage_class != csc_static)
-#if WANT_C99_INLINE_SEMANTICS
-	  DECL_EXTERNAL (decl) = (storage_class == csc_extern) == !flag_isoc99;
-#else
-	  DECL_EXTERNAL (decl) = (storage_class == csc_extern);
-#endif
+	  DECL_EXTERNAL (decl) = ((storage_class == csc_extern)
+				  == flag_gnu89_inline);
 	else
 	  DECL_EXTERNAL (decl) = !initialized;
 
@@ -6085,17 +6070,15 @@ start_function (struct c_declspecs *decl
     warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
 	     decl1);
 
-#if WANT_C99_INLINE_SEMANTICS
   /* Handle gnu_inline attribute.  */
   if (declspecs->inline_p
-      && flag_isoc99
+      && !flag_gnu89_inline
       && TREE_CODE (decl1) == FUNCTION_DECL
       && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1)))
     {
       if (declspecs->storage_class != csc_static)
 	DECL_EXTERNAL (decl1) = !DECL_EXTERNAL (decl1);
     }
-#endif /* WANT_C99_INLINE_SEMANTICS */
 
   announce_function (decl1);
 
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 122421)
+++ gcc/c.opt	(working copy)
@@ -1,5 +1,5 @@
 ; Options for the C, ObjC, C++ and ObjC++ front ends.
-; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+; Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 ;
 ; This file is part of GCC.
 ;
@@ -554,6 +554,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 122421)
+++ gcc/c-opts.c	(working copy)
@@ -1023,6 +1023,13 @@ c_common_post_options (const char **pfil
   if (flag_inline_functions)
     flag_inline_trees = 2;
 
+  /* By default we use C99 inline semantics in GNU99 or C99 mode.  C99
+     inline semantics are not supported in GNU89 or C89 mode.  */
+  if (flag_gnu89_inline == -1)
+    flag_gnu89_inline = !flag_isoc99;
+  else if (!flag_gnu89_inline && !flag_isoc99)
+    error ("-fno-gnu89-inline is only supported in GNU99 or C99 mode");
+
   /* If we are given more than one input file, we must use
      unit-at-a-time mode.  */
   if (num_in_fnames > 1)

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