From dc399dfe1265a1222b7cfa0fc35533768a8a1a8a Mon Sep 17 00:00:00 2001
From: Patrick Palka <ppalka@redhat.com>
Date: Tue, 9 May 2023 15:06:34 -0400
Subject: [PATCH] c++: noexcept-spec from nested class confusion [PR109761]

When late processing a noexcept-spec from a nested class after completion
of the outer class (since it's a complete-class context), we pass the wrong
class context to noexcept_override_late_checks -- the outer class type
instead of the nested class type -- which leads to bogus errors in the
below test.

This patch fixes this by making noexcept_override_late_checks obtain the
class context directly via DECL_CONTEXT instead of via an additional
parameter.

	PR c++/109761

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_class_specifier): Don't pass a class
	context to noexcept_override_late_checks.
	(noexcept_override_late_checks): Remove 'type' parameter
	and use DECL_CONTEXT of 'fndecl' instead.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/noexcept78.C: New test.

(cherry picked from commit c13906f258fb34b3e0c90ddc8d9191dd72f3da0e)
---
 gcc/cp/parser.cc                        | 13 ++++++-------
 gcc/testsuite/g++.dg/cpp0x/noexcept78.C | 16 ++++++++++++++++
 2 files changed, 22 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept78.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a6341b98af21..560ed2f2298f 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -251,7 +251,7 @@ static cp_token_cache *cp_token_cache_new
 static tree cp_parser_late_noexcept_specifier
   (cp_parser *, tree);
 static void noexcept_override_late_checks
-  (tree, tree);
+  (tree);
 
 static void cp_parser_initial_pragma
   (cp_token *);
@@ -26426,7 +26426,7 @@ cp_parser_class_specifier (cp_parser* parser)
 	  /* The finish_struct call above performed various override checking,
 	     but it skipped unparsed noexcept-specifier operands.  Now that we
 	     have resolved them, check again.  */
-	  noexcept_override_late_checks (type, decl);
+	  noexcept_override_late_checks (decl);
 
 	  /* Remove any member-function parameters from the symbol table.  */
 	  pop_injected_parms ();
@@ -28208,14 +28208,13 @@ cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg)
 }
 
 /* Perform late checking of overriding function with respect to their
-   noexcept-specifiers.  TYPE is the class and FNDECL is the function
-   that potentially overrides some virtual function with the same
-   signature.  */
+   noexcept-specifiers.  FNDECL is the member function that potentially
+   overrides some virtual function with the same signature.  */
 
 static void
-noexcept_override_late_checks (tree type, tree fndecl)
+noexcept_override_late_checks (tree fndecl)
 {
-  tree binfo = TYPE_BINFO (type);
+  tree binfo = TYPE_BINFO (DECL_CONTEXT (fndecl));
   tree base_binfo;
 
   if (DECL_STATIC_FUNCTION_P (fndecl))
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept78.C b/gcc/testsuite/g++.dg/cpp0x/noexcept78.C
new file mode 100644
index 000000000000..e8156eb7c6f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept78.C
@@ -0,0 +1,16 @@
+// PR c++/109761
+// { dg-do compile { target c++11 } }
+
+struct base {
+  virtual void foo() noexcept { }
+  virtual ~base() { }
+};
+
+struct outer : base {
+  struct nested {
+    void foo() noexcept(noexcept(g())); // { dg-bogus "looser" }
+    ~nested() noexcept(noexcept(g()));  // { dg-bogus "looser" }
+  };
+  static void g();
+};
+
-- 
GitLab