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):
&gt; A complete-class context of a class (template) is a
&gt; - function body,
&gt; - default argument,
&gt; - default template argument,
&gt; - _noexcept-specifier_, or
&gt; - default member initializer
&gt;
&gt; 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 &amp; 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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to