From 89523fa34645df9a2a2cfb8b1409000449bc43e4 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 7 Nov 2006 23:01:23 +0000 Subject: * c-common.c (c_common_attributes): Add gnu_inline attribyte. (handle_gnu_inline_attribute): New function. * c-decl.c (diagnose_mismatched_decls): Handle gnu_inline attribute. (merge_decls, start_decl, start_function): Likewise. * doc/extend.texi: Document gnu_inline attribute. * gcc.dg/inline-17.c: New test. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@118567 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 8 ++++ gcc/c-common.c | 27 +++++++++++++ gcc/c-decl.c | 86 ++++++++++++++++++++++++++++++++-------- gcc/doc/extend.texi | 12 ++++-- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/inline-17.c | 24 +++++++++++ 6 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/inline-17.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1d01bd5c484..38eed0db8bd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2006-11-07 Jakub Jelinek + + * c-common.c (c_common_attributes): Add gnu_inline attribyte. + (handle_gnu_inline_attribute): New function. + * c-decl.c (diagnose_mismatched_decls): Handle gnu_inline attribute. + (merge_decls, start_decl, start_function): Likewise. + * doc/extend.texi: Document gnu_inline attribute. + 2006-11-07 Steve Ellcey PR other/25028 diff --git a/gcc/c-common.c b/gcc/c-common.c index 47cda1b6413..0603da65bc1 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -510,6 +510,8 @@ static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); 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 *); @@ -578,6 +580,8 @@ const struct attribute_spec c_common_attribute_table[] = 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, @@ -4268,6 +4272,29 @@ handle_always_inline_attribute (tree *node, tree name, 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. */ diff --git a/gcc/c-decl.c b/gcc/c-decl.c index a49b88b199b..80f1a1a621f 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -63,7 +63,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #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=gnuc99, and to 0 if you want + when you specify -std=c99 or -std=gnu99, and to 0 if you want behaviour compatible with the nonstandard semantics implemented by GCC 2.95 through 4.2. */ #define WANT_C99_INLINE_SEMANTICS 1 @@ -1339,7 +1339,16 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, unit. */ if ((!DECL_EXTERN_INLINE (olddecl) || DECL_EXTERN_INLINE (newdecl) - || flag_isoc99) +#if WANT_C99_INLINE_SEMANTICS + || (flag_isoc99 + && (!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)) { error ("redefinition of %q+D", newdecl); @@ -1399,6 +1408,23 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, warned = true; } } + + /* Make sure gnu_inline attribute is either not present, or + present on all inline decls. */ + if (DECL_DECLARED_INLINE_P (olddecl) + && DECL_DECLARED_INLINE_P (newdecl)) + { + bool newa = lookup_attribute ("gnu_inline", + DECL_ATTRIBUTES (newdecl)) != NULL; + bool olda = lookup_attribute ("gnu_inline", + DECL_ATTRIBUTES (olddecl)) != NULL; + if (newa != olda) + { + error ("% attribute present on %q+D", + newa ? newdecl : olddecl); + error ("%Jbut not here", newa ? olddecl : newdecl); + } + } } else if (TREE_CODE (newdecl) == VAR_DECL) { @@ -1531,9 +1557,9 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, mode and can get it right? Definitely don't complain if the decls are in different translation units. - C99 permits this, so don't warn in that case. (The function - may not be inlined everywhere in function-at-a-time mode, but - we still shouldn't warn.) */ + C99 permits this, so don't warn in that case. (The function + may not be inlined everywhere in function-at-a-time mode, but + we still shouldn't warn.) */ if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl) && same_translation_unit_p (olddecl, newdecl) && ! flag_isoc99) @@ -1767,17 +1793,19 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) } #if WANT_C99_INLINE_SEMANTICS - /* In c99, 'extern' declaration before (or after) 'inline' means this - function is not DECL_EXTERNAL. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL - && (DECL_DECLARED_INLINE_P (newdecl) - || DECL_DECLARED_INLINE_P (olddecl)) - && (!DECL_DECLARED_INLINE_P (newdecl) - || !DECL_DECLARED_INLINE_P (olddecl) - || !DECL_EXTERNAL (olddecl)) - && DECL_EXTERNAL (newdecl) - && flag_isoc99) - DECL_EXTERNAL (newdecl) = 0; + /* 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 + && (DECL_DECLARED_INLINE_P (newdecl) + || DECL_DECLARED_INLINE_P (olddecl)) + && (!DECL_DECLARED_INLINE_P (newdecl) + || !DECL_DECLARED_INLINE_P (olddecl) + || !DECL_EXTERNAL (olddecl)) + && DECL_EXTERNAL (newdecl) + && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl))) + DECL_EXTERNAL (newdecl) = 0; #endif /* WANT_C99_INLINE_SEMANTICS */ if (DECL_EXTERNAL (newdecl)) @@ -3292,6 +3320,20 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, /* 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 + && TREE_CODE (decl) == FUNCTION_DECL + && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl))) + { + if (declspecs->storage_class == csc_auto && current_scope != file_scope) + ; + 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))) { @@ -6053,6 +6095,18 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, 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 + && 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); if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1)))) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 9ec4460bb6a..1579b94a970 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1581,8 +1581,8 @@ attributes are currently defined for functions on all targets: @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,11 @@ Generally, functions are not inlined unless optimization is specified. 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 on an inline declaration results in the old GNU C89 +inline behavior even in the ISO C99 mode. + @cindex @code{flatten} function attribute @item flatten Generally, inlining into a function is limited. For a function marked with @@ -3802,7 +3807,8 @@ also direct GCC to try to integrate all ``simple enough'' functions 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}, another when +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++. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 22e43d0f23a..29dfb3f80c3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2006-11-07 Jakub Jelinek + + * gcc.dg/inline-17.c: New test. + 2006-11-07 Steve Ellcey PR other/25028 diff --git a/gcc/testsuite/gcc.dg/inline-17.c b/gcc/testsuite/gcc.dg/inline-17.c new file mode 100644 index 00000000000..235ad8b001e --- /dev/null +++ b/gcc/testsuite/gcc.dg/inline-17.c @@ -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; } -- cgit v1.2.3