[clang] [Clang] Ensure the method scope at the late parsing of noexcept specifiers (PR #98023)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 8 22:01:31 PDT 2024
https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/98023
>From 74d7184777e977ab3e83bfcae7e08e550ef32a39 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Mon, 8 Jul 2024 21:28:30 +0800
Subject: [PATCH 1/2] [Clang] Ensure the method scope at the late parsing of
noexcept specifiers
---
clang/docs/ReleaseNotes.rst | 2 +-
clang/lib/Parse/ParseCXXInlineMethods.cpp | 15 +++++++++++++--
.../expr/expr.prim/expr.prim.general/p3-0x.cpp | 5 +++--
clang/test/CodeGenCXX/mangle-exception-spec.cpp | 11 +++++++++++
clang/test/SemaCXX/cxx0x-noexcept-expression.cpp | 8 ++++++++
5 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 838cb69f647ee..b521de4515e1f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -958,7 +958,7 @@ Bug Fixes to C++ Support
- Fixed a type constraint substitution issue involving a generic lambda expression. (#GH93821)
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474)
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307),
- (#GH88081), (#GH89496), (#GH90669) and (#GH91633).
+ (#GH88081), (#GH89496), (#GH90669), (#GH91633) and (#GH97453).
- Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368).
- Clang now instantiates local constexpr functions eagerly for constant evaluators. (#GH35052), (#GH94849)
- Fixed a failed assertion when attempting to convert an integer representing the difference
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 943ce0fdde3a3..faab9c6b19caa 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -511,11 +511,13 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// and the end of the function-definition, member-declarator, or
// declarator.
CXXMethodDecl *Method;
+ FunctionDecl *FunctionToPush;
if (FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(LM.Method))
- Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ FunctionToPush = FunTmpl->getTemplatedDecl();
else
- Method = dyn_cast<CXXMethodDecl>(LM.Method);
+ FunctionToPush = cast<FunctionDecl>(LM.Method);
+ Method = dyn_cast<CXXMethodDecl>(FunctionToPush);
Sema::CXXThisScopeRAII ThisScope(
Actions, Method ? Method->getParent() : nullptr,
@@ -529,6 +531,15 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
ExprResult NoexceptExpr;
CachedTokens *ExceptionSpecTokens;
+ // Push a function scope so that tryCaptureVariable() can properly visit
+ // function scopes involving function parameters that are referenced inside
+ // the noexcept specifier e.g. through a lambda expression.
+ // Example:
+ // struct X {
+ // void ICE(int val) noexcept(noexcept([val]{}));
+ // };
+ Sema::SynthesizedFunctionScope Scope(Actions, FunctionToPush);
+
ExceptionSpecificationType EST
= tryParseExceptionSpecification(/*Delayed=*/false, SpecificationRange,
DynamicExceptions,
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
index b59cc175a1976..d50d05d17ab7a 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
@@ -113,8 +113,9 @@ namespace Static {
static auto g() -> decltype(this->m); // expected-error{{'this' cannot be used in a static member function declaration}}
static int h();
-
- static int i() noexcept(noexcept(m + 2)); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+
+ // The use of 'm' doesn't constitute an ODR use, so we don't have a reason to reject it.
+ static int i() noexcept(noexcept(m + 2));
};
auto X1::h() -> decltype(m) { return 0; } // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
diff --git a/clang/test/CodeGenCXX/mangle-exception-spec.cpp b/clang/test/CodeGenCXX/mangle-exception-spec.cpp
index 15f7a8b6cb504..1bc268e1b6ca4 100644
--- a/clang/test/CodeGenCXX/mangle-exception-spec.cpp
+++ b/clang/test/CodeGenCXX/mangle-exception-spec.cpp
@@ -47,3 +47,14 @@ template auto i<>(int()) -> int (*)();
// CHECK-CXX11: define {{.*}} @_Z1iIJfEEPDwiDpT_EFivEPS2_(
// CHECK-CXX17: define {{.*}} @_Z1iIJfEEPDwiDpT_EFivES3_(
template auto i<float>(int()) -> int (*)();
+
+template <class T>
+struct X1 {
+ T m;
+ static void j(int (X1::*)() noexcept(noexcept(m + 2)));
+};
+
+void foo() {
+ // CHECK-CXX17: call {{.*}} @_ZN2X1IiE1jEMS0_DoFivE(
+ X1<int>::j(nullptr);
+}
diff --git a/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp b/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp
index c616a77f36619..53d23580d02a2 100644
--- a/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp
+++ b/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp
@@ -157,3 +157,11 @@ void f5() {
// expected-error at -1 {{no member named 'non_existent' in 'typeid_::X<true>'}}
}
} // namespace typeid_
+
+namespace GH97453 {
+
+struct X {
+ void ICE(int that) noexcept(noexcept([that]() {}));
+};
+
+} // namespace GH97453
>From 58f8ba2d6cb8809078059bbcab86d691e55efe4c Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 9 Jul 2024 12:53:39 +0800
Subject: [PATCH 2/2] Comments
---
clang/lib/Parse/ParseCXXInlineMethods.cpp | 15 +++++++--------
.../expr/expr.prim/expr.prim.general/p3-0x.cpp | 5 ++++-
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index faab9c6b19caa..2df84e78d7f0e 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -523,14 +523,6 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
Actions, Method ? Method->getParent() : nullptr,
Method ? Method->getMethodQualifiers() : Qualifiers{},
Method && getLangOpts().CPlusPlus11);
-
- // Parse the exception-specification.
- SourceRange SpecificationRange;
- SmallVector<ParsedType, 4> DynamicExceptions;
- SmallVector<SourceRange, 4> DynamicExceptionRanges;
- ExprResult NoexceptExpr;
- CachedTokens *ExceptionSpecTokens;
-
// Push a function scope so that tryCaptureVariable() can properly visit
// function scopes involving function parameters that are referenced inside
// the noexcept specifier e.g. through a lambda expression.
@@ -540,6 +532,13 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// };
Sema::SynthesizedFunctionScope Scope(Actions, FunctionToPush);
+ // Parse the exception-specification.
+ SourceRange SpecificationRange;
+ SmallVector<ParsedType, 4> DynamicExceptions;
+ SmallVector<SourceRange, 4> DynamicExceptionRanges;
+ ExprResult NoexceptExpr;
+ CachedTokens *ExceptionSpecTokens;
+
ExceptionSpecificationType EST
= tryParseExceptionSpecification(/*Delayed=*/false, SpecificationRange,
DynamicExceptions,
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
index d50d05d17ab7a..203490632dffb 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
@@ -114,7 +114,10 @@ namespace Static {
static int h();
- // The use of 'm' doesn't constitute an ODR use, so we don't have a reason to reject it.
+ // [expr.prim.id.general]p4:
+ // An id-expression that denotes a non-static data member... can only be used:
+ // ...
+ // (4.3) if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
static int i() noexcept(noexcept(m + 2));
};
More information about the cfe-commits
mailing list