Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit db5bc8e

Browse files
authored
[Clang] Warn about [[noreturn]] on coroutines (#127623)
Declaring a coroutine `[[noreturn]]` doesn't make sense, because it will always return its handle. Clang previously crashed when trying to warn about this (diagnostic ID was 0). Fixes #127327.
1 parent 8529bd7 commit db5bc8e

File tree

5 files changed

+43
-4
lines changed

5 files changed

+43
-4
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

+3
Original file line numberDiff line numberDiff line change
@@ -10606,6 +10606,9 @@ def warn_noreturn_function_has_return_expr : Warning<
1060610606
def warn_falloff_noreturn_function : Warning<
1060710607
"function declared 'noreturn' should not return">,
1060810608
InGroup<InvalidNoreturn>;
10609+
def warn_noreturn_coroutine : Warning<
10610+
"coroutine %0 cannot be declared 'noreturn' as it always returns a coroutine handle">,
10611+
InGroup<InvalidNoreturn>;
1060910612
def err_noreturn_block_has_return_expr : Error<
1061010613
"block declared 'noreturn' should not return">;
1061110614
def err_carries_dependency_missing_on_first_decl : Error<

clang/lib/Sema/AnalysisBasedWarnings.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,12 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
697697
return;
698698
SourceLocation LBrace = Body->getBeginLoc(), RBrace = Body->getEndLoc();
699699
auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
700-
if (IsCoroutine)
701-
S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType();
702-
else
700+
if (IsCoroutine) {
701+
if (DiagID != 0)
702+
S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType();
703+
} else {
703704
S.Diag(Loc, DiagID);
705+
}
704706
};
705707

706708
// cpu_dispatch functions permit empty function bodies for ICC compatibility.

clang/lib/Sema/SemaCoroutine.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,10 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
11761176
for (AddrLabelExpr *ALE : Fn->AddrLabels)
11771177
Diag(ALE->getBeginLoc(), diag::err_coro_invalid_addr_of_label);
11781178

1179+
// Coroutines always return a handle, so they can't be [[noreturn]].
1180+
if (FD->isNoReturn())
1181+
Diag(FD->getLocation(), diag::warn_noreturn_coroutine) << FD;
1182+
11791183
CoroutineStmtBuilder Builder(*this, *FD, *Fn, Body);
11801184
if (Builder.isInvalid() || !Builder.buildStatements())
11811185
return FD->setInvalidDecl();

clang/lib/Sema/SemaStmt.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -3910,7 +3910,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
39103910
FnRetType = FD->getReturnType();
39113911
if (FD->hasAttrs())
39123912
Attrs = &FD->getAttrs();
3913-
if (FD->isNoReturn())
3913+
if (FD->isNoReturn() && !getCurFunction()->isCoroutine())
39143914
Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << FD;
39153915
if (FD->isMain() && RetValExp)
39163916
if (isa<CXXBoolLiteralExpr>(RetValExp))
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -Winvalid-noreturn -verify
2+
3+
#include "Inputs/std-coroutine.h"
4+
5+
struct Promise;
6+
7+
struct Awaitable {
8+
bool await_ready();
9+
void await_suspend(std::coroutine_handle<>);
10+
void await_resume();
11+
};
12+
13+
struct Coro : std::coroutine_handle<> {
14+
using promise_type = Promise;
15+
};
16+
17+
struct Promise {
18+
Coro get_return_object();
19+
std::suspend_always initial_suspend() noexcept;
20+
std::suspend_always final_suspend() noexcept;
21+
void return_void();
22+
void unhandled_exception();
23+
};
24+
25+
[[noreturn]] Coro test() { // expected-warning {{coroutine 'test' cannot be declared 'noreturn' as it always returns a coroutine handle}}
26+
co_await Awaitable{};
27+
}
28+
29+
// NO warning here. This could be a regular function returning a `Coro` object.
30+
[[noreturn]] Coro test2();

0 commit comments

Comments
 (0)