https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/90517
According to [[class.mem.general] p8](http://eel.is/c++draft/class.mem.general#8): > A complete-class context of a class (template) is a > - function body, > - default argument, > - default template argument, > - _noexcept-specifier_, or > - default member initializer > > within the member-specification of the class or class template. When testing #90152, it came to my attention that we do _not_ consider the _noexcept-specifier_ of a friend function declaration to be a complete-class context (something which the Microsoft standard library depends on). Although a comment states that this is "consistent with what other implementations do", the only other implementation that exhibits this behavior is GCC (MSVC and EDG both late-parse the _noexcept-specifier_). This patch changes _noexcept-specifiers_ of friend function declarations to be late parsed, which is in agreement with the standard & majority of implementations. Pre-#90152, our existing implementation falls "in between" the implementation consensus: within non-template classes, we would not find latter declared members (qualified and unqualified), while within class templates we would not find latter declared member when named with a unqualified name, we would find members named with a qualified name (even when lookup context is the current instantiation). Therefore, this _shouldn't_ be a breaking change -- any code that didn't compile will continue to not compile (since a _noexcept-specifier_ is not part of the [deduction substitution loci](http://eel.is/c++draft/temp.deduct.general#7)), and any code which did compile should continue to do so. >From 3f5feb2b17c06f6e001e9324e90eef07fd720539 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Mon, 29 Apr 2024 15:34:40 -0400 Subject: [PATCH] [Clang][Parse] Delay parsing of noexcept-specifiers in friend function declarations --- clang/lib/Parse/ParseDecl.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index a7846e102a43c7..93950e27a08f35 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -7388,12 +7388,20 @@ void Parser::ParseFunctionDeclarator(Declarator &D, std::optional<Sema::CXXThisScopeRAII> ThisScope; InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope); - // Parse exception-specification[opt]. - // FIXME: Per [class.mem]p6, all exception-specifications at class scope - // should be delayed, including those for non-members (eg, friend - // declarations). But only applying this to member declarations is - // consistent with what other implementations do. - bool Delayed = D.isFirstDeclarationOfMember() && + // C++ [class.mem.general]p8: + // A complete-class context of a class (template) is a + // - function body, + // - default argument, + // - default template argument, + // - noexcept-specifier, or + // - default member initializer + // within the member-specification of the class or class template. + // + // Parse exception-specification[opt]. If we are in the + // member-specification of a class or class template, this is a + // complete-class context and parsing of the noexcept-specifier should be + // delayed (even if this is a friend declaration). + bool Delayed = D.getContext() == DeclaratorContext::Member && D.isFunctionDeclaratorAFunctionDeclaration(); if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) && GetLookAheadToken(0).is(tok::kw_noexcept) && _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits