This is a spurious error on nested subprograms with pragma Inline_Always and
Intrinsic, which comes from a thinko in check_inlining_for_nested_subprog, so
it's a regression present on the mainline and 5 branch.
Tested on x86_64-suse-linux, applied on the mainline and 5 branch.
2016-01-18 Eric Botcazou <ebotca...@adacore.com>
PR ada/69219
* gcc-interface/trans.c (check_inlining_for_nested_subprog): Consider
the parent function instead of the current function in order to issue
the warning or the error. Add guard for ignored functions.
2016-01-18 Eric Botcazou <ebotca...@adacore.com>
* gnat.dg/inline12.adb: New test.
--
Eric Botcazou
Index: gcc-interface/trans.c
===================================================================
--- gcc-interface/trans.c (revision 232465)
+++ gcc-interface/trans.c (working copy)
@@ -1487,7 +1487,7 @@ Pragma_to_gnu (Node_Id gnat_node)
}
-/* Check the inlining status of nested function FNDECL in the current context.
+/* Check the inline status of nested function FNDECL wrt its parent function.
If a non-inline nested function is referenced from an inline external
function, we cannot honor both requests at the same time without cloning
@@ -1495,24 +1495,27 @@ Pragma_to_gnu (Node_Id gnat_node)
We could inline it as well but it's probably better to err on the side
of too little inlining.
- This must be invoked only on nested functions present in the source code
+ This must be done only on nested functions present in the source code
and not on nested functions generated by the compiler, e.g. finalizers,
- because they are not marked inline and we don't want them to block the
- inlining of the parent function. */
+ because they may be not marked inline and we don't want them to block
+ the inlining of the parent function. */
static void
check_inlining_for_nested_subprog (tree fndecl)
{
- if (!DECL_DECLARED_INLINE_P (fndecl)
- && current_function_decl
- && DECL_EXTERNAL (current_function_decl)
- && DECL_DECLARED_INLINE_P (current_function_decl))
+ if (DECL_IGNORED_P (current_function_decl) || DECL_IGNORED_P (fndecl))
+ return;
+
+ if (DECL_DECLARED_INLINE_P (fndecl))
+ return;
+
+ tree parent_decl = decl_function_context (fndecl);
+ if (DECL_EXTERNAL (parent_decl) && DECL_DECLARED_INLINE_P (parent_decl))
{
const location_t loc1 = DECL_SOURCE_LOCATION (fndecl);
- const location_t loc2 = DECL_SOURCE_LOCATION (current_function_decl);
+ const location_t loc2 = DECL_SOURCE_LOCATION (parent_decl);
- if (lookup_attribute ("always_inline",
- DECL_ATTRIBUTES (current_function_decl)))
+ if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (parent_decl)))
{
error_at (loc1, "subprogram %q+F not marked Inline_Always", fndecl);
error_at (loc2, "parent subprogram cannot be inlined");
@@ -1524,8 +1527,8 @@ check_inlining_for_nested_subprog (tree
warning_at (loc2, OPT_Winline, "parent subprogram cannot be inlined");
}
- DECL_DECLARED_INLINE_P (current_function_decl) = 0;
- DECL_UNINLINABLE (current_function_decl) = 1;
+ DECL_DECLARED_INLINE_P (parent_decl) = 0;
+ DECL_UNINLINABLE (parent_decl) = 1;
}
}
-- PR ada/69219
-- Testcae by yuta tomino <demoon...@panathenaia.halfmoon.jp> */
-- { dg-do compile }
procedure Inline12 is
procedure NI;
procedure IA;
pragma Convention (Intrinsic, IA);
pragma Inline_Always (IA);
procedure IA is
begin
NI;
end;
procedure NI is null;
begin
IA;
end;