aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-05-16 11:37:43 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2019-05-16 11:37:43 +0200
commit4b8e35f1b1df60633aeb0bf37ea9f6311f2132b9 (patch)
tree3f485b6b1cf328ccbe3d102f53c45fc88878f488 /gcc/calls.c
parent86c23d9314c4081c13ebf629fd3393de4e316bf6 (diff)
downloadgcc-4b8e35f1b1df60633aeb0bf37ea9f6311f2132b9.zip
gcc-4b8e35f1b1df60633aeb0bf37ea9f6311f2132b9.tar.gz
gcc-4b8e35f1b1df60633aeb0bf37ea9f6311f2132b9.tar.bz2
re PR fortran/90329 (Incompatibility between gfortran and C lapack calls)
PR fortran/90329 * tree-core.h (struct tree_decl_common): Document decl_nonshareable_flag for PARM_DECLs. * tree.h (DECL_HIDDEN_STRING_LENGTH): Define. * calls.c (expand_call): Don't try tail call if caller has any DECL_HIDDEN_STRING_LENGTH PARM_DECLs that are or might be passed on the stack and callee needs to pass any arguments on the stack. * tree-streamer-in.c (unpack_ts_decl_common_value_fields): Use else if instead of series of mutually exclusive ifs. Handle DECL_HIDDEN_STRING_LENGTH for PARM_DECLs. * tree-streamer-out.c (pack_ts_decl_common_value_fields): Likewise. * trans-decl.c (create_function_arglist): Set DECL_HIDDEN_STRING_LENGTH on hidden string length PARM_DECLs if len is constant. From-SVN: r271285
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index 6b22e7a..c8a4268 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -3628,6 +3628,28 @@ expand_call (tree exp, rtx target, int ignore)
|| dbg_cnt (tail_call) == false)
try_tail_call = 0;
+ /* Workaround buggy C/C++ wrappers around Fortran routines with
+ character(len=constant) arguments if the hidden string length arguments
+ are passed on the stack; if the callers forget to pass those arguments,
+ attempting to tail call in such routines leads to stack corruption.
+ Avoid tail calls in functions where at least one such hidden string
+ length argument is passed (partially or fully) on the stack in the
+ caller and the callee needs to pass any arguments on the stack.
+ See PR90329. */
+ if (try_tail_call && maybe_ne (args_size.constant, 0))
+ for (tree arg = DECL_ARGUMENTS (current_function_decl);
+ arg; arg = DECL_CHAIN (arg))
+ if (DECL_HIDDEN_STRING_LENGTH (arg) && DECL_INCOMING_RTL (arg))
+ {
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, DECL_INCOMING_RTL (arg), NONCONST)
+ if (MEM_P (*iter))
+ {
+ try_tail_call = 0;
+ break;
+ }
+ }
+
/* If the user has marked the function as requiring tail-call
optimization, attempt it. */
if (must_tail_call)