From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <gentoo-commits+bounces-1733574-garchives=archives.gentoo.org@lists.gentoo.org>
Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (4096 bits))
	(No client certificate requested)
	by finch.gentoo.org (Postfix) with ESMTPS id 4BE251581EE
	for <garchives@archives.gentoo.org>; Wed, 02 Apr 2025 13:56:28 +0000 (UTC)
Received: from lists.gentoo.org (bobolink.gentoo.org [140.211.166.189])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (4096 bits))
	(No client certificate requested)
	(Authenticated sender: relay-lists.gentoo.org@gentoo.org)
	by smtp.gentoo.org (Postfix) with ESMTPSA id 35E673430FD
	for <garchives@archives.gentoo.org>; Wed, 02 Apr 2025 13:56:28 +0000 (UTC)
Received: from bobolink.gentoo.org (localhost [127.0.0.1])
	by bobolink.gentoo.org (Postfix) with ESMTP id 2EE341104B3;
	Wed, 02 Apr 2025 13:56:27 +0000 (UTC)
Received: from smtp.gentoo.org (dev.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (4096 bits))
	(No client certificate requested)
	by bobolink.gentoo.org (Postfix) with ESMTPS id 23DCD1104B3
	for <gentoo-commits@lists.gentoo.org>; Wed, 02 Apr 2025 13:56:27 +0000 (UTC)
Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (4096 bits))
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id 82FCE3430BD
	for <gentoo-commits@lists.gentoo.org>; Wed, 02 Apr 2025 13:56:26 +0000 (UTC)
Received: from localhost.localdomain (localhost [IPv6:::1])
	by oystercatcher.gentoo.org (Postfix) with ESMTP id 186272FE
	for <gentoo-commits@lists.gentoo.org>; Wed, 02 Apr 2025 13:56:25 +0000 (UTC)
From: "Sam James" <sam@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: 8bit
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Sam James" <sam@gentoo.org>
Message-ID: <1743602166.966453b927f5030c1b2e858345091d867f78b94c.sam@gentoo>
Subject: [gentoo-commits] proj/gcc-patches:master commit in: 15.0.0/gentoo/
X-VCS-Repository: proj/gcc-patches
X-VCS-Files: 15.0.0/gentoo/80_all_PR119376-tailc-Don-t-fail-musttail-calls-if-they-use-or-could.patch 15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch 15.0.0/gentoo/README.history
X-VCS-Directories: 15.0.0/gentoo/
X-VCS-Committer: sam
X-VCS-Committer-Name: Sam James
X-VCS-Revision: 966453b927f5030c1b2e858345091d867f78b94c
X-VCS-Branch: master
Date: Wed, 02 Apr 2025 13:56:25 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply
X-Archives-Salt: 4884d3b1-d6c0-4937-b7d1-4362e742900a
X-Archives-Hash: 6c349fbbe7276a2d14daefee05647850

commit:     966453b927f5030c1b2e858345091d867f78b94c
Author:     Sam James <sam <AT> gentoo <DOT> org>
AuthorDate: Wed Apr  2 13:55:41 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Wed Apr  2 13:56:06 2025 +0000
URL:        https://gitweb.gentoo.org/proj/gcc-patches.git/commit/?id=966453b9

15.0.0: update musttail patches

* Drop the "Don't fail" patch (merged upstream) for clang vs gnu::musttail
* Update eh musttail patch

Signed-off-by: Sam James <sam <AT> gentoo.org>

 ...-fail-musttail-calls-if-they-use-or-could.patch | 1124 --------------------
 15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch    |  339 +++---
 15.0.0/gentoo/README.history                       |    1 +
 3 files changed, 185 insertions(+), 1279 deletions(-)

diff --git a/15.0.0/gentoo/80_all_PR119376-tailc-Don-t-fail-musttail-calls-if-they-use-or-could.patch b/15.0.0/gentoo/80_all_PR119376-tailc-Don-t-fail-musttail-calls-if-they-use-or-could.patch
deleted file mode 100644
index d906b0c..0000000
--- a/15.0.0/gentoo/80_all_PR119376-tailc-Don-t-fail-musttail-calls-if-they-use-or-could.patch
+++ /dev/null
@@ -1,1124 +0,0 @@
-https://inbox.sourceware.org/gcc-patches/Z+JccoSNxYWZIPz5@tucnak/
-
-From 4c5f092df307ec34b842483b1702d2e173e592a5 Mon Sep 17 00:00:00 2001
-Message-ID: <4c5f092df307ec34b842483b1702d2e173e592a5.1743280205.git.sam@gentoo.org>
-From: Jakub Jelinek <jakub@redhat.com>
-Date: Tue, 25 Mar 2025 08:34:10 +0100
-Subject: [PATCH] tailc: Don't fail musttail calls if they use or could use
- local arguments, instead warn [PR119376]
-
-Hi!
-
-As discussed here and in bugzilla, [[clang::musttail]] attribute in clang
-not just strongly asks for tail call or error, but changes behavior.
-To quote:
-https://clang.llvm.org/docs/AttributeReference.html#musttail
-"The lifetimes of all local variables and function parameters end immediately
-before the call to the function.  This means that it is undefined behaviour
-to pass a pointer or reference to a local variable to the called function,
-which is not the case without the attribute.  Clang will emit a warning in
-common cases where this happens."
-
-The GCC behavior was just to error if we can't prove the musttail callee
-could not have dereferenced escaped pointers to local vars or parameters
-of the caller.  That is still the case for variables with non-trivial
-destruction (even in clang), like vars with C++ non-trivial destructors or
-variables with cleanup attribute.
-
-The following patch changes the behavior to match that of clang, for all of
-[[clang::musttail]], [[gnu::musttail]] and __attribute__((musttail)).
-
-clang 20 actually added warning for some cases of it in
-https://github.com/llvm/llvm-project/pull/109255
-but it is under -Wreturn-stack-address warning.
-
-Now, gcc doesn't have that warning, but -Wreturn-local-addr instead, and
-IMHO it is better to have this under new warnings, because this isn't about
-returning local address, but about passing it to a musttail call, or maybe
-escaping to a musttail call.  And perhaps users will appreciate they can
-control it separately as well.
-
-The patch introduces 2 new warnings.
--Wmusttail-local-addr
-which is turn on by default and warns for the always dumb cases of passing
-an address of a local variable or parameter to musttail call's argument.
-And then
--Wmaybe-musttail-local-addr
-which is only diagnosed if -Wmusttail-local-addr was not diagnosed and
-diagnoses at most one (so that we don't emit 100s of warnings for one call
-if 100s of vars can escape) case where an address of a local var could have
-escaped to the musttail call.  This is less severe, the code doesn't have
-to be obviously wrong, so the warning is only enabled in -Wextra.
-
-And I've adjusted also the documentation for this change and addition of
-new warnings.
-
-Bootstrapped/regtested on x86_64-linux and i686-linux (on top of the
-just posted patch), ok for trunk?
-
-2025-03-25  Jakub Jelinek  <jakub@redhat.com>
-
-	PR ipa/119376
-	* common.opt (Wmusttail-local-addr, Wmaybe-musttail-local-addr): New.
-	* tree-tailcall.cc (suitable_for_tail_call_opt_p): Don't fail for
-	TREE_ADDRESSABLE PARM_DECLs for musttail calls if diag_musttail.
-	Emit -Wmusttail-local-addr warnings.
-	(maybe_error_musttail): Use gimple_location instead of directly
-	accessing location member.
-	(find_tail_calls): For musttail calls if diag_musttail, don't fail
-	if address of local could escape to the call, instead emit
-	-Wmaybe-musttail-local-addr warnings.  Emit
-	-Wmaybe-musttail-local-addr warnings also for address taken
-	parameters.
-	* common.opt.urls: Regenerate.
-	* doc/extend.texi (musttail statement attribute): Clarify local
-	variables without non-trivial destruction are considered out of scope
-	before the tail call instruction.
-	* doc/invoke.texi (-Wno-musttail-local-addr,
-	-Wmaybe-musttail-local-addr): Document.
-
-	* c-c++-common/musttail8.c: Expect a warning rather than error in one
-	case.
-	(f4): Add int * argument.
-	* c-c++-common/musttail15.c: Don't disallow for C++98.
-	* c-c++-common/musttail16.c: Likewise.
-	* c-c++-common/musttail17.c: Likewise.
-	* c-c++-common/musttail18.c: Likewise.
-	* c-c++-common/musttail19.c: Likewise.  Expect a warning rather than
-	error in one case.
-	(f4): Add int * argument.
-	* c-c++-common/musttail20.c: Don't disallow for C++98.
-	* c-c++-common/musttail21.c: Likewise.
-	* c-c++-common/musttail28.c: New test.
-	* c-c++-common/musttail29.c: New test.
-	* c-c++-common/musttail30.c: New test.
-	* c-c++-common/musttail31.c: New test.
-	* g++.dg/ext/musttail1.C: New test.
-	* g++.dg/ext/musttail2.C: New test.
-	* g++.dg/ext/musttail3.C: New test.
----
- gcc/common.opt                          |   8 ++
- gcc/common.opt.urls                     |   6 ++
- gcc/doc/extend.texi                     |  49 ++++++++++-
- gcc/doc/invoke.texi                     |  52 ++++++++++-
- gcc/testsuite/c-c++-common/musttail15.c |   2 +-
- gcc/testsuite/c-c++-common/musttail16.c |   2 +-
- gcc/testsuite/c-c++-common/musttail17.c |   2 +-
- gcc/testsuite/c-c++-common/musttail18.c |   2 +-
- gcc/testsuite/c-c++-common/musttail19.c |   7 +-
- gcc/testsuite/c-c++-common/musttail20.c |   2 +-
- gcc/testsuite/c-c++-common/musttail21.c |   2 +-
- gcc/testsuite/c-c++-common/musttail28.c | 108 +++++++++++++++++++++++
- gcc/testsuite/c-c++-common/musttail29.c | 109 ++++++++++++++++++++++++
- gcc/testsuite/c-c++-common/musttail30.c | 109 ++++++++++++++++++++++++
- gcc/testsuite/c-c++-common/musttail31.c | 109 ++++++++++++++++++++++++
- gcc/testsuite/c-c++-common/musttail8.c  |   5 +-
- gcc/testsuite/g++.dg/ext/musttail1.C    |  38 +++++++++
- gcc/testsuite/g++.dg/ext/musttail2.C    |  38 +++++++++
- gcc/testsuite/g++.dg/ext/musttail3.C    |  37 ++++++++
- gcc/tree-tailcall.cc                    |  97 +++++++++++++++++++--
- 20 files changed, 760 insertions(+), 24 deletions(-)
- create mode 100644 gcc/testsuite/c-c++-common/musttail28.c
- create mode 100644 gcc/testsuite/c-c++-common/musttail29.c
- create mode 100644 gcc/testsuite/c-c++-common/musttail30.c
- create mode 100644 gcc/testsuite/c-c++-common/musttail31.c
- create mode 100644 gcc/testsuite/g++.dg/ext/musttail1.C
- create mode 100644 gcc/testsuite/g++.dg/ext/musttail2.C
- create mode 100644 gcc/testsuite/g++.dg/ext/musttail3.C
-
-diff --git a/gcc/common.opt b/gcc/common.opt
-index 2da02866ca08..9400c4b94e88 100644
---- a/gcc/common.opt
-+++ b/gcc/common.opt
-@@ -693,6 +693,14 @@ Does nothing. Preserved for backward compatibility.
- Wmissing-noreturn
- Common Warning Alias(Wsuggest-attribute=noreturn)
- 
-+Wmusttail-local-addr
-+Common Var(warn_musttail_local_addr) Init(1) Warning
-+Warn about passing a pointer/reference to a local or temporary variable to a musttail call argument.
-+
-+Wmaybe-musttail-local-addr
-+Common Var(warn_maybe_musttail_local_addr) Warning EnabledBy(Wextra)
-+Warn about pointer/reference to a local or temporary variable possibly escaping to a musttail call.
-+
- Wodr
- Common Var(warn_odr_violations) Init(1) Warning
- Warn about some C++ One Definition Rule violations during link time optimization.
-diff --git a/gcc/common.opt.urls b/gcc/common.opt.urls
-index e7900c825c17..860ebd01ace2 100644
---- a/gcc/common.opt.urls
-+++ b/gcc/common.opt.urls
-@@ -157,6 +157,12 @@ UrlSuffix(gcc/Warning-Options.html#index-Wno-unsafe-loop-optimizations)
- Wmissing-noreturn
- UrlSuffix(gcc/Warning-Options.html#index-Wmissing-noreturn)
- 
-+Wmusttail-local-addr
-+UrlSuffix(gcc/Warning-Options.html#index-Wno-musttail-local-addr)
-+
-+Wmaybe-musttail-local-addr
-+UrlSuffix(gcc/Warning-Options.html#index-Wmaybe-musttail-local-addr)
-+
- Wodr
- UrlSuffix(gcc/Warning-Options.html#index-Wno-odr)
- 
-diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
-index ed766e53dcc4..fcb6df95dcf5 100644
---- a/gcc/doc/extend.texi
-+++ b/gcc/doc/extend.texi
-@@ -9282,10 +9282,51 @@ __attribute__((musttail)) return bar();
- 
- If the compiler cannot generate a @code{musttail} tail call it will report
- an error.  On some targets tail calls may never be supported.
--Tail calls cannot reference locals in memory, which may affect
--builds without optimization when passing small structures, or passing
--or returning large structures.  Enabling @option{-O1} or @option{-O2} can
--improve the success of tail calls.
-+The user asserts for @code{musttail} tail calls that lifetime of automatic
-+variables, function parameters and temporaries (unless they have non-trivial
-+destruction) can end before the actual call instruction and that any access
-+to those from inside of the called function results is considered undefined
-+behavior.  Enabling @option{-O1} or @option{-O2} can improve the success of
-+tail calls.
-+
-+@smallexample
-+int foo (int *);
-+void bar (int *);
-+struct S @{ S (); ~S (); int s; @};
-+
-+int
-+baz (int *x)
-+@{
-+  if (*x == 1)
-+    @{
-+      int a = 42;
-+      /* The call will be tail called (would not be without the
-+         attribute), dereferencing the pointer in the callee is
-+         undefined behavior and there will be a warning emitted
-+         for this by default (@option{-Wmusttail-local-addr}).  */
-+      [[gnu::musttail]] return foo (&a);
-+    @}
-+  else if (*x == 2)
-+    @{
-+      int a = 42;
-+      bar (&a);
-+      /* The call will be tail called (would not be without the
-+         attribute), if bar stores the pointer anywhere, dereferencing
-+         it in foo will be undefined behavior and there will be a warning
-+         emitted for this with @option{-Wextra}, which implies
-+         @option{-Wmaybe-musttail-local-addr}.  */
-+      [[gnu::musttail]] return foo (nullptr);
-+    @}
-+  else
-+    @{
-+      S s;
-+      /* The s variable requires non-trivial destruction which ought
-+         to be performed after the foo call returns, so this will
-+         be rejected.  */
-+      [[gnu::musttail]] return foo (&s.s);
-+    @}
-+@}
-+@end smallexample
- @end table
- 
- @node Attribute Syntax
-diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
-index df4610908243..2617406b7691 100644
---- a/gcc/doc/invoke.texi
-+++ b/gcc/doc/invoke.texi
-@@ -394,7 +394,8 @@ Objective-C and Objective-C++ Dialects}.
- -Wmemset-elt-size  -Wmemset-transposed-args
- -Wmisleading-indentation  -Wmissing-attributes  -Wmissing-braces
- -Wmissing-field-initializers  -Wmissing-format-attribute
---Wmissing-include-dirs  -Wmissing-noreturn  -Wno-missing-profile
-+-Wmissing-include-dirs  -Wmissing-noreturn  -Wmusttail-local-addr
-+-Wmaybe-musttail-local-addr  -Wno-missing-profile
- -Wno-multichar  -Wmultistatement-macros  -Wnonnull  -Wnonnull-compare
- -Wnormalized=@r{[}none@r{|}id@r{|}nfc@r{|}nfkc@r{]}
- -Wnull-dereference  -Wno-odr
-@@ -6975,6 +6976,55 @@ is only active when @option{-fdelete-null-pointer-checks} is active,
- which is enabled by optimizations in most targets.  The precision of
- the warnings depends on the optimization options used.
- 
-+@opindex Wno-musttail-local-addr
-+@opindex -Wmusttail-local-addr
-+@item -Wno-musttail-local-addr
-+Do not warn about passing a pointer (or in C++, a reference) to a
-+local variable or label to argument of a @code{musttail} call.  Those
-+variables go out of scope before the tail call instruction.
-+
-+@opindex Wmaybe-musttail-local-addr
-+@opindex -Wno-maybe-musttail-local-addr
-+@item -Wmaybe-musttail-local-addr
-+Warn when address of a local variable can escape to a @code{musttail}
-+call, unless it goes out of scope already before the @code{musttail}
-+call.
-+
-+@smallexample
-+int foo (int *);
-+
-+int
-+bar (int *x)
-+@{
-+  if (x[0] == 1)
-+    @{
-+      int a = 42;
-+      foo (&a);
-+      /* Without the @code{musttail} attribute this call would not
-+         be tail called, because address of the @code{a} variable escapes
-+         and the second foo call could dereference it.  With the attribute
-+         the local variables are assumed to go out of scope immediately
-+         before the tail call instruction and the compiler warns about
-+         this.  */
-+      [[gnu::musttail]] return foo (nullptr);
-+    @}
-+  else
-+    @{
-+      @{
-+        int a = 42;
-+        foo (&a);
-+      @}
-+      /* The @code{a} variable isn't already in scope, so even when it
-+         escaped, even without @code{musttail} attribute it would be
-+         undefined behavior to dereference it and the compiler could
-+         turn this into a tail call.  No warning is diagnosed here.  */
-+      [[gnu::musttail]] return foo (nullptr);
-+    @}
-+@}
-+@end smallexample
-+
-+This warning is enabled by @option{-Wextra}.
-+
- @opindex Wnrvo
- @opindex Wno-nrvo
- @item -Wnrvo @r{(C++ and Objective-C++ only)}
-diff --git a/gcc/testsuite/c-c++-common/musttail15.c b/gcc/testsuite/c-c++-common/musttail15.c
-index 2addc971922c..b8223d77fd56 100644
---- a/gcc/testsuite/c-c++-common/musttail15.c
-+++ b/gcc/testsuite/c-c++-common/musttail15.c
-@@ -1,4 +1,4 @@
--/* { dg-do compile { target { musttail && { c || c++11 } } } } */
-+/* { dg-do compile { target musttail } } */
- /* { dg-additional-options "-fdelayed-branch" { target sparc*-*-* } } */
- 
- int __attribute__((noinline,noclone,noipa))
-diff --git a/gcc/testsuite/c-c++-common/musttail16.c b/gcc/testsuite/c-c++-common/musttail16.c
-index b1e2ff3e6dc8..f27a27923314 100644
---- a/gcc/testsuite/c-c++-common/musttail16.c
-+++ b/gcc/testsuite/c-c++-common/musttail16.c
-@@ -1,4 +1,4 @@
--/* { dg-do compile { target { musttail && { c || c++11 } } } } */
-+/* { dg-do compile { target musttail } } */
- 
- struct box { char field[256]; int i; };
- 
-diff --git a/gcc/testsuite/c-c++-common/musttail17.c b/gcc/testsuite/c-c++-common/musttail17.c
-index 490f3c35ca23..58fab84993bf 100644
---- a/gcc/testsuite/c-c++-common/musttail17.c
-+++ b/gcc/testsuite/c-c++-common/musttail17.c
-@@ -1,4 +1,4 @@
--/* { dg-do compile { target { musttail && { c || c++11 } } } } */
-+/* { dg-do compile { target musttail } } */
- 
- struct box { char field[64]; int i; };
- 
-diff --git a/gcc/testsuite/c-c++-common/musttail18.c b/gcc/testsuite/c-c++-common/musttail18.c
-index 4f34a8d27f36..ab608871fd08 100644
---- a/gcc/testsuite/c-c++-common/musttail18.c
-+++ b/gcc/testsuite/c-c++-common/musttail18.c
-@@ -1,4 +1,4 @@
--/* { dg-do compile { target { musttail && { c || c++11 } } } } */
-+/* { dg-do compile { target musttail } } */
- /* { dg-additional-options "-fdelayed-branch" { target sparc*-*-* } } */
- 
- void __attribute__((noipa)) f() {}
-diff --git a/gcc/testsuite/c-c++-common/musttail19.c b/gcc/testsuite/c-c++-common/musttail19.c
-index 70f9eaff139c..a592b69c1b7c 100644
---- a/gcc/testsuite/c-c++-common/musttail19.c
-+++ b/gcc/testsuite/c-c++-common/musttail19.c
-@@ -1,4 +1,4 @@
--/* { dg-do compile { target { musttail && { c || c++11 } } } } */
-+/* { dg-do compile { target musttail } } */
- 
- float f1(void);
- 
-@@ -10,8 +10,9 @@ int f2(void)
- 
- int f3(int *);
- 
--int f4(void)
-+int f4(int *p)
- {
-   int x;
--  __attribute__((musttail)) return f3(&x); /* { dg-error "\(refers to locals|other reasons\)" } */
-+  (void) p;
-+  __attribute__((musttail)) return f3(&x); /* { dg-warning "address of automatic variable 'x' passed to 'musttail' call argument" } */
- }
-diff --git a/gcc/testsuite/c-c++-common/musttail20.c b/gcc/testsuite/c-c++-common/musttail20.c
-index 70f14ff2f217..1931f2cc8e4a 100644
---- a/gcc/testsuite/c-c++-common/musttail20.c
-+++ b/gcc/testsuite/c-c++-common/musttail20.c
-@@ -1,4 +1,4 @@
--/* { dg-do compile { target { struct_musttail && { c || c++11 } } } } */
-+/* { dg-do compile { target struct_musttail } } */
- /* { dg-additional-options "-fdelayed-branch" { target sparc*-*-* } } */
- 
- struct str
-diff --git a/gcc/testsuite/c-c++-common/musttail21.c b/gcc/testsuite/c-c++-common/musttail21.c
-index 954209ddcd51..1a109e1955dc 100644
---- a/gcc/testsuite/c-c++-common/musttail21.c
-+++ b/gcc/testsuite/c-c++-common/musttail21.c
-@@ -1,4 +1,4 @@
--/* { dg-do compile { target { c || c++11 } } } */
-+/* { dg-do compile { target musttail } } */
- void f(void)
- {
-   __attribute__((musttail)) return; /* { dg-error "cannot tail-call.*return value must be a call" } */
-diff --git a/gcc/testsuite/c-c++-common/musttail28.c b/gcc/testsuite/c-c++-common/musttail28.c
-new file mode 100644
-index 000000000000..d84658aa8a05
---- /dev/null
-+++ b/gcc/testsuite/c-c++-common/musttail28.c
-@@ -0,0 +1,108 @@
-+/* { dg-do compile { target { musttail && { c || c++11 } } } } */
-+
-+int foo (int, void *);
-+int bar (int, int *);
-+struct S { int a, b, c; };
-+struct T { int d; struct S e; };
-+
-+int
-+baz (int x, void *y)
-+{
-+  [[gnu::musttail]] return bar (2, &x);		/* { dg-warning "address of parameter 'x' passed to 'musttail' call argument" } */
-+}
-+
-+int
-+qux (int x, void *y)
-+{
-+  __label__ lab;
-+  lab:;
-+  if (*(int *) y == 1)
-+    [[gnu::musttail]] return foo (1, &&lab);	/* { dg-warning "address of label passed to 'musttail' call argument" } */
-+  if (x == 1)
-+    [[gnu::musttail]] return foo (3, 0);
-+  else if (x == 2)
-+    {
-+      {
-+        int a = 42;
-+        bar (4, &a);
-+      }
-+      [[gnu::musttail]] return bar (5, 0);
-+    }
-+  else if (x == 3)
-+    {
-+      int a = 42;
-+      bar (4, &a);
-+      [[gnu::musttail]] return bar (6, 0);
-+    }
-+  else if (x == 4)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return bar (7, &a);	/* { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 5)
-+    {
-+      struct T b;
-+      [[gnu::musttail]] return bar (8, &b.e.b);	/* { dg-warning "address of automatic variable 'b' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 6)
-+    {
-+      struct T b;
-+      bar (9, &b.e.a);
-+      [[gnu::musttail]] return bar (10, 0);
-+    }
-+  else if (x == 7)
-+    {
-+      {
-+        struct T b;
-+        bar (9, &b.e.a);
-+      }
-+      [[gnu::musttail]] return bar (11, 0);
-+    }
-+  else if (x == 8)
-+    {
-+      {
-+        int a = 42;
-+        bar (4, &a);
-+      }
-+      [[gnu::musttail]] return foo (12, 0);
-+    }
-+  else if (x == 9)
-+    {
-+      int a = 42;
-+      bar (4, &a);
-+      [[gnu::musttail]] return foo (13, 0);
-+    }
-+  else if (x == 10)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return foo (14, &a);	/* { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 11)
-+    {
-+      struct T b;
-+      [[gnu::musttail]] return foo (15, &b.e.b); /* { dg-warning "address of automatic variable 'b' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 12)
-+    {
-+      struct T b;
-+      bar (9, &b.e.a);
-+      [[gnu::musttail]] return foo (16, 0);
-+    }
-+  else if (x == 13)
-+    {
-+      {
-+        struct T b;
-+        bar (9, &b.e.a);
-+      }
-+      [[gnu::musttail]] return foo (17, 0);
-+    }
-+  return 0;
-+}
-+
-+int
-+corge (int x, void *y)
-+{
-+  if (*(int *) y == 1)
-+    bar (18, &x);
-+  [[gnu::musttail]] return bar (2, 0);
-+}
-diff --git a/gcc/testsuite/c-c++-common/musttail29.c b/gcc/testsuite/c-c++-common/musttail29.c
-new file mode 100644
-index 000000000000..f6b3d76abe11
---- /dev/null
-+++ b/gcc/testsuite/c-c++-common/musttail29.c
-@@ -0,0 +1,109 @@
-+/* { dg-do compile { target { musttail && { c || c++11 } } } } */
-+/* { dg-options "-O2 -Wmusttail-local-addr" } */
-+
-+int foo (int, void *);
-+int bar (int, int *);
-+struct S { int a, b, c; };
-+struct T { int d; struct S e; };
-+
-+int
-+baz (int x, void *y)
-+{
-+  [[gnu::musttail]] return bar (2, &x);		/* { dg-warning "address of parameter 'x' passed to 'musttail' call argument" } */
-+}
-+
-+int
-+qux (int x, void *y)
-+{
-+  __label__ lab;
-+  lab:;
-+  if (*(int *) y == 1)
-+    [[gnu::musttail]] return foo (1, &&lab);	/* { dg-warning "address of label passed to 'musttail' call argument" } */
-+  if (x == 1)
-+    [[gnu::musttail]] return foo (3, 0);
-+  else if (x == 2)
-+    {
-+      {
-+        int a = 42;
-+        bar (4, &a);
-+      }
-+      [[gnu::musttail]] return bar (5, 0);
-+    }
-+  else if (x == 3)
-+    {
-+      int a = 42;
-+      bar (4, &a);
-+      [[gnu::musttail]] return bar (6, 0);
-+    }
-+  else if (x == 4)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return bar (7, &a);	/* { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 5)
-+    {
-+      struct T b;
-+      [[gnu::musttail]] return bar (8, &b.e.b);	/* { dg-warning "address of automatic variable 'b' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 6)
-+    {
-+      struct T b;
-+      bar (9, &b.e.a);
-+      [[gnu::musttail]] return bar (10, 0);
-+    }
-+  else if (x == 7)
-+    {
-+      {
-+        struct T b;
-+        bar (9, &b.e.a);
-+      }
-+      [[gnu::musttail]] return bar (11, 0);
-+    }
-+  else if (x == 8)
-+    {
-+      {
-+        int a = 42;
-+        bar (4, &a);
-+      }
-+      [[gnu::musttail]] return foo (12, 0);
-+    }
-+  else if (x == 9)
-+    {
-+      int a = 42;
-+      bar (4, &a);
-+      [[gnu::musttail]] return foo (13, 0);
-+    }
-+  else if (x == 10)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return foo (14, &a);	/* { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 11)
-+    {
-+      struct T b;
-+      [[gnu::musttail]] return foo (15, &b.e.b); /* { dg-warning "address of automatic variable 'b' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 12)
-+    {
-+      struct T b;
-+      bar (9, &b.e.a);
-+      [[gnu::musttail]] return foo (16, 0);
-+    }
-+  else if (x == 13)
-+    {
-+      {
-+        struct T b;
-+        bar (9, &b.e.a);
-+      }
-+      [[gnu::musttail]] return foo (17, 0);
-+    }
-+  return 0;
-+}
-+
-+int
-+corge (int x, void *y)
-+{
-+  if (*(int *) y == 1)
-+    bar (18, &x);
-+  [[gnu::musttail]] return bar (2, 0);
-+}
-diff --git a/gcc/testsuite/c-c++-common/musttail30.c b/gcc/testsuite/c-c++-common/musttail30.c
-new file mode 100644
-index 000000000000..be1c3daf6af2
---- /dev/null
-+++ b/gcc/testsuite/c-c++-common/musttail30.c
-@@ -0,0 +1,109 @@
-+/* { dg-do compile { target { musttail && { c || c++11 } } } } */
-+/* { dg-options "-Wextra" } */
-+
-+int foo (int, void *);
-+int bar (int, int *);
-+struct S { int a, b, c; };
-+struct T { int d; struct S e; };
-+
-+int
-+baz (int x, void *y)
-+{
-+  [[gnu::musttail]] return bar (2, &x);		/* { dg-warning "address of parameter 'x' passed to 'musttail' call argument" } */
-+}
-+
-+int
-+qux (int x, void *y)
-+{
-+  __label__ lab;
-+  lab:;
-+  if (*(int *) y == 1)
-+    [[gnu::musttail]] return foo (1, &&lab);	/* { dg-warning "address of label passed to 'musttail' call argument" } */
-+  if (x == 1)
-+    [[gnu::musttail]] return foo (3, 0);
-+  else if (x == 2)
-+    {
-+      {
-+        int a = 42;
-+        bar (4, &a);
-+      }
-+      [[gnu::musttail]] return bar (5, 0);
-+    }
-+  else if (x == 3)
-+    {
-+      int a = 42;
-+      bar (4, &a);
-+      [[gnu::musttail]] return bar (6, 0);	/* { dg-warning "address of automatic variable 'a' can escape to 'musttail' call" } */
-+    }
-+  else if (x == 4)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return bar (7, &a);	/* { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 5)
-+    {
-+      struct T b;
-+      [[gnu::musttail]] return bar (8, &b.e.b);	/* { dg-warning "address of automatic variable 'b' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 6)
-+    {
-+      struct T b;
-+      bar (9, &b.e.a);
-+      [[gnu::musttail]] return bar (10, 0);	/* { dg-warning "address of automatic variable 'b' can escape to 'musttail' call" } */
-+    }
-+  else if (x == 7)
-+    {
-+      {
-+        struct T b;
-+        bar (9, &b.e.a);
-+      }
-+      [[gnu::musttail]] return bar (11, 0);
-+    }
-+  else if (x == 8)
-+    {
-+      {
-+        int a = 42;
-+        bar (4, &a);
-+      }
-+      [[gnu::musttail]] return foo (12, 0);
-+    }
-+  else if (x == 9)
-+    {
-+      int a = 42;
-+      bar (4, &a);
-+      [[gnu::musttail]] return foo (13, 0);	/* { dg-warning "address of automatic variable 'a' can escape to 'musttail' call" } */
-+    }
-+  else if (x == 10)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return foo (14, &a);	/* { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 11)
-+    {
-+      struct T b;
-+      [[gnu::musttail]] return foo (15, &b.e.b); /* { dg-warning "address of automatic variable 'b' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 12)
-+    {
-+      struct T b;
-+      bar (9, &b.e.a);
-+      [[gnu::musttail]] return foo (16, 0);	/* { dg-warning "address of automatic variable 'b' can escape to 'musttail' call" } */
-+    }
-+  else if (x == 13)
-+    {
-+      {
-+        struct T b;
-+        bar (9, &b.e.a);
-+      }
-+      [[gnu::musttail]] return foo (17, 0);
-+    }
-+  return 0;
-+}
-+
-+int
-+corge (int x, void *y)
-+{
-+  if (*(int *) y == 1)
-+    bar (18, &x);
-+  [[gnu::musttail]] return bar (2, 0);		/* { dg-warning "address of parameter 'x' can escape to 'musttail' call" } */
-+}
-diff --git a/gcc/testsuite/c-c++-common/musttail31.c b/gcc/testsuite/c-c++-common/musttail31.c
-new file mode 100644
-index 000000000000..f44ada4d4733
---- /dev/null
-+++ b/gcc/testsuite/c-c++-common/musttail31.c
-@@ -0,0 +1,109 @@
-+/* { dg-do compile { target { musttail && { c || c++11 } } } } */
-+/* { dg-options "-O2 -Wmaybe-musttail-local-addr" } */
-+
-+int foo (int, void *);
-+int bar (int, int *);
-+struct S { int a, b, c; };
-+struct T { int d; struct S e; };
-+
-+int
-+baz (int x, void *y)
-+{
-+  [[gnu::musttail]] return bar (2, &x);		/* { dg-warning "address of parameter 'x' passed to 'musttail' call argument" } */
-+}
-+
-+int
-+qux (int x, void *y)
-+{
-+  __label__ lab;
-+  lab:;
-+  if (*(int *) y == 1)
-+    [[gnu::musttail]] return foo (1, &&lab);	/* { dg-warning "address of label passed to 'musttail' call argument" } */
-+  if (x == 1)
-+    [[gnu::musttail]] return foo (3, 0);
-+  else if (x == 2)
-+    {
-+      {
-+        int a = 42;
-+        bar (4, &a);
-+      }
-+      [[gnu::musttail]] return bar (5, 0);
-+    }
-+  else if (x == 3)
-+    {
-+      int a = 42;
-+      bar (4, &a);
-+      [[gnu::musttail]] return bar (6, 0);	/* { dg-warning "address of automatic variable 'a' can escape to 'musttail' call" } */
-+    }
-+  else if (x == 4)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return bar (7, &a);	/* { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 5)
-+    {
-+      struct T b;
-+      [[gnu::musttail]] return bar (8, &b.e.b);	/* { dg-warning "address of automatic variable 'b' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 6)
-+    {
-+      struct T b;
-+      bar (9, &b.e.a);
-+      [[gnu::musttail]] return bar (10, 0);	/* { dg-warning "address of automatic variable 'b' can escape to 'musttail' call" } */
-+    }
-+  else if (x == 7)
-+    {
-+      {
-+        struct T b;
-+        bar (9, &b.e.a);
-+      }
-+      [[gnu::musttail]] return bar (11, 0);
-+    }
-+  else if (x == 8)
-+    {
-+      {
-+        int a = 42;
-+        bar (4, &a);
-+      }
-+      [[gnu::musttail]] return foo (12, 0);
-+    }
-+  else if (x == 9)
-+    {
-+      int a = 42;
-+      bar (4, &a);
-+      [[gnu::musttail]] return foo (13, 0);	/* { dg-warning "address of automatic variable 'a' can escape to 'musttail' call" } */
-+    }
-+  else if (x == 10)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return foo (14, &a);	/* { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 11)
-+    {
-+      struct T b;
-+      [[gnu::musttail]] return foo (15, &b.e.b); /* { dg-warning "address of automatic variable 'b' passed to 'musttail' call argument" } */
-+    }
-+  else if (x == 12)
-+    {
-+      struct T b;
-+      bar (9, &b.e.a);
-+      [[gnu::musttail]] return foo (16, 0);	/* { dg-warning "address of automatic variable 'b' can escape to 'musttail' call" } */
-+    }
-+  else if (x == 13)
-+    {
-+      {
-+        struct T b;
-+        bar (9, &b.e.a);
-+      }
-+      [[gnu::musttail]] return foo (17, 0);
-+    }
-+  return 0;
-+}
-+
-+int
-+corge (int x, void *y)
-+{
-+  if (*(int *) y == 1)
-+    bar (18, &x);
-+  [[gnu::musttail]] return bar (2, 0);		/* { dg-warning "address of parameter 'x' can escape to 'musttail' call" } */
-+}
-diff --git a/gcc/testsuite/c-c++-common/musttail8.c b/gcc/testsuite/c-c++-common/musttail8.c
-index 50ca1ac0dd48..9a29030a3b06 100644
---- a/gcc/testsuite/c-c++-common/musttail8.c
-+++ b/gcc/testsuite/c-c++-common/musttail8.c
-@@ -10,8 +10,9 @@ int f2(void)
- 
- int f3(int *);
- 
--int f4(void)
-+int f4(int *p)
- {
-   int x;
--  [[gnu::musttail]] return f3(&x); /* { dg-error "\(refers to locals|other reasons\)" } */
-+  (void) p;
-+  [[gnu::musttail]] return f3(&x); /* { dg-warning "address of automatic variable 'x' passed to 'musttail' call argument" } */
- }
-diff --git a/gcc/testsuite/g++.dg/ext/musttail1.C b/gcc/testsuite/g++.dg/ext/musttail1.C
-new file mode 100644
-index 000000000000..fd9b386a5974
---- /dev/null
-+++ b/gcc/testsuite/g++.dg/ext/musttail1.C
-@@ -0,0 +1,38 @@
-+// PR ipa/119376
-+// { dg-do compile { target { musttail && c++11 } } }
-+// { dg-options "-Wmaybe-musttail-local-addr" }
-+
-+int foo (int &);
-+int bar (int &&);
-+int corge (int *);
-+
-+int
-+baz (int &x)
-+{
-+  if (x == 1)
-+    [[gnu::musttail]] return foo (x);
-+  if (x == 2)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return foo (a);		// { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" }
-+    }
-+  if (x == 3)
-+    {
-+      int a = 42;
-+      foo (a);
-+      [[gnu::musttail]] return foo (x);		// { dg-warning "address of automatic variable 'a' can escape to 'musttail' call" }
-+    }
-+  return 0;
-+}
-+
-+int
-+qux (int &&x)
-+{
-+  [[gnu::musttail]] return bar (x + 1);		// { dg-warning "address of local variable passed to 'musttail' call argument" }
-+}
-+
-+int
-+freddy (int x)
-+{
-+  [[gnu::musttail]] return foo (x);		// { dg-warning "address of parameter 'x' passed to 'musttail' call argument" }
-+}
-diff --git a/gcc/testsuite/g++.dg/ext/musttail2.C b/gcc/testsuite/g++.dg/ext/musttail2.C
-new file mode 100644
-index 000000000000..ac99aafb0f0c
---- /dev/null
-+++ b/gcc/testsuite/g++.dg/ext/musttail2.C
-@@ -0,0 +1,38 @@
-+// PR ipa/119376
-+// { dg-do compile { target { musttail && c++11 } } }
-+// { dg-options "-Wextra" }
-+
-+int foo (int &);
-+int bar (int &&);
-+int corge (int *);
-+
-+int
-+baz (int &x)
-+{
-+  if (x == 1)
-+    [[clang::musttail]] return foo (x);
-+  if (x == 2)
-+    {
-+      int a = 42;
-+      [[clang::musttail]] return foo (a);		// { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" }
-+    }
-+  if (x == 3)
-+    {
-+      int a = 42;
-+      foo (a);
-+      [[clang::musttail]] return foo (x);		// { dg-warning "address of automatic variable 'a' can escape to 'musttail' call" }
-+    }
-+  return 0;
-+}
-+
-+int
-+qux (int &&x)
-+{
-+  [[clang::musttail]] return bar (x + 1);		// { dg-warning "address of local variable passed to 'musttail' call argument" }
-+}
-+
-+int
-+freddy (int x)
-+{
-+  [[clang::musttail]] return foo (x);			// { dg-warning "address of parameter 'x' passed to 'musttail' call argument" }
-+}
-diff --git a/gcc/testsuite/g++.dg/ext/musttail3.C b/gcc/testsuite/g++.dg/ext/musttail3.C
-new file mode 100644
-index 000000000000..1c4b939a2a43
---- /dev/null
-+++ b/gcc/testsuite/g++.dg/ext/musttail3.C
-@@ -0,0 +1,37 @@
-+// PR ipa/119376
-+// { dg-do compile { target { musttail && c++11 } } }
-+
-+int foo (int &);
-+int bar (int &&);
-+int corge (int *);
-+
-+int
-+baz (int &x)
-+{
-+  if (x == 1)
-+    [[gnu::musttail]] return foo (x);
-+  if (x == 2)
-+    {
-+      int a = 42;
-+      [[gnu::musttail]] return foo (a);		// { dg-warning "address of automatic variable 'a' passed to 'musttail' call argument" }
-+    }
-+  if (x == 3)
-+    {
-+      int a = 42;
-+      foo (a);
-+      [[gnu::musttail]] return foo (x);
-+    }
-+  return 0;
-+}
-+
-+int
-+qux (int &&x)
-+{
-+  [[gnu::musttail]] return bar (x + 1);		// { dg-warning "address of local variable passed to 'musttail' call argument" }
-+}
-+
-+int
-+freddy (int x)
-+{
-+  [[gnu::musttail]] return foo (x);		// { dg-warning "address of parameter 'x' passed to 'musttail' call argument" }
-+}
-diff --git a/gcc/tree-tailcall.cc b/gcc/tree-tailcall.cc
-index 8ba675221915..e025a1cb78b2 100644
---- a/gcc/tree-tailcall.cc
-+++ b/gcc/tree-tailcall.cc
-@@ -206,14 +206,48 @@ suitable_for_tail_call_opt_p (gcall *call, bool diag_musttail)
- 
-   /* ??? It is OK if the argument of a function is taken in some cases,
-      but not in all cases.  See PR15387 and PR19616.  Revisit for 4.1.  */
--  for (param = DECL_ARGUMENTS (current_function_decl);
--       param;
--       param = DECL_CHAIN (param))
--    if (TREE_ADDRESSABLE (param))
-+  if (!diag_musttail || !gimple_call_must_tail_p (call))
-+    for (param = DECL_ARGUMENTS (current_function_decl);
-+	 param; param = DECL_CHAIN (param))
-+      if (TREE_ADDRESSABLE (param))
-+	{
-+	  maybe_error_musttail (call, _("address of caller arguments taken"),
-+				diag_musttail);
-+	  return false;
-+	}
-+
-+  if (diag_musttail
-+      && gimple_call_must_tail_p (call)
-+      && warn_musttail_local_addr)
-+    for (unsigned int i = 0; i < gimple_call_num_args (call); i++)
-       {
--	maybe_error_musttail (call, _("address of caller arguments taken"),
--			      diag_musttail);
--	return false;
-+	tree arg = gimple_call_arg (call, i);
-+	if (!POINTER_TYPE_P (TREE_TYPE (arg)))
-+	  continue;
-+	if (TREE_CODE (arg) == ADDR_EXPR)
-+	  {
-+	    arg = get_base_address (TREE_OPERAND (arg, 0));
-+	    if (auto_var_in_fn_p (arg, current_function_decl))
-+	      {
-+		if (TREE_CODE (arg) == LABEL_DECL)
-+		  warning_at (gimple_location (call), OPT_Wmusttail_local_addr,
-+			      "address of label passed to %<musttail%> "
-+			      "call argument");
-+		else if (TREE_CODE (arg) == PARM_DECL)
-+		  warning_at (gimple_location (call), OPT_Wmusttail_local_addr,
-+			      "address of parameter %qD passed to "
-+			      "%<musttail%> call argument", arg);
-+		else if (!DECL_ARTIFICIAL (arg) && DECL_NAME (arg))
-+		  warning_at (gimple_location (call), OPT_Wmusttail_local_addr,
-+			      "address of automatic variable %qD passed to "
-+			      "%<musttail%> call argument", arg);
-+		else
-+		  warning_at (gimple_location (call), OPT_Wmusttail_local_addr,
-+			      "address of local variable passed to "
-+			      "%<musttail%> call argument");
-+		suppress_warning (call, OPT_Wmaybe_musttail_local_addr);
-+	      }
-+	  }
-       }
- 
-   return true;
-@@ -443,7 +477,7 @@ maybe_error_musttail (gcall *call, const char *err, bool diag_musttail)
- {
-   if (gimple_call_must_tail_p (call) && diag_musttail)
-     {
--      error_at (call->location, "cannot tail-call: %s", err);
-+      error_at (gimple_location (call), "cannot tail-call: %s", err);
-       /* Avoid another error. ??? If there are multiple reasons why tail
- 	 calls fail it might be useful to report them all to avoid
- 	 whack-a-mole for the user. But currently there is too much
-@@ -728,6 +762,19 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail,
- 	{
- 	  if (!VAR_P (var))
- 	    {
-+	      if (diag_musttail && gimple_call_must_tail_p (call))
-+		{
-+		  auto opt = OPT_Wmaybe_musttail_local_addr;
-+		  if (!warning_suppressed_p (call,
-+					     opt))
-+		    {
-+		      warning_at (gimple_location (call), opt,
-+				  "address of local variable can escape to "
-+				  "%<musttail%> call");
-+		      suppress_warning (call, opt);
-+		    }
-+		  continue;
-+		}
- 	      if (local_live_vars)
- 		BITMAP_FREE (local_live_vars);
- 	      maybe_error_musttail (call,
-@@ -740,6 +787,24 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail,
- 	      unsigned int *v = live_vars->get (DECL_UID (var));
- 	      if (bitmap_bit_p (local_live_vars, *v))
- 		{
-+		  if (diag_musttail && gimple_call_must_tail_p (call))
-+		    {
-+		      auto opt = OPT_Wmaybe_musttail_local_addr;
-+		      if (!warning_suppressed_p (call, opt))
-+			{
-+			  if (!DECL_ARTIFICIAL (var) && DECL_NAME (var))
-+			    warning_at (gimple_location (call), opt,
-+					"address of automatic variable %qD "
-+					"can escape to %<musttail%> call",
-+					var);
-+			  else
-+			    warning_at (gimple_location (call), opt,
-+					"address of local variable can escape "
-+					"to %<musttail%> call");
-+			  suppress_warning (call, opt);
-+			}
-+		      continue;
-+		    }
- 		  BITMAP_FREE (local_live_vars);
- 		  maybe_error_musttail (call,
- 					_("call invocation refers to locals"),
-@@ -749,6 +814,22 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail,
- 	    }
- 	}
-     }
-+  if (diag_musttail
-+      && gimple_call_must_tail_p (call)
-+      && !warning_suppressed_p (call, OPT_Wmaybe_musttail_local_addr))
-+    for (tree param = DECL_ARGUMENTS (current_function_decl);
-+	 param; param = DECL_CHAIN (param))
-+      if (may_be_aliased (param)
-+	  && (ref_maybe_used_by_stmt_p (call, param, false)
-+	      || call_may_clobber_ref_p (call, param, false)))
-+	{
-+	  auto opt = OPT_Wmaybe_musttail_local_addr;
-+	  warning_at (gimple_location (call), opt,
-+		      "address of parameter %qD can escape to "
-+		      "%<musttail%> call", param);
-+	  suppress_warning (call, opt);
-+	  break;
-+	}
- 
-   if (local_live_vars)
-     BITMAP_FREE (local_live_vars);
-
-base-commit: eb26b667518c951d06f3c51118a1d41dcdda8b99
--- 
-2.49.0
-

diff --git a/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch b/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch
index 339ba64..1873a71 100644
--- a/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch
+++ b/15.0.0/gentoo/83_all_PR119491-tailcall-eh.patch
@@ -1,20 +1,22 @@
-https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c4
+https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c5
 
 2025-04-01  Jakub Jelinek  <jakub@redhat.com>
 
 	PR tree-optimization/119491
-	* tree-tailcall.cc (independent_of_stmt_p): Use
-	find_fallthru_edge (bb->succs)->dest instead of single_succ (bb).
+	* tree-tailcall.cc (single_non_eh_succ_edge): New function.
+	(independent_of_stmt_p): Use single_non_eh_succ_edge (bb)->dest
+	instead of single_succ (bb).
 	(empty_eh_cleanup): New function.
 	(find_tail_calls): Diagnose throwing of exceptions which do not
 	propagate only if there are no EDGE_EH successor edges.  If there are
 	and the call is musttail, use empty_eh_cleanup to find if the cleanup
 	is not empty.  If not or the call is not musttail, use different
 	diagnostics.  Set is_noreturn even if there are successor edges.  Use
-	find_fallthru_edge (abb->succs) instead of single_succ_edge (abb).
+	single_non_eh_succ_edge (abb) instead of single_succ_edge (abb).  Punt
+	on internal noreturn calls.
 	(decrease_profile): Don't assert 0 or 1 successor edges.
 	(eliminate_tail_call): Use
-	find_fallthru_edge (gsi_bb (t->call_gsi)->succs) instead of
+	single_non_eh_succ_edge (gsi_bb (t->call_gsi)) instead of
 	single_succ_edge (gsi_bb (t->call_gsi)).
 	(tree_optimize_tail_calls_1): Also look into basic blocks with
 	single succ edge which is EDGE_EH for noreturn musttail calls.
@@ -22,164 +24,52 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119491#c4
 	* g++.dg/opt/musttail3.C: New test.
 	* g++.dg/opt/musttail4.C: New test.
 	* g++.dg/opt/musttail5.C: New test.
-diff --git a/gcc/testsuite/g++.dg/opt/musttail3.C b/gcc/testsuite/g++.dg/opt/musttail3.C
-new file mode 100644
-index 000000000000..1c4e54952b1e
---- /dev/null
-+++ b/gcc/testsuite/g++.dg/opt/musttail3.C
-@@ -0,0 +1,41 @@
-+// PR tree-optimization/119491
-+// { dg-do compile { target { external_musttail && c++11 } } }
-+// { dg-options "-O2" }
-+
-+struct A {
-+  struct B {};
-+  A () {}
-+};
-+void qux ();
-+unsigned char v;
-+A w;
-+void foo (A);
-+
-+template <typename T>
-+[[gnu::always_inline]] static inline void
-+bar (int &)
-+{
-+}
-+
-+[[gnu::always_inline]] static inline void
-+baz (int *)
-+{
-+  int r = 0;
-+  bar<int> (r);
-+}
-+
-+[[gnu::always_inline]] inline void
-+corge (A)
-+{
-+  if (v)
-+    qux ();
-+  [[gnu::musttail]] return foo (w);
-+}
-+
-+void
-+freddy (A)
-+{
-+  int t;
-+  baz (&t);
-+  [[gnu::musttail]] return corge (A{});
-+}
-diff --git a/gcc/testsuite/g++.dg/opt/musttail4.C b/gcc/testsuite/g++.dg/opt/musttail4.C
-new file mode 100644
-index 000000000000..ede2959f7d74
---- /dev/null
-+++ b/gcc/testsuite/g++.dg/opt/musttail4.C
-@@ -0,0 +1,35 @@
-+// { dg-do compile { target { external_musttail && c++11 } } }
-+// { dg-options "-O2 -fexceptions" }
-+
-+struct S { ~S (); };
-+volatile int v;
-+struct T { ~T () { v = v + 1; } };
-+struct U { ~U () {} };
-+int foo ();
-+
-+int
-+bar () noexcept
-+{
-+  [[gnu::musttail]] return foo ();	// { dg-error "cannot tail-call: call may throw exception that does not propagate" }
-+}
-+
-+int
-+baz ()
-+{
-+  S s;
-+  [[gnu::musttail]] return foo ();	// { dg-error "cannot tail-call: other reasons" }
-+}
-+
-+int
-+qux ()
-+{
-+  T t;
-+  [[gnu::musttail]] return foo ();	// { dg-error "cannot tail-call: other reasons" }
-+}
-+
-+int
-+corge ()
-+{
-+  U u;
-+  [[gnu::musttail]] return foo ();
-+}
-diff --git a/gcc/testsuite/g++.dg/opt/musttail5.C b/gcc/testsuite/g++.dg/opt/musttail5.C
-new file mode 100644
-index 000000000000..604dd6907aa9
---- /dev/null
-+++ b/gcc/testsuite/g++.dg/opt/musttail5.C
-@@ -0,0 +1,41 @@
-+// PR tree-optimization/119491
-+// { dg-do compile { target { external_musttail && c++11 } } }
-+// { dg-options "-O2" }
-+
-+struct A {
-+  struct B {};
-+  A () {}
-+};
-+void qux ();
-+unsigned char v;
-+A w;
-+[[noreturn]] void foo (A);
-+
-+template <typename T>
-+[[gnu::always_inline]] static inline void
-+bar (int &)
-+{
-+}
-+
-+[[gnu::always_inline]] static inline void
-+baz (int *)
-+{
-+  int r = 0;
-+  bar<int> (r);
-+}
+
+--- a/gcc/tree-tailcall.cc	2025-04-01 16:47:30.373502796 +0200
++++ b/gcc/tree-tailcall.cc	2025-04-02 09:02:35.572760732 +0200
+@@ -219,6 +219,23 @@ suitable_for_tail_call_opt_p (gcall *cal
+   return true;
+ }
+ 
++/* Return single successor edge ignoring EDGE_EH edges.  */
 +
-+[[gnu::always_inline]] inline void
-+corge (A)
++static edge
++single_non_eh_succ_edge (basic_block bb)
 +{
-+  if (v)
-+    qux ();
-+  [[gnu::musttail]] return foo (w);
++   edge e, ret = NULL;
++   edge_iterator ei;
++   FOR_EACH_EDGE (e, ei, bb->succs)
++    if ((e->flags & EDGE_EH) == 0)
++      {
++	gcc_assert (ret == NULL);
++	ret = e;
++      }
++  gcc_assert (ret);
++  return ret;
 +}
 +
-+void
-+freddy (A)
-+{
-+  int t;
-+  baz (&t);
-+  [[gnu::musttail]] return corge (A{});
-+}
-diff --git a/gcc/tree-tailcall.cc b/gcc/tree-tailcall.cc
-index e71341bfb2bc..b910dce7acbd 100644
---- a/gcc/tree-tailcall.cc
-+++ b/gcc/tree-tailcall.cc
-@@ -245,7 +245,7 @@ independent_of_stmt_p (tree expr, gimple *at, gimple_stmt_iterator gsi,
+ /* Checks whether the expression EXPR in stmt AT is independent of the
+    statement pointed to by GSI (in a sense that we already know EXPR's value
+    at GSI).  We use the fact that we are only called from the chain of
+@@ -245,7 +262,7 @@ independent_of_stmt_p (tree expr, gimple
    /* Mark the blocks in the chain leading to the end.  */
    at_bb = gimple_bb (at);
    call_bb = gimple_bb (gsi_stmt (gsi));
 -  for (bb = call_bb; bb != at_bb; bb = single_succ (bb))
-+  for (bb = call_bb; bb != at_bb; bb = find_fallthru_edge (bb->succs)->dest)
++  for (bb = call_bb; bb != at_bb; bb = single_non_eh_succ_edge (bb)->dest)
      bb->aux = &bb->aux;
    bb->aux = &bb->aux;
  
-@@ -289,7 +289,7 @@ independent_of_stmt_p (tree expr, gimple *at, gimple_stmt_iterator gsi,
+@@ -289,7 +306,7 @@ independent_of_stmt_p (tree expr, gimple
      }
  
    /* Unmark the blocks.  */
 -  for (bb = call_bb; bb != at_bb; bb = single_succ (bb))
-+  for (bb = call_bb; bb != at_bb; bb = find_fallthru_edge (bb->succs)->dest)
++  for (bb = call_bb; bb != at_bb; bb = single_non_eh_succ_edge (bb)->dest)
      bb->aux = NULL;
    bb->aux = NULL;
  
-@@ -462,6 +462,33 @@ maybe_error_musttail (gcall *call, const char *err, bool diag_musttail)
+@@ -462,6 +479,33 @@ maybe_error_musttail (gcall *call, const
      }
  }
  
@@ -213,7 +103,7 @@ index e71341bfb2bc..b910dce7acbd 100644
  /* Argument for compute_live_vars/live_vars_at_stmt and what compute_live_vars
     returns.  Computed lazily, but just once for the function.  */
  static live_vars_map *live_vars;
-@@ -612,14 +639,35 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail,
+@@ -612,14 +656,36 @@ find_tail_calls (basic_block bb, struct
    if ((stmt_could_throw_p (cfun, stmt)
         && !stmt_can_throw_external (cfun, stmt)) || EDGE_COUNT (bb->succs) > 1)
    {
@@ -247,7 +137,8 @@ index e71341bfb2bc..b910dce7acbd 100644
 +      }
 +
 +    if (!gimple_call_must_tail_p (call)
-+	|| !empty_eh_cleanup (e->dest, 20))
++	|| !empty_eh_cleanup (e->dest, 20)
++	|| EDGE_COUNT (bb->succs) > 2)
 +      {
 +	maybe_error_musttail (call,
 +			      _("call may throw exception caught locally "
@@ -257,7 +148,7 @@ index e71341bfb2bc..b910dce7acbd 100644
    }
  
    /* If the function returns a value, then at present, the tail call
-@@ -763,8 +811,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail,
+@@ -763,8 +829,7 @@ find_tail_calls (basic_block bb, struct
    a = NULL_TREE;
    auto_bitmap to_move_defs;
    auto_vec<gimple *> to_move_stmts;
@@ -267,19 +158,31 @@ index e71341bfb2bc..b910dce7acbd 100644
  
    abb = bb;
    agsi = gsi;
-@@ -776,8 +823,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret, bool only_musttail,
+@@ -776,8 +841,9 @@ find_tail_calls (basic_block bb, struct
  
        while (gsi_end_p (agsi))
  	{
 -	  ass_var = propagate_through_phis (ass_var, single_succ_edge (abb));
 -	  abb = single_succ (abb);
-+	  edge e = find_fallthru_edge (abb->succs);
++	  edge e = single_non_eh_succ_edge (abb);
 +	  ass_var = propagate_through_phis (ass_var, e);
 +	  abb = e->dest;
  	  agsi = gsi_start_bb (abb);
  	}
  
-@@ -1112,11 +1160,6 @@ static void
+@@ -851,6 +917,11 @@ find_tail_calls (basic_block bb, struct
+   /* See if this is a tail call we can handle.  */
+   if (is_noreturn)
+     {
++      if (gimple_call_internal_p (call))
++	{
++	  maybe_error_musttail (call, _("internal call"), diag_musttail);
++	  return;
++	}
+       tree rettype = TREE_TYPE (TREE_TYPE (current_function_decl));
+       tree calltype = TREE_TYPE (gimple_call_fntype (call));
+       if (!VOID_TYPE_P (rettype)
+@@ -1112,11 +1183,6 @@ static void
  decrease_profile (basic_block bb, profile_count count)
  {
    bb->count = bb->count - count;
@@ -291,16 +194,16 @@ index e71341bfb2bc..b910dce7acbd 100644
  }
  
  /* Eliminates tail call described by T.  TMP_VARS is a list of
-@@ -1181,7 +1224,7 @@ eliminate_tail_call (struct tailcall *t, class loop *&new_loop)
+@@ -1181,7 +1247,7 @@ eliminate_tail_call (struct tailcall *t,
    else
      {
        /* Number of executions of function has reduced by the tailcall.  */
 -      e = single_succ_edge (gsi_bb (t->call_gsi));
-+      e = find_fallthru_edge (gsi_bb (t->call_gsi)->succs);
++      e = single_non_eh_succ_edge (gsi_bb (t->call_gsi));
  
        profile_count count = e->count ();
  
-@@ -1196,8 +1239,7 @@ eliminate_tail_call (struct tailcall *t, class loop *&new_loop)
+@@ -1196,8 +1262,7 @@ eliminate_tail_call (struct tailcall *t,
  	decrease_profile (e->dest, count);
  
        /* Replace the call by a jump to the start of function.  */
@@ -310,7 +213,7 @@ index e71341bfb2bc..b910dce7acbd 100644
      }
    gcc_assert (e);
    PENDING_STMT (e) = NULL;
-@@ -1362,7 +1404,9 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls, bool only_musttail,
+@@ -1362,7 +1427,9 @@ tree_optimize_tail_calls_1 (bool opt_tai
      {
        basic_block bb;
        FOR_EACH_BB_FN (bb, cfun)
@@ -321,3 +224,129 @@ index e71341bfb2bc..b910dce7acbd 100644
  	  if (gimple *c = last_nondebug_stmt (bb))
  	    if (is_gimple_call (c)
  		&& gimple_call_must_tail_p (as_a <gcall *> (c))
+--- a/gcc/testsuite/g++.dg/opt/musttail3.C	2025-04-01 18:47:10.474945080 +0200
++++ b/gcc/testsuite/g++.dg/opt/musttail3.C	2025-04-01 18:49:27.063068029 +0200
+@@ -0,0 +1,41 @@
++// PR tree-optimization/119491
++// { dg-do compile { target { external_musttail && c++11 } } }
++// { dg-options "-O2" }
++
++struct A {
++  struct B {};
++  A () {}
++};
++void qux ();
++unsigned char v;
++A w;
++void foo (A);
++
++template <typename T>
++[[gnu::always_inline]] static inline void
++bar (int &)
++{
++}
++
++[[gnu::always_inline]] static inline void
++baz (int *)
++{
++  int r = 0;
++  bar<int> (r);
++}
++
++[[gnu::always_inline]] inline void
++corge (A)
++{
++  if (v)
++    qux ();
++  [[gnu::musttail]] return foo (w);
++}
++
++void
++freddy (A)
++{
++  int t;
++  baz (&t);
++  [[gnu::musttail]] return corge (A{});
++}
+--- a/gcc/testsuite/g++.dg/opt/musttail4.C	2025-04-01 19:10:56.389350911 +0200
++++ b/gcc/testsuite/g++.dg/opt/musttail4.C	2025-04-01 19:28:18.285020409 +0200
+@@ -0,0 +1,35 @@
++// { dg-do compile { target { external_musttail && c++11 } } }
++// { dg-options "-O2 -fexceptions" }
++
++struct S { ~S (); };
++volatile int v;
++struct T { ~T () { v = v + 1; } };
++struct U { ~U () {} };
++int foo ();
++
++int
++bar () noexcept
++{
++  [[gnu::musttail]] return foo ();	// { dg-error "cannot tail-call: call may throw exception that does not propagate" }
++}
++
++int
++baz ()
++{
++  S s;
++  [[gnu::musttail]] return foo ();	// { dg-error "cannot tail-call: other reasons" }
++}
++
++int
++qux ()
++{
++  T t;
++  [[gnu::musttail]] return foo ();	// { dg-error "cannot tail-call: other reasons" }
++}
++
++int
++corge ()
++{
++  U u;
++  [[gnu::musttail]] return foo ();
++}
+--- a/gcc/testsuite/g++.dg/opt/musttail5.C	2025-04-01 19:14:50.981127712 +0200
++++ b/gcc/testsuite/g++.dg/opt/musttail5.C	2025-04-01 19:11:25.249954382 +0200
+@@ -0,0 +1,41 @@
++// PR tree-optimization/119491
++// { dg-do compile { target { external_musttail && c++11 } } }
++// { dg-options "-O2" }
++
++struct A {
++  struct B {};
++  A () {}
++};
++void qux ();
++unsigned char v;
++A w;
++[[noreturn]] void foo (A);
++
++template <typename T>
++[[gnu::always_inline]] static inline void
++bar (int &)
++{
++}
++
++[[gnu::always_inline]] static inline void
++baz (int *)
++{
++  int r = 0;
++  bar<int> (r);
++}
++
++[[gnu::always_inline]] inline void
++corge (A)
++{
++  if (v)
++    qux ();
++  [[gnu::musttail]] return foo (w);
++}
++
++void
++freddy (A)
++{
++  int t;
++  baz (&t);
++  [[gnu::musttail]] return corge (A{});
++}

diff --git a/15.0.0/gentoo/README.history b/15.0.0/gentoo/README.history
index b497164..8223363 100644
--- a/15.0.0/gentoo/README.history
+++ b/15.0.0/gentoo/README.history
@@ -1,5 +1,6 @@
 51	????
 
+	- 80_all_PR119376-tailc-Don-t-fail-musttail-calls-if-they-use-or-could.patch
 	+ 82_all_PR119318-ipa-cp.patch
 	+ 83_all_PR119491-tailcall-eh.patch