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]

Clean up extern inline


Since I've been a bit lax on posting controversial patches this year,
here is one.

There is a problem with "extern inline" functions.  Historically, for
gcc, a function declared "inline" without "extern" would appear in the
.o file.  A function declared "extern inline" would never appear in
the .o file.  It was possible to define a non-inline version of a
function declared "extern inline," to provide an out-of-line
definition for cases where the function was not inlined.  The
out-of-line definition did not have to be the same as the inline
definition.  glibc, for one, takes advantage of this facility.

The C99 standard defined "extern inline" incompatibly with gcc
historical practice.  In C99, a function declared "inline" without
"extern" is not visible outside of the current object.  A function
declared "extern inline" is visible outside of the current object.

In other words, the C99 treatment of "extern inline" is essentially
the exact opposite of the traditional gcc treatment.  The equivalent
of "inline" in gnu89 is "extern inline" in c99.  "extern inline" in
gnu89 has no equivalent in c99 (because redefinition is not
permitted).  The equivalent of "inline" in c99 is "extern inline" with
no redefinition.  The equivalent of "extern inline" in c99 is "inline"
in gnu89.  Fortunately "static inline" is the same in both gnu89 and
c99.

A program which uses "inline" in gnu89 may fail in c99 with an
undefined reference in the linker.  This is easy to fix in c99 by
changing the "inline" to "extern inline".  A program which uses
"extern inline" in gnu89 may fail in c99 due to multiple definition
errors.

Understandably but unfortunately, up to and including gcc 4.2, gcc has
used gnu89 semantics for inline even when -std=c99 was explicitly
specified.

We would like to provide standard c99 semantics for inline.  We would
like to eventually make gcc use gnu99 by default, and we would like
gnu99 to use c99 semantics.  We would like to help our users make that
transition by issuing appropriate warnings and by providing mechanisms
to help them convert their programs.

Current gcc mainline provides a half-measure which is, in my outspoken
opinion, broken and should not have been committed.  With -std=c99 or
-std=gnu99 gcc mainline applies c99 semantics for inline.  In all
cases, it adds a "gnu_inline" attribute which may be used to get the
gnu89 "extern inline" semantics.  It provides a gcc source code macro
WANT_C99_INLINE_SEMANTICS which lets you change the definition in the
gcc sources, which is utterly useless.  There is no good way for user
programs to know which semantics are in effect.  There are no warnings
in pre-4.3 releases to let people know that the semantics are going to
reverse for -std=gnu99.

On to my proposed solution.

My belief is that we don't have to worry about unadorned "inline"
gnu89 functions.  I believe they are less common.  When they cause
problems, the problem will be an undefined symbol, which is reasonably
easy to understand.  The fix suitable for both gnu89 and c99 will be
to remove the "inline" qualifier.  gcc is pretty good at inlining
functions anyhow.

I am completely open to question on this, and would be interested in
different opinions.

However, I believe that we do have to worry about "extern inline"
functions.  There are programs which take advantage of the gnu89
semantics.  Besides glibc, gcc itself takes advantages of them (look
at floor_log2 in toplev.h and toplev.c).  When these cause problems,
they will cause odd compilation errors.  The only simple fix, short of
rewriting the code, is to add the gnu_inline attribute to the
function.  The gnu_inline attribute is not available before gcc 4.3.

I do not think this state of affairs is acceptable.

Here is my proposal.

For gcc 4.1.x, 4.2.x:

* Add option -fgnu-extern-inline which indicates that gnu89 "extern
  inline" should be used.

* Define __GNUC_GNU_EXTERN_INLINE__ to indicate that gnu89 "extern
  inline" is in used.

* Add attribute "gnu_inline" for inline functions.  This makes the
  function a gnu89 "extern inline" function.

* If we see an "extern inline" function:
  + If -fgnu-extern-inline is used, apply gnu89 semantics.
  + Else, if the declaration is in a system header, apply gnu89
    semantics.
  + Else, if -std=c99 is used, but not -std=gnu99, issue an error.
  + Else, issue a warning controlled by -Wdeprecated, and apply gnu89
    semantics.

For gcc 4.3.x:

* Add option -fgnu-extern-inline which indicates that gnu89 "extern
  inline" should be used.

* If -fgnu-extern-inline is used, or if neither -std=c99 nor
  -std=gnu99 is used, define __GNUC_GNU_EXTERN_INLINE__.  Otherwise,
  define __GNUC_STDC_EXTERN_INLINE__.

* Add attribute "gnu_inline" for inline functions.  This makes the
  function a traditional gnu89 "extern inline" function (already
  implemented in mainline).

* If we see an "extern inline" function:
  + If -fgnu-extern-inline is used, apply gnu89 semantics.
  + Else, if -std=c99 or -std=gnu99 is used, apply c99 semantics.
  + Else, issue a warning controlled by -Wdeprecated, and apply GNU
    semantics.

* Remove useless WANT_C99_INLINE_SEMANTICS macro from gcc source
  code.

For gcc 4.4.x (or maybe later, it depends):

* Define __GNUC_STDC_EXTERN_INLINE__ unless -fgnu-extern-inline is
  used (i.e., define it even without -std=c99 or -std=gnu99).

* If we see an "extern inline" function:
  + If -fgnu-extern-inline is used, apply GNU semantics.
  + Else, apply c99 semantics.


I welcome comments and alternative proposals.

I have attached the patch I am testing for gcc 4.1.  If this proposal
seems acceptable, I will ask permission to apply this patch to the gcc
4.1 and 4.2 active branches.

Ian

Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 121370)
+++ gcc/c-decl.c	(working copy)
@@ -6020,7 +6020,43 @@ start_function (struct c_declspecs *decl
      So normally clear DECL_EXTERNAL.
      However, `extern inline' acts like a declaration
      except for defining how to inline.  So set DECL_EXTERNAL in that case.  */
-  DECL_EXTERNAL (decl1) = current_extern_inline;
+
+  DECL_EXTERNAL (decl1) = 0;
+
+  /* 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.  To help people switch, we
+     warn about the GNU definition.  */
+
+  if (current_extern_inline)
+    {
+      if (!flag_gnu_extern_inline)
+	{
+	  static bool noted = false;
+
+	  warning (OPT_Wdeprecated,
+		   "traditional GNU %<extern inline%> is deprecated");
+
+	  if (!noted && warn_deprecated && diagnostic_report_warnings_p ())
+	    {
+	      inform ("use the %<gnu_inline%> function attribute or "
+		      "-fgnu-extern-inline");
+	      noted = true;
+	    }
+
+	  if (flag_isoc99 && flag_iso)
+	    error ("ISO C99 definition of %<extern inline%> is not supported");
+	}
+
+      DECL_EXTERNAL (decl1) = 1;
+    }
+
+  if (lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1)))
+    {
+      /* Setting DECL_EXTERNAL still 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!)  */
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 121370)
+++ gcc/c.opt	(working copy)
@@ -528,6 +528,10 @@ fgnu-keywords
 C++ ObjC++
 Recognize GNU-defined keywords
 
+fgnu-extern-inline
+C Var(flag_gnu_extern_inline)
+Use traditional GNU definition for \"extern inline\" functions
+
 fgnu-runtime
 ObjC ObjC++
 Generate code for GNU runtime environment
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 121370)
+++ 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,
@@ -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.  */
 
Index: gcc/toplev.h
===================================================================
--- gcc/toplev.h	(revision 121370)
+++ gcc/toplev.h	(working copy)
@@ -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 121370)
+++ gcc/c-cppbuiltin.c	(working copy)
@@ -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.c-torture/execute/20010119-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/20010119-1.c	(revision 121370)
+++ gcc/testsuite/gcc.c-torture/execute/20010119-1.c	(working copy)
@@ -4,7 +4,7 @@ extern void undef (void);
 void bar (unsigned x) { }
 void baz (unsigned x) { }
 
-extern inline void foo (int a, int b)
+inline __attribute__ ((gnu_inline)) void foo (int a, int b)
 {
   int c = 0;
   while (c++ < b)
Index: gcc/testsuite/gcc.c-torture/compile/20011119-2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/compile/20011119-2.c	(revision 121370)
+++ gcc/testsuite/gcc.c-torture/compile/20011119-2.c	(working copy)
@@ -4,7 +4,7 @@
 #define ASMNAME2(prefix, cname) STRING (prefix) cname
 #define STRING(x)    #x
 
-extern inline int foo (void) { return 23; }
+inline __attribute__ ((gnu_inline)) int foo (void) { return 23; }
 int bar (void) { return foo (); }
 extern int foo (void) __attribute__ ((weak, alias ("xxx")));
 int baz (void) { return foo (); }
Index: gcc/testsuite/gcc.c-torture/compile/20050328-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/compile/20050328-1.c	(revision 121370)
+++ gcc/testsuite/gcc.c-torture/compile/20050328-1.c	(working copy)
@@ -3,7 +3,7 @@ void fn2 (void *);
 void foo (void);
 void bar (void);
 
-extern inline void *
+inline __attribute__ ((gnu_inline)) void *
 baz (void)
 {
   return 0;
Index: gcc/testsuite/gcc.c-torture/compile/20021120-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/compile/20021120-1.c	(revision 121370)
+++ gcc/testsuite/gcc.c-torture/compile/20021120-1.c	(working copy)
@@ -2,8 +2,8 @@
 /* Contributed by Volker Reichelt. */
 
 /* Verify that GCC doesn't get confused by the
-   redefinition of an extern inline function. */
+   redefinition of a gnu_inline function. */
 
-extern int inline foo () { return 0; }
-extern int inline bar () { return 0; }
+int inline __attribute__ ((gnu_inline)) foo () { return 0; }
+int inline __attribute__ ((gnu_inline)) bar () { return 0; }
 static int inline bar () { return foo(); }
Index: gcc/testsuite/gcc.c-torture/compile/20021120-2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/compile/20021120-2.c	(revision 121370)
+++ gcc/testsuite/gcc.c-torture/compile/20021120-2.c	(working copy)
@@ -2,8 +2,8 @@
 /* Contributed by Volker Reichelt. */
 
 /* Verify that GCC doesn't get confused by the
-   redefinition of an extern inline function. */
+   redefinition of a gnu_inline function. */
 
-extern int inline foo () { return 0; }
-extern int inline bar () { return 0; }
+int inline __attribute__ ((gnu_inline)) foo () { return 0; }
+int inline __attribute__ ((gnu_inline)) bar () { return 0; }
 static int bar () { return foo(); }
Index: gcc/testsuite/gcc.c-torture/compile/20021204-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/compile/20021204-1.c	(revision 121370)
+++ gcc/testsuite/gcc.c-torture/compile/20021204-1.c	(working copy)
@@ -1,9 +1,9 @@
 /* PR c/7622 */
 
 /* Verify that GCC can handle the mix of
-   extern inline and nested functions. */
+   gnu_inline and nested functions. */
 
-extern inline int t()
+inline __attribute__ ((gnu_inline)) int t()
 {
   int q() { return 0; }
 
Index: gcc/testsuite/gcc.c-torture/compile/20000211-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/compile/20000211-1.c	(revision 121370)
+++ gcc/testsuite/gcc.c-torture/compile/20000211-1.c	(working copy)
@@ -5,7 +5,7 @@ typedef int Charcount;
 typedef struct lstream Lstream;
 typedef int  Lisp_Object;
 extern Lisp_Object Qnil;
-extern inline  int
+inline __attribute__ ((gnu_inline)) int
 TRUE_LIST_P (Lisp_Object object)
 {
   return ((  object  ) == (  Qnil ))  ;
Index: gcc/testsuite/gcc.c-torture/compile/20011119-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/compile/20011119-1.c	(revision 121370)
+++ gcc/testsuite/gcc.c-torture/compile/20011119-1.c	(working copy)
@@ -4,7 +4,7 @@
 #define ASMNAME2(prefix, cname) STRING (prefix) cname
 #define STRING(x)    #x
 
-extern inline int foo (void) { return 23; }
+inline __attribute__ ((gnu_inline)) int foo (void) { return 23; }
 int xxx(void) __asm__(ASMNAME ("xxx"));
 int xxx(void) { return 23; }
 extern int foo (void) __attribute__ ((weak, alias ("xxx")));
Index: gcc/testsuite/gcc.target/i386/990117-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/990117-1.c	(revision 121370)
+++ gcc/testsuite/gcc.target/i386/990117-1.c	(working copy)
@@ -2,7 +2,7 @@
 /* { dg-require-effective-target ilp32 } */
 /* { dg-options "-O2 -march=pentiumpro" } */
 
-extern __inline  double
+__inline __attribute__ ((gnu_inline)) double
 fabs (double __x)
 {
   register double __value;
Index: gcc/testsuite/gcc.target/i386/20001127-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/20001127-1.c	(revision 121370)
+++ gcc/testsuite/gcc.target/i386/20001127-1.c	(working copy)
@@ -1,7 +1,7 @@
 /* { dg-do compile { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2" } */
 
-extern inline float bar (float x)
+inline __attribute__ ((gnu_inline)) float bar (float x)
 {
   register long double value;
   asm volatile ("frndint" : "=t" (value) : "0" (x));
Index: gcc/testsuite/gcc.target/i386/20000720-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/20000720-1.c	(revision 121370)
+++ gcc/testsuite/gcc.target/i386/20000720-1.c	(working copy)
@@ -4,7 +4,7 @@
 
 extern void *foo(void *a, const void *b, unsigned c);
 
-extern inline void *
+inline __attribute__ ((gnu_inline)) void *
 bar(void *a, const void *b, unsigned c)
 {
   int d0, d1, d2;
Index: gcc/testsuite/gcc.target/i386/980709-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/980709-1.c	(revision 121370)
+++ gcc/testsuite/gcc.target/i386/980709-1.c	(working copy)
@@ -1,7 +1,7 @@
 /* { dg-do compile { target i?86-*-* x86_64-*-* } } */
 /* { dg-options -O2 } */
 
-extern __inline__ int test_and_set_bit(int nr, volatile void * addr)
+__inline__ __attribute__ ((gnu_inline)) int test_and_set_bit(int nr, volatile void * addr)
 {
 	int oldbit;
 	__asm__ __volatile__( "" 
Index: gcc/testsuite/gcc.dg/980312-1.c
===================================================================
--- gcc/testsuite/gcc.dg/980312-1.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/980312-1.c	(working copy)
@@ -2,14 +2,14 @@
 /* { dg-require-effective-target ilp32 } */
 /* { dg-options "-O2 -march=pentiumpro" } */
 
-extern __inline  double
+__inline __attribute__ ((gnu_inline)) double
 __expm1 (double __x)
 {
   double __temp;
   __temp = 1.0;
   return __temp;
 }
-extern __inline  double
+__inline __attribute__ ((gnu_inline)) double
 __sgn1 (double __x)
 {
   return __x >= 0.0 ? 1.0 : -1.0;
Index: gcc/testsuite/gcc.dg/980313-1.c
===================================================================
--- gcc/testsuite/gcc.dg/980313-1.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/980313-1.c	(working copy)
@@ -2,14 +2,14 @@
 /* { dg-require-effective-target ilp32 } */
 /* { dg-options "-O2 -march=pentiumpro" } */
 
-extern __inline  double
+__inline __attribute__ ((gnu_inline)) double
 __expm1 (double __x)
 {
   double __temp;
   __temp -= 1.0;
   return __temp;
 }
-extern __inline  double
+__inline __attribute__ ((gnu_inline)) double
 __sgn1 (double __x)
 {
   return __x >= 0.0 ? 1.0 : -1.0;
Index: gcc/testsuite/gcc.dg/pch/inline-2.hs
===================================================================
--- gcc/testsuite/gcc.dg/pch/inline-2.hs	(revision 121370)
+++ gcc/testsuite/gcc.dg/pch/inline-2.hs	(working copy)
@@ -1,4 +1,4 @@
-extern inline const char *
+inline __attribute__ ((gnu_inline)) const char *
 foo(int a)
 {
   return "abcdefgh"+a;
Index: gcc/testsuite/gcc.dg/pch/inline-2.c
===================================================================
--- gcc/testsuite/gcc.dg/pch/inline-2.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/pch/inline-2.c	(working copy)
@@ -1,11 +1,11 @@
 #include "inline-2.h"
-extern inline char
+inline __attribute__ ((gnu_inline)) char
 bar(int a)
 {
   return foo(a)[0];
 }
 
-extern inline char
+inline __attribute__ ((gnu_inline)) char
 baz(void)
 {
   return foo(0)[0];
Index: gcc/testsuite/gcc.dg/pch/inline-1.hs
===================================================================
--- gcc/testsuite/gcc.dg/pch/inline-1.hs	(revision 121370)
+++ gcc/testsuite/gcc.dg/pch/inline-1.hs	(working copy)
@@ -1,4 +1,4 @@
-extern inline int
+inline __attribute__ ((gnu_inline)) int
 foo(int a)
 {
   return a * 2 + 1;
Index: gcc/testsuite/gcc.dg/pch/except-1.hs
===================================================================
--- gcc/testsuite/gcc.dg/pch/except-1.hs	(revision 121370)
+++ gcc/testsuite/gcc.dg/pch/except-1.hs	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-options "-fexceptions" } */
-extern inline int
+inline __attribute__ ((gnu_inline)) int
 foo(int a)
 {
   return a + 1;
Index: gcc/testsuite/gcc.dg/inline2.c
===================================================================
--- gcc/testsuite/gcc.dg/inline2.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/inline2.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
 /* { dg-options "-Wall -std=gnu89" } */
 /* This test should compile successfully.  */
-extern inline int foo (void) { return 0; }
+inline __attribute__ ((gnu_inline)) int foo (void) { return 0; }
 inline int foo (void) { return 1; }
Index: gcc/testsuite/gcc.dg/inline4.c
===================================================================
--- gcc/testsuite/gcc.dg/inline4.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/inline4.c	(working copy)
@@ -3,4 +3,4 @@
 /* This testcase should fail since we're redefining foo in the same
    translation unit.  */
 int foo (void) { return 2; } /* { dg-error "previous definition of" } */
-extern inline int foo (void) { return 1; } /* { dg-error "redefinition of" } */
+inline __attribute__ ((gnu_inline)) int foo (void) { return 1; } /* { dg-error "redefinition of" } */
Index: gcc/testsuite/gcc.dg/inline-1.c
===================================================================
--- gcc/testsuite/gcc.dg/inline-1.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/inline-1.c	(working copy)
@@ -20,7 +20,7 @@ int test1 (void)
 }
 
 /* Test that redeclaration inside a function body inlines.  */
-extern inline int xyzzy2 (int x) { return x; }
+inline __attribute__ ((gnu_inline)) int xyzzy2 (int x) { return x; }
 int test2 (void)
 {
   extern int xyzzy2 (int);
Index: gcc/testsuite/gcc.dg/tree-ssa/20030807-8.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/20030807-8.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/tree-ssa/20030807-8.c	(working copy)
@@ -25,14 +25,14 @@ typedef struct dw_attr_struct
 }
 dw_attr_node;
 
-extern __inline__ enum dw_val_class
+__inline__ __attribute__ ((gnu_inline)) enum dw_val_class
 AT_class (a)
      dw_attr_ref a;
 {
   return a->dw_attr_val.val_class;
 }
 
-extern __inline__ dw_loc_list_ref
+__inline__ __attribute__ ((gnu_inline)) dw_loc_list_ref
 AT_loc_list (a)
      dw_attr_ref a;
 {
Index: gcc/testsuite/gcc.dg/tls/opt-4.c
===================================================================
--- gcc/testsuite/gcc.dg/tls/opt-4.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/tls/opt-4.c	(working copy)
@@ -10,7 +10,7 @@ struct A
 
 extern __thread const unsigned char *tcc1, **tcc2;
 
-extern inline const unsigned char ** __attribute__ ((const))
+inline __attribute__ ((gnu_inline)) const unsigned char ** __attribute__ ((const))
 foo (void)
 {
   const unsigned char **a = &tcc1;
@@ -19,7 +19,7 @@ foo (void)
   return a;
 }
 
-extern inline int
+inline __attribute__ ((gnu_inline)) int
 bar (const struct A *x)
 {
   int a;
Index: gcc/testsuite/gcc.dg/20000724-1.c
===================================================================
--- gcc/testsuite/gcc.dg/20000724-1.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/20000724-1.c	(working copy)
@@ -50,7 +50,7 @@ NT	"popl %edi; popl %esi; popl %edx; pop
 NT	"ret"
 );
 
-extern inline void do_asm(struct s * x)
+inline __attribute__ ((gnu_inline)) void do_asm(struct s * x)
 {
   asm volatile("call ___checkme" : : "c" (x) : "memory");
 }
Index: gcc/testsuite/gcc.dg/20000707-1.c
===================================================================
--- gcc/testsuite/gcc.dg/20000707-1.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/20000707-1.c	(working copy)
@@ -2,7 +2,7 @@
 /* { dg-options "-O2 -Wall" } */
 
 extern void foo(void *here);
-extern inline void bar(void)
+inline __attribute__ ((gnu_inline)) void bar(void)
 {
   __label__ here;
   foo(&&here);
Index: gcc/testsuite/gcc.dg/debug/20010207-1.c
===================================================================
--- gcc/testsuite/gcc.dg/debug/20010207-1.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/debug/20010207-1.c	(working copy)
@@ -1,4 +1,4 @@
 /* { dg-do compile } */
-extern inline int f1 (void) {return f2();}
+inline __attribute__ ((gnu_inline)) int f1 (void) {return f2();}
 int f3 (void) {return f1();}
 int f1 (void) {return 0;}
Index: gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-die3.c
===================================================================
--- gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-die3.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-die3.c	(working copy)
@@ -1,8 +1,8 @@
-/* Verify that extern inline function never actually inlined has no abstract DIE.  */
+/* Verify that gnu_inline function never actually inlined has no abstract DIE.  */
 /* { dg-do compile } */
 /* { dg-options "-O0 -gdwarf-2 -dA" } */
 /* { dg-final { scan-assembler-not "DW_AT_inline" } } */
-extern inline int t()
+inline __attribute__ ((gnu_inline)) int t()
 {
 }
 int (*q)()=t;
Index: gcc/testsuite/gcc.dg/attr-warn-unused-result.c
===================================================================
--- gcc/testsuite/gcc.dg/attr-warn-unused-result.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/attr-warn-unused-result.c	(working copy)
@@ -3,7 +3,7 @@
 /* { dg-options "-O" } */
 
 #define WUR __attribute__((warn_unused_result))
-#define WURAI __attribute__((warn_unused_result, always_inline)) inline
+#define WURAI __attribute__((warn_unused_result, always_inline, gnu_inline)) inline
 typedef WUR int (*fnt) (void);
 
 typedef struct { long i; } A;
@@ -14,24 +14,24 @@ WUR int check1 (void);
 WUR void check2 (void); /* { dg-warning "attribute ignored" } */
 int foo WUR;	  /* { dg-warning "only applies" } */
 int bar (void);
-extern WURAI int check3 (void) { return bar (); }
+WURAI int check3 (void) { return bar (); }
 WUR A check4 (void);
 WUR B check5 (void);
 WUR C check6 (void);
 A bar7 (void);
 B bar8 (void);
 C bar9 (void);
-extern WURAI A check7 (void) { return bar7 (); }
-extern WURAI B check8 (void) { return bar8 (); }
-extern WURAI C check9 (void) { return bar9 (); }
+WURAI A check7 (void) { return bar7 (); }
+WURAI B check8 (void) { return bar8 (); }
+WURAI C check9 (void) { return bar9 (); }
 /* This is useful for checking whether return value of statement
    expressions (returning int in this case) is used.  */
-extern WURAI int check_int_result (int res) { return res; }
+WURAI int check_int_result (int res) { return res; }
 #define GU(v) ({ int e = 0; (v) = bar (); if ((v) < 23) e = 14; e; })
 fnt fnptr;
 WUR int check10 (void);
 int baz (void);
-extern WURAI int check11 (void) { return baz (); }
+WURAI int check11 (void) { return baz (); }
 int k;
 
 void
Index: gcc/testsuite/gcc.dg/inline3.c
===================================================================
--- gcc/testsuite/gcc.dg/inline3.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/inline3.c	(working copy)
@@ -2,6 +2,6 @@
 /* { dg-options "-Wall -std=gnu89" } */
 /* This testcase should fail since we're redefining foo in the same
    translation unit.  */
-extern inline int foo(void) { return 0; }
+inline __attribute__ ((gnu_inline)) int foo(void) { return 0; }
 inline int foo (void) { return 1; } /* { dg-error "previous definition of" } */
 int foo (void) { return 2; } /* { dg-error "error: redefinition of" } */
Index: gcc/testsuite/gcc.dg/inline5.c
===================================================================
--- gcc/testsuite/gcc.dg/inline5.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/inline5.c	(working copy)
@@ -2,5 +2,5 @@
 /* { dg-options "-Wall -std=gnu89" } */
 /* This testcase should fail since we're redefining foo in the same
    translation unit.  */
-extern inline int foo (void) { return 2; } /* { dg-error "previous definition of" } */
-extern inline int foo (void) { return 1; } /* { dg-error "redefinition of" } */
+inline __attribute__ ((gnu_inline)) int foo (void) { return 2; } /* { dg-error "previous definition of" } */
+inline __attribute__ ((gnu_inline)) int foo (void) { return 1; } /* { dg-error "redefinition of" } */
Index: gcc/testsuite/gcc.dg/sparc-dwarf2.c
===================================================================
--- gcc/testsuite/gcc.dg/sparc-dwarf2.c	(revision 121370)
+++ gcc/testsuite/gcc.dg/sparc-dwarf2.c	(working copy)
@@ -3,7 +3,7 @@
 /* { dg-do compile { target sparc-*-linux* } } */
 /* { dg-options "-g -O1" } */
 
-extern __inline double sqrt (double __x)
+__inline __attribute__ ((gnu_inline)) double sqrt (double __x)
 {
   register double __r;
   __asm ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x));

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