/* If either decl says `inline', this fn is inline,
unless its definition was passed already. */
if (DECL_DECLARED_INLINE_P (newdecl)
- && DECL_DECLARED_INLINE_P (olddecl) == 0)
- DECL_DECLARED_INLINE_P (olddecl) = 1;
-
- DECL_DECLARED_INLINE_P (newdecl) = DECL_DECLARED_INLINE_P (olddecl);
+ || DECL_DECLARED_INLINE_P (olddecl))
+ DECL_DECLARED_INLINE_P (newdecl) = 1;
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
}
+
/* Also preserve various other info from the definition. */
- else if (! new_is_definition)
- DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
if (! new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+ DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
- if (DECL_INLINE (newdecl))
- DECL_ABSTRACT_ORIGIN (newdecl)
- = (different_binding_level
- ? DECL_ORIGIN (olddecl)
- : DECL_ABSTRACT_ORIGIN (olddecl));
+
+ /* Set DECL_INLINE on the declaration if we've got a body
+ from which to instantiate. */
+ if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
+ {
+ DECL_INLINE (newdecl) = 1;
+ DECL_ABSTRACT_ORIGIN (newdecl)
+ = (different_binding_level
+ ? DECL_ORIGIN (olddecl)
+ : DECL_ABSTRACT_ORIGIN (olddecl));
+ }
+ }
+ else
+ {
+ /* If a previous declaration said inline, mark the
+ definition as inlinable. */
+ if (DECL_DECLARED_INLINE_P (newdecl)
+ && ! DECL_UNINLINABLE (newdecl))
+ DECL_INLINE (newdecl) = 1;
}
}
if (different_binding_level)
else if (inlinep)
{
/* Assume that otherwise the function can be inlined. */
- DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 1;
- if (specbits & (1 << (int) RID_EXTERN))
- current_extern_inline = 1;
+ /* Do not mark bare declarations as DECL_INLINE. Doing so
+ in the presence of multiple declarations can result in
+ the abstract origin pointing between the declarations,
+ which will confuse dwarf2out. */
+ if (initialized)
+ {
+ DECL_INLINE (decl) = 1;
+ if (specbits & (1 << (int) RID_EXTERN))
+ current_extern_inline = 1;
+ }
}
/* If -finline-functions, assume it can be inlined. This does
two things: let the function be deferred until it is actually
needed, and let dwarf2 know that the function is inlinable. */
- else if (flag_inline_trees == 2)
+ else if (flag_inline_trees == 2 && initialized)
{
DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 0;
--- /dev/null
+/* Verify that DECL_INLINE gets copied between DECLs properly. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+/* { dg-final { scan-assembler-not "xyzzy" } } */
+
+/* Test that declaration followed by definition inlines. */
+static inline int xyzzy0 (int);
+static int xyzzy0 (int x) { return x; }
+int test0 (void)
+{
+ return xyzzy0 (5);
+}
+
+/* Test that definition following declaration inlines. */
+static int xyzzy1 (int);
+static inline int xyzzy1 (int x) { return x; }
+int test1 (void)
+{
+ return xyzzy1 (5);
+}
+
+/* Test that redeclaration inside a function body inlines. */
+extern inline int xyzzy2 (int x) { return x; }
+int test2 (void)
+{
+ extern int xyzzy2 (int);
+ return xyzzy2 (5);
+}