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:
parent
a7f02c2d27
commit
4eb7fd8398
6 changed files with 142 additions and 19 deletions
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
86
gcc/c-decl.c
86
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 ("%<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))))
|
||||
|
|
|
@ -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++.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
24
gcc/testsuite/gcc.dg/inline-17.c
Normal file
24
gcc/testsuite/gcc.dg/inline-17.c
Normal 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; }
|
Loading…
Add table
Reference in a new issue