This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH RFC: gcc 4.1 extern inline patch, take 2
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 08 Feb 2007 21:49:52 -0800
- Subject: PATCH RFC: gcc 4.1 extern inline patch, take 2
Here is the second version of my extern inline patch for gcc 4.1.
This takes into account all the comments I received on the last one.
The basic idea is to ease the transition to C99 extern inline
semantics. This is to be done by:
1) Adding an option -fgnu89-extern-inline to control the semantics
being used.
2) Adding the gnu_inline attribute, to provide traditional GNU
semantics even in C99 mode.
3) Defining preprocessor macros to indicate which mode is being used
for extern inline functions.
4) In gcc 4.1.x, x >= 3, give a warning about uses of "extern inline"
in c99 mode.
5) In gcc 4.2, give a warning about uses of "extern inline" in gnu89
mode, and give an error for them in c99 mode.
6) In gcc 4.3 and above, use c99 semantics for "extern inline" in
gnu89 and c99 modes.
In detail, the current proposal is:
gcc 4.1 branch:
* Add option -fgnu89-extern-inline which indicates that GNU style
"extern inline" should be used.
* Reject -fno-gnu89-extern-inline with an error.
* Define __GNUC_GNU_EXTERN_INLINE__ to indicate that GNU style "extern
inline" is in used.
* Add attribute "gnu_inline" for inline functions. This makes the
function a traditional GNU "extern inline" function.
* If we see an "extern inline" function:
+ Apply GNU semantics.
+ If -std=c99 is used, but not -std=gnu99, and not
-fgnu89-extern-inline, issue a pedantic warning.
gcc 4.2 branch:
* Add option -fgnu89-extern-inline which indicates that GNU style
"extern inline" should be used.
* Reject -fno-gnu89-extern-inline with an error.
* Define __GNUC_GNU_EXTERN_INLINE__ to indicate that GNU style "extern
inline" is in used.
* Add attribute "gnu_inline" for inline functions. This makes the
function a traditional GNU "extern inline" function.
* If we see an "extern inline" function:
+ If -fgnu89-extern-inline is used, apply GNU semantics.
+ Else, if the declaration is in a system header, apply GNU
semantics.
+ Else, if -std=c99 is used, but not -std=gnu99, issue an error.
+ Else, if -std=gnu99 is used, issue a warning controlled by
-Wdeprecated, and apply GNU semantics.
+ Else, apply GNU semantics with no warning.
mainline:
* Add option -fgnu89-extern-inline which indicates that GNU style
"extern inline" should be used.
* If -fgnu89-extern-inline is used, or if none of -std=c99, -std=gnu99
or -fno-gnu89-extern-inline is used, define
__GNUC_GNU_EXTERN_INLINE__. Otherwise, define
__GNUC_STDC_EXTERN_INLINE__.
* The attribute "gnu_inline" is already implemented for inline
functions. This makes the function a traditional GNU "extern
inline" function.
* If we see an "extern inline" function:
+ If -fgnu89-extern-inline is used, apply GNU semantics.
+ Else, if -fno-gnu89-extern-inline is used, apply C99 semantics.
+ Else, if -std=c99 or -std=gnu99 is used, apply C99 semantics.
+ Else, apply GNU semantics.
* Note that in this proposal -f[no-]gnu89-extern-inline overrides
-std=XX.
This patch implements the above proposal for gcc 4.1. If this is
accepted, I will follow up with patches for gcc 4.2 and mainline.
Bootstrapped and tested on i686-pc-linux-gnu.
Ian
gcc/ChangeLog:
2007-02-08 Ian Lance Taylor <iant@google.com>
* c.opt (fgnu89-extern-inline): New option.
* c-opts.c (c_common_handle_option): Give an error for
-fno-gnu89-extern-inline.
* c-common.c (c_common_attribute_table): Add "gnu_inline".
(handle_gnu_inline_attribute): New static function.
* c-decl.c (start_function): In -std=c99 mode, pedwarn about
extern inline. Support the gnu_inline attribute.
* c-cppbuiltin.c (c_cpp_builtins): Define
__GNUC_GNU_EXTERN_INLINE__.
* toplev.h: If __GNUC_GNU_EXTERN_INLINE or
__GNUC_STD_EXTERN_INLINE is defined, use __attribute__
((gnu_inline)) with inline definitions of floor_log2 and
exact_log2.
gcc/testsuite/ChangeLog:
2007-02-08 Ian Lance Taylor <iant@google.com>
* gcc.dg/inline-13.c: New file.
* gcc.dg/inline-14.c: New file.
* gcc.dg/inline-15.c: New file.
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi (revision 121738)
+++ gcc/doc/extend.texi (working copy)
@@ -1566,6 +1566,29 @@ 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 definition of the function is used only for inlining. In no case
+is the function compiled on its own, not even if you refer to 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 it is to put a
+function definition in a header file with this attribute, and put
+another copy of the function, without the attribute, 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.
+
+This is how GCC traditionally handled functions declared @code{extern
+inline}. Since ISO C99 specifies a different semantics for
+@code{extern 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 @code{__GNUC_GNU_EXTERN_INLINE__} or
+@code{__GNUC_STD_EXTERN_INLINE__} are defined. @xref{Inline,,An
+Inline Function is As Fast As a Macro}.
+
@cindex @code{flatten} function attribute
@item flatten
Generally, inlining into a function is limited. For a function marked with
@@ -3601,6 +3624,17 @@ existing semantics will remain available
specified, but eventually the default will be @option{-std=gnu99} and
that will implement the C99 semantics, though it does not do so yet.)
+For convenience in porting programs, GCC automatically defines
+preprocessor macros to indicate which semantics are being used for
+@code{extern inline} functions. @code{__GNUC_GNU_EXTERN_INLINE__}
+will be defined for the traditional GNU definition (an @code{extern
+inline} function is like a macro). @code{__GNUC_STDC_EXTERN_INLINE__}
+will be defined for the ISO C99 definition (an @code{extern inline}
+function is always compiled with a standalone definition visible from
+outside the file). If neither macro is defined, an older version of
+GCC is being used, and is effectively the same as if
+@code{__GNUC_GNU_EXTERN_INLINE__} is defined.
+
GCC does not inline any functions when not optimizing unless you specify
the @samp{always_inline} attribute for the function, like this:
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 121738)
+++ gcc/doc/invoke.texi (working copy)
@@ -166,7 +166,7 @@ in the following sections.
-trigraphs -no-integrated-cpp -traditional -traditional-cpp @gol
-fallow-single-precision -fcond-mismatch @gol
-fsigned-bitfields -fsigned-char @gol
--funsigned-bitfields -funsigned-char}
+-funsigned-bitfields -funsigned-char -fgnu89-extern-inline}
@item C++ Language Options
@xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
@@ -1314,6 +1314,17 @@ C compiler. They are now only supported
The preprocessor continues to support a pre-standard mode. See the GNU
CPP manual for details.
+@item -fno-gnu89-extern-inline
+@opindex fno-gnu89-extern-inline
+The option @option{-fgnu89-extern-inline} tells GCC to use the
+traditional GNU semantics for @code{extern inline}, even when in C99
+mode. @xref{Inline,,An Inline Function is As Fast As a Macro}. GCC
+versions before 4.3 do not support C99 @code{extern line} semantics,
+so for them @option{-fno-gnu89-extern-inline} is not supported and
+produces an error. @option{-fgnu89-extern-inline} is recognized, but
+has no effect, as GCC versions before 4.3 always use the traditional
+GNU semantics.
+
@item -fcond-mismatch
@opindex fcond-mismatch
Allow conditional expressions with mismatched types in the second and
Index: gcc/toplev.h
===================================================================
--- gcc/toplev.h (revision 121738)
+++ gcc/toplev.h (working copy)
@@ -1,5 +1,5 @@
/* toplev.h - Various declarations for functions found in toplev.c
- Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007
Free Software Foundation, Inc.
This file is part of GCC.
@@ -171,13 +171,21 @@ extern int floor_log2 (
# define CTZ_HWI __builtin_ctz
# endif
-extern inline int
+# if defined (__GNUC_GNU_EXTERN_INLINE__) || defined (__GNUC_STDC_EXTERN_INLINE)
+# define EXTERN_INLINE inline
+# define ATTRIBUTE_GNU_INLINE __attribute__ ((__gnu_inline__))
+# else
+# define EXTERN_INLINE extern inline
+# define ATTRIBUTE_GNU_INLINE
+# endif
+
+EXTERN_INLINE ATTRIBUTE_GNU_INLINE int
floor_log2 (unsigned HOST_WIDE_INT x)
{
return x ? HOST_BITS_PER_WIDE_INT - 1 - (int) CLZ_HWI (x) : -1;
}
-extern inline int
+EXTERN_INLINE ATTRIBUTE_GNU_INLINE int
exact_log2 (unsigned HOST_WIDE_INT x)
{
return x == (x & -x) && x ? (int) CTZ_HWI (x) : -1;
Index: gcc/c-cppbuiltin.c
===================================================================
--- gcc/c-cppbuiltin.c (revision 121738)
+++ gcc/c-cppbuiltin.c (working copy)
@@ -1,5 +1,5 @@
/* Define builtin-in macros for the C family front ends.
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
This file is part of GCC.
@@ -393,6 +393,8 @@ c_cpp_builtins (cpp_reader *pfile)
/* Misc. */
builtin_define_with_value ("__VERSION__", version_string, 1);
+ cpp_define (pfile, "__GNUC_GNU_EXTERN_INLINE__");
+
/* Definitions for LP64 model. */
if (TYPE_PRECISION (long_integer_type_node) == 64
&& POINTER_SIZE == 64
Index: gcc/testsuite/gcc.dg/inline-15.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-15.c (revision 0)
+++ gcc/testsuite/gcc.dg/inline-15.c (revision 0)
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+/* We can redefine a gnu_inline function. */
+
+inline __attribute__ ((gnu_inline)) int foo () { return 0; }
+int foo () { return 1; }
Index: gcc/testsuite/gcc.dg/inline-14.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-14.c (revision 0)
+++ gcc/testsuite/gcc.dg/inline-14.c (revision 0)
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu89-extern-inline" } */
+
+/* We can redefine a GNU extern inline function. */
+
+extern inline int foo () { return 0; }
+int foo () { return 1; }
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,6 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic" } */
+
+/* In isoc99 mode we give a warning for "extern inline". */
+
+extern inline int foo () { return 0; } /* { dg-warning "inline" } */
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c (revision 121738)
+++ 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.
@@ -6022,6 +6022,23 @@ 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 defined "extern inline" in a way which is incompatible with
+ the traditional GNU definition of "extern inline". The C99
+ definition is supported in gcc 4.3. */
+
+ if (current_extern_inline
+ && !flag_gnu89_extern_inline
+ && flag_isoc99
+ && flag_iso)
+ pedwarn ("ISO C99 definition of %<extern inline%> is not supported");
+
+ if (lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1)))
+ {
+ /* Setting DECL_EXTERNAL gives the traditional GNU definition of
+ "extern inline". */
+ DECL_EXTERNAL (decl1) = 1;
+ }
+
/* 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 121738)
+++ gcc/c.opt (working copy)
@@ -532,6 +532,10 @@ fgnu-runtime
ObjC ObjC++
Generate code for GNU runtime environment
+fgnu89-extern-inline
+C Var(flag_gnu89_extern_inline)
+Use traditional GNU definition for \"extern inline\" functions
+
fguiding-decls
C++ ObjC++
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c (revision 121738)
+++ gcc/c-opts.c (working copy)
@@ -1,5 +1,6 @@
/* C/ObjC/C++ command line option handling.
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Contributed by Neil Booth.
This file is part of GCC.
@@ -686,6 +687,11 @@ c_common_handle_option (size_t scode, co
flag_next_runtime = !value;
break;
+ case OPT_fgnu89_extern_inline:
+ if (!value)
+ error ("-fno-gnu89-extern-inline is not supported");
+ break;
+
case OPT_fhandle_exceptions:
warning (0, "-fhandle-exceptions has been renamed -fexceptions (and is now on by default)");
flag_exceptions = value;
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c (revision 121738)
+++ gcc/c-common.c (working copy)
@@ -1,6 +1,6 @@
/* Subroutines shared by all languages that are variants of C.
Copyright (C) 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.
@@ -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,
@@ -4216,6 +4220,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)
+ {
+ /* 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. */