aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r--gcc/c-decl.c86
1 files changed, 70 insertions, 16 deletions
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 ("%<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))))