Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Clang][Sema][Parse] Delay parsing of noexcept-specifiers in friend function declarations #90517

Merged
merged 5 commits into from
Apr 30, 2024

Conversation

sdkrystian
Copy link
Member

According to [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.

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), and any code which did compile should continue to do so.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Apr 29, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Apr 29, 2024

@llvm/pr-subscribers-clang

Author: Krystian Stasiowski (sdkrystian)

Changes

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 --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) &&

@sdkrystian
Copy link
Member Author

Note: This still needs a release note + test updates

@sdkrystian
Copy link
Member Author

This actually requires a little more work... (the delayed exception specification parsing code seems to only expect CXXMethodDecls). I'll take care of that tomorrow.

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test + release note.

In the future, please use 'draft pull request' when your patch is not ready for review/to be committed.

Copy link

github-actions bot commented Apr 30, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@sdkrystian sdkrystian force-pushed the delayed-parse-friend-except-spec branch from a68b482 to a327d79 Compare April 30, 2024 12:54
@sdkrystian sdkrystian changed the title [Clang][Parse] Delay parsing of noexcept-specifiers in friend function declarations [Clang][Sema][Parse] Delay parsing of noexcept-specifiers in friend function declarations Apr 30, 2024
@sdkrystian sdkrystian force-pushed the delayed-parse-friend-except-spec branch from e7bc177 to ea4534b Compare April 30, 2024 12:58
@sdkrystian sdkrystian force-pushed the delayed-parse-friend-except-spec branch from ea4534b to 78058da Compare April 30, 2024 13:00
@sdkrystian
Copy link
Member Author

PR updated with full implementation, tests, and release note

@sdkrystian sdkrystian force-pushed the delayed-parse-friend-except-spec branch from 4bc4d3b to 646e637 Compare April 30, 2024 13:04
Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a nit but otherwise LGTM
I'd like @erichkeane to look at it too

clang/include/clang/Sema/Sema.h Show resolved Hide resolved
Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corentin's request for a comment makes sense to me, or perhaps a better name th an just 'D'? So please take care of his request, but otherwise LGTM.

@sdkrystian sdkrystian force-pushed the delayed-parse-friend-except-spec branch from 646e637 to fafe75f Compare April 30, 2024 14:25
@sdkrystian sdkrystian merged commit f061a39 into llvm:main Apr 30, 2024
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants