c-common.c (c_common_attributes): Add gnu_inline attribyte.

* 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.

From-SVN: r118567
This commit is contained in:
Jakub Jelinek 2006-11-08 00:01:23 +01:00 committed by Jakub Jelinek
parent a7f02c2d27
commit 4eb7fd8398
6 changed files with 142 additions and 19 deletions

View File

@ -1,3 +1,11 @@
2006-11-07 Jakub Jelinek <jakub@redhat.com>
* 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 <sje@cup.hp.com>
PR other/25028

View File

@ -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. */

View File

@ -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 ("%<gnu_inline%> 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))))

View File

@ -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++.

View File

@ -1,3 +1,7 @@
2006-11-07 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/inline-17.c: New test.
2006-11-07 Steve Ellcey <sje@cup.hp.com>
PR other/25028

View File

@ -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; }