[clang] [Clang][Parse] Delay parsing of noexcept-specifiers in friend function declarations (PR #90517)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 29 12:59:27 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Krystian Stasiowski (sdkrystian)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/90517.diff
1 Files Affected:
- (modified) clang/lib/Parse/ParseDecl.cpp (+14-6)
``````````diff
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) &&
``````````
</details>
https://github.com/llvm/llvm-project/pull/90517
More information about the cfe-commits
mailing list