diff options
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r-- | gcc/c-decl.c | 86 |
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)))) |