* 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
+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
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 *);
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,
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. */
#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
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);
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)
{
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)
}
#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))
/* 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)))
{
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))))
@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}).
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
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++.
+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
--- /dev/null
+/* 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; }