The code is as follows: template <typename T> struct A { void f() noexcept(noexcept(m.f())) { m.f(); } T m; }; struct B { void f(); }; int main() { A<B> a; a.f(); } g++ produces: error: 'm' was not declared in this scope void f() noexcept(noexcept(m.f())) { What gives? Surely A is complete in this context and we can see m? I tried clang++. It accepts the code.
Confirmed, noexcept-specifier is a complete-class context. Simpler test: struct S { void g() noexcept(noexcept(i)) { } int i; };
Patch available: <https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00511.html>.
Author: mpolacek Date: Sat Jun 22 15:14:30 2019 New Revision: 272586 URL: https://gcc.gnu.org/viewcvs?rev=272586&root=gcc&view=rev Log: PR c++/86476 - noexcept-specifier is a complete-class context. PR c++/52869 * cp-tree.def (DEFAULT_ARG): Update commentary. * cp-tree.h (UNPARSED_NOEXCEPT_SPEC_P): New macro. (tree_default_arg): Use tree_base instead of tree_common. (do_push_parm_decls, maybe_check_overriding_exception_spec): Declare. * decl.c (do_push_parm_decls): New function, broken out of... (store_parm_decls): ...here. Call it. * except.c (nothrow_spec_p): Accept DEFAULT_ARG in the assert. * parser.c (cp_parser_noexcept_specification_opt, cp_parser_late_noexcept_specifier, noexcept_override_late_checks): Forward-declare. (unparsed_noexcepts): New macro. (push_unparsed_function_queues): Update initializer. (cp_parser_direct_declarator): Pass FRIEND_P to cp_parser_exception_specification_opt. (inject_parm_decls): New. (pop_injected_parms): New. (cp_parser_class_specifier_1): Implement delayed parsing of noexcept-specifiers. (cp_parser_save_noexcept): New. (cp_parser_late_noexcept_specifier): New. (noexcept_override_late_checks): New. (cp_parser_noexcept_specification_opt): Add FRIEND_P parameter. Call cp_parser_save_noexcept instead of the normal processing if needed. (cp_parser_exception_specification_opt): Add FRIEND_P parameter and pass it to cp_parser_noexcept_specification_opt. (cp_parser_save_member_function_body): Fix comment. (cp_parser_save_default_args): Maybe save the noexcept-specifier to post process. (cp_parser_transaction): Update call to cp_parser_noexcept_specification_opt. (cp_parser_transaction_expression): Likewise. * parser.h (cp_unparsed_functions_entry): Add new field to carry a noexcept-specifier. * pt.c (dependent_type_p_r): Handle unparsed noexcept expression. * search.c (maybe_check_overriding_exception_spec): New function, broken out of... (check_final_overrider): ...here. Call maybe_check_overriding_exception_spec. * tree.c (canonical_eh_spec): Handle UNPARSED_NOEXCEPT_SPEC_P. (cp_tree_equal): Handle DEFAULT_ARG. * g++.dg/cpp0x/noexcept45.C: New test. * g++.dg/cpp0x/noexcept46.C: New test. * g++.dg/cpp0x/noexcept47.C: New test. * g++.dg/cpp0x/noexcept48.C: New test. * g++.dg/cpp0x/noexcept49.C: New test. * g++.dg/cpp0x/noexcept50.C: New test. * g++.dg/cpp0x/noexcept51.C: New test. * g++.dg/cpp0x/noexcept52.C: New test. * g++.dg/cpp0x/noexcept53.C: New test. * g++.dg/eh/shadow1.C: Adjust dg-error. Added: trunk/gcc/testsuite/g++.dg/cpp0x/noexcept45.C trunk/gcc/testsuite/g++.dg/cpp0x/noexcept46.C trunk/gcc/testsuite/g++.dg/cpp0x/noexcept47.C trunk/gcc/testsuite/g++.dg/cpp0x/noexcept48.C trunk/gcc/testsuite/g++.dg/cpp0x/noexcept49.C trunk/gcc/testsuite/g++.dg/cpp0x/noexcept50.C trunk/gcc/testsuite/g++.dg/cpp0x/noexcept51.C trunk/gcc/testsuite/g++.dg/cpp0x/noexcept52.C trunk/gcc/testsuite/g++.dg/cpp0x/noexcept53.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.def trunk/gcc/cp/cp-tree.h trunk/gcc/cp/decl.c trunk/gcc/cp/except.c trunk/gcc/cp/parser.c trunk/gcc/cp/parser.h trunk/gcc/cp/pt.c trunk/gcc/cp/search.c trunk/gcc/cp/tree.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/eh/shadow1.C
Fixed.
Since the resolution of CWG 1330 is enabled here (plus PR 109761), https://gcc.gnu.org/projects/cxx-dr-status.html should be updated.
(In reply to frankhb1989 from comment #5) > Since the resolution of CWG 1330 is enabled here (plus PR 109761), > https://gcc.gnu.org/projects/cxx-dr-status.html should be updated. Updated, thanks.