Skip to content

Commit f52a467

Browse files
authored
[Clang] Ensure the method scope at the late parsing of noexcept specifiers (#98023)
Previously, we only pushed the function scope once we entered the function definition, whereas tryCaptureVariable() requires at least one function scope available when ParmVarDecls being captured have been owned by a function. This led to problems parsing the noexcept specifiers, as the DeclRefExprs inside them were improperly computed. Fixes #97453
1 parent 6dd1f08 commit f52a467

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,7 @@ Bug Fixes to C++ Support
10111011
- Fixed a type constraint substitution issue involving a generic lambda expression. (#GH93821)
10121012
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474)
10131013
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307),
1014-
(#GH88081), (#GH89496), (#GH90669) and (#GH91633).
1014+
(#GH88081), (#GH89496), (#GH90669), (#GH91633) and (#GH97453).
10151015
- Fixed a crash in constraint instantiation under nested lambdas with dependent parameters.
10161016
- Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368).
10171017
- Clang now instantiates local constexpr functions eagerly for constant evaluators. (#GH35052), (#GH94849)

clang/lib/Parse/ParseCXXInlineMethods.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,11 +511,28 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
511511
// and the end of the function-definition, member-declarator, or
512512
// declarator.
513513
CXXMethodDecl *Method;
514+
FunctionDecl *FunctionToPush;
514515
if (FunctionTemplateDecl *FunTmpl
515516
= dyn_cast<FunctionTemplateDecl>(LM.Method))
516-
Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
517+
FunctionToPush = FunTmpl->getTemplatedDecl();
517518
else
518-
Method = dyn_cast<CXXMethodDecl>(LM.Method);
519+
FunctionToPush = cast<FunctionDecl>(LM.Method);
520+
Method = dyn_cast<CXXMethodDecl>(FunctionToPush);
521+
522+
// Push a function scope so that tryCaptureVariable() can properly visit
523+
// function scopes involving function parameters that are referenced inside
524+
// the noexcept specifier e.g. through a lambda expression.
525+
// Example:
526+
// struct X {
527+
// void ICE(int val) noexcept(noexcept([val]{}));
528+
// };
529+
// Setup the CurScope to match the function DeclContext - we have such
530+
// assumption in IsInFnTryBlockHandler().
531+
ParseScope FnScope(this, Scope::FnScope);
532+
Sema::ContextRAII FnContext(Actions, FunctionToPush,
533+
/*NewThisContext=*/false);
534+
Sema::FunctionScopeRAII PopFnContext(Actions);
535+
Actions.PushFunctionScope();
519536

520537
Sema::CXXThisScopeRAII ThisScope(
521538
Actions, Method ? Method->getParent() : nullptr,

clang/test/SemaCXX/cxx0x-noexcept-expression.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,21 @@ void f5() {
157157
// expected-error@-1 {{no member named 'non_existent' in 'typeid_::X<true>'}}
158158
}
159159
} // namespace typeid_
160+
161+
namespace GH97453 {
162+
163+
struct UnconstrainedCtor {
164+
int value_;
165+
166+
template <typename T>
167+
constexpr UnconstrainedCtor(T value) noexcept(noexcept(value_ = value))
168+
: value_(static_cast<int>(value)) {}
169+
};
170+
171+
UnconstrainedCtor U(42);
172+
173+
struct X {
174+
void ICE(int that) noexcept(noexcept([that]() {}));
175+
};
176+
177+
} // namespace GH97453

0 commit comments

Comments
 (0)