[clang] d87e2ea - [Clang] Diagnose `co_await` expressions in default arguments of nested functions (#191817)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 15 07:01:12 PDT 2026
Author: Corentin Jabot
Date: 2026-04-15T16:01:06+02:00
New Revision: d87e2eadbb124e34537df1e75c73b71dd09a7a30
URL: https://github.com/llvm/llvm-project/commit/d87e2eadbb124e34537df1e75c73b71dd09a7a30
DIFF: https://github.com/llvm/llvm-project/commit/d87e2eadbb124e34537df1e75c73b71dd09a7a30.diff
LOG: [Clang] Diagnose `co_await` expressions in default arguments of nested functions (#191817)
co_await/co_yield expressions are not allowed in default arguments. We
were checking they do not appear outside of function contexts, which
include default arguments of the corresponding function, but it missed
default arguments of functions declared in the body of another
functions.
Because parsing default argument isn't done in a dedicated scope, we do
additional checks in `ActOnParamDefaultArgument`. Because the checks is
done in two places, we cannot introduce a more precise diagnostic.
It might be worth considering a parse scope for default arguments in the
future.
Fixes #98923
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/SemaCXX/coroutines.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8d74dd8bc9699..083bc696f2f79 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -446,6 +446,7 @@ Bug Fixes to C++ Support
template parameters when one of its parameters is also a pack. (#GH181166)
- Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639)
- Fixed an alias template CTAD crash.
+- Correctly diagnose uses of ``co_await`` / ``co_yield`` in the default argument of nested function declarations. (#GH98923)
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
- Clang incorrectly instantiated variable specializations outside of the immediate context. (#GH54439)
- Fixed a crash when instantiating an invalid out-of-line static data member definition in a local class. (#GH176152)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 6647e52535114..6923d4df6f97f 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -83,6 +83,8 @@ class CheckDefaultArgumentVisitor
bool VisitCXXThisExpr(const CXXThisExpr *ThisE);
bool VisitLambdaExpr(const LambdaExpr *Lambda);
bool VisitPseudoObjectExpr(const PseudoObjectExpr *POE);
+ bool VisitCoawaitExpr(const CoawaitExpr *E);
+ bool VisitCoyieldExpr(const CoyieldExpr *E);
};
/// VisitExpr - Visit all of the children of this expression.
@@ -178,6 +180,23 @@ bool CheckDefaultArgumentVisitor::VisitLambdaExpr(const LambdaExpr *Lambda) {
}
return Invalid;
}
+
+bool CheckDefaultArgumentVisitor::VisitCoawaitExpr(const CoawaitExpr *E) {
+ // [expr.await] An await-expression shall not appear in a default argument.
+ // Note that this is generally diagnosed by isValidCoroutineContext,
+ // however isValidCoroutineContext misses default argument in nested
+ // function declarations.
+ S.Diag(E->getBeginLoc(), diag::err_coroutine_outside_function)
+ << "co_await" << E->getSourceRange();
+ return true;
+}
+
+bool CheckDefaultArgumentVisitor::VisitCoyieldExpr(const CoyieldExpr *E) {
+ S.Diag(E->getBeginLoc(), diag::err_coroutine_outside_function)
+ << "co_yield" << E->getSourceRange();
+ return true;
+}
+
} // namespace
void
diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp
index 098c1c21a5962..dcb670ea13173 100644
--- a/clang/test/SemaCXX/coroutines.cpp
+++ b/clang/test/SemaCXX/coroutines.cpp
@@ -1545,3 +1545,24 @@ void warn_always_inline() { // expected-warning {{this coroutine may be split in
void warn_gnu_always_inline() { // expected-warning {{this coroutine may be split into pieces; not every piece is guaranteed to be inlined}}
co_await suspend_always{};
}
+
+namespace GH98923 {
+struct Awaiter : suspend_never {
+ int await_resume() { return 0; }
+};
+
+void f(int x = co_await Awaiter{});
+// expected-error at -1 {{'co_await' cannot be used outside a function}}
+
+void g() {
+ void g1(int x = co_await Awaiter{});
+ // expected-error at -1 {{'co_await' cannot be used outside a function}}
+ void g2(int x = ((co_yield 0), 1));
+ // expected-error at -1 {{'co_yield' cannot be used outside a function}}
+ auto g3 = [&](int x = co_await Awaiter{}) -> void{
+ // expected-error at -1 {{'co_await' cannot be used outside a function}}
+ co_return 0;
+ };
+}
+
+}
More information about the cfe-commits
mailing list