Ian Lance Taylor - Clean up extern inline (original) (raw)

This is the mail archive of the gcc-patches@gcc.gnu.orgmailing 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]

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:

For gcc 4.3.x:

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

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]