This revision was automatically updated to reflect the committed changes. Closed by commit rGc25acec84594: [Coroutines] Handle dependent promise types for final_suspend non-throw check (authored by lxfind).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82332/new/ https://reviews.llvm.org/D82332 Files: clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaCoroutine.cpp clang/lib/Sema/TreeTransform.h clang/test/SemaCXX/coroutine-final-suspend-noexcept.cpp
Index: clang/test/SemaCXX/coroutine-final-suspend-noexcept.cpp =================================================================== --- clang/test/SemaCXX/coroutine-final-suspend-noexcept.cpp +++ clang/test/SemaCXX/coroutine-final-suspend-noexcept.cpp @@ -11,27 +11,27 @@ template <class Promise = void> struct coroutine_handle { - static coroutine_handle from_address(void *); // expected-note {{must be declared with 'noexcept'}} + static coroutine_handle from_address(void *); // expected-note 2 {{must be declared with 'noexcept'}} }; template <> struct coroutine_handle<void> { template <class PromiseType> - coroutine_handle(coroutine_handle<PromiseType>); // expected-note {{must be declared with 'noexcept'}} + coroutine_handle(coroutine_handle<PromiseType>); // expected-note 2 {{must be declared with 'noexcept'}} }; struct suspend_never { - bool await_ready() { return true; } // expected-note {{must be declared with 'noexcept'}} - void await_suspend(coroutine_handle<>) {} // expected-note {{must be declared with 'noexcept'}} - void await_resume() {} // expected-note {{must be declared with 'noexcept'}} - ~suspend_never() noexcept(false); // expected-note {{must be declared with 'noexcept'}} + bool await_ready() { return true; } // expected-note 2 {{must be declared with 'noexcept'}} + void await_suspend(coroutine_handle<>) {} // expected-note 2 {{must be declared with 'noexcept'}} + void await_resume() {} // expected-note 2 {{must be declared with 'noexcept'}} + ~suspend_never() noexcept(false); // expected-note 2 {{must be declared with 'noexcept'}} }; struct suspend_always { bool await_ready() { return false; } void await_suspend(coroutine_handle<>) {} void await_resume() {} - suspend_never operator co_await(); // expected-note {{must be declared with 'noexcept'}} - ~suspend_always() noexcept(false); // expected-note {{must be declared with 'noexcept'}} + suspend_never operator co_await(); // expected-note 2 {{must be declared with 'noexcept'}} + ~suspend_always() noexcept(false); // expected-note 2 {{must be declared with 'noexcept'}} }; } // namespace experimental @@ -50,7 +50,7 @@ struct promise_type { coro_t get_return_object(); suspend_never initial_suspend(); - suspend_always final_suspend(); // expected-note {{must be declared with 'noexcept'}} + suspend_always final_suspend(); // expected-note 2 {{must be declared with 'noexcept'}} void return_void(); static void unhandled_exception(); }; @@ -60,3 +60,13 @@ A a{}; co_await a; } + +template <typename T> +coro_t f_dep(T n) { // expected-error {{the expression 'co_await __promise.final_suspend()' is required to be non-throwing}} + A a{}; + co_await a; +} + +void foo() { + f_dep<int>(5); // expected-note {{in instantiation of function template specialization 'f_dep<int>' requested here}} +} Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -7630,7 +7630,8 @@ return StmtError(); StmtResult FinalSuspend = getDerived().TransformStmt(S->getFinalSuspendStmt()); - if (FinalSuspend.isInvalid()) + if (FinalSuspend.isInvalid() || + !SemaRef.checkFinalSuspendNoThrow(FinalSuspend.get())) return StmtError(); ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get()); assert(isa<Expr>(InitSuspend.get()) && isa<Expr>(FinalSuspend.get())); Index: clang/lib/Sema/SemaCoroutine.cpp =================================================================== --- clang/lib/Sema/SemaCoroutine.cpp +++ clang/lib/Sema/SemaCoroutine.cpp @@ -642,7 +642,6 @@ } else if (SC == Expr::CallExprClass || SC == Expr::CXXMemberCallExprClass || SC == Expr::CXXOperatorCallExprClass) { if (!cast<CallExpr>(E)->isTypeDependent()) { - // FIXME: Handle dependent types. checkDeclNoexcept(cast<CallExpr>(E)->getCalleeDecl()); auto ReturnType = cast<CallExpr>(E)->getCallReturnType(S.getASTContext()); // Check the destructor of the call return type, if any. @@ -662,22 +661,20 @@ } } -/// Check that the expression co_await promise.final_suspend() shall not be -/// potentially-throwing. -static bool checkNoThrow(Sema &S, const Stmt *FinalSuspend) { +bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) { llvm::SmallPtrSet<const Decl *, 4> ThrowingDecls; // We first collect all declarations that should not throw but not declared // with noexcept. We then sort them based on the location before printing. // This is to avoid emitting the same note multiple times on the same // declaration, and also provide a deterministic order for the messages. - checkNoThrow(S, FinalSuspend, ThrowingDecls); + checkNoThrow(*this, FinalSuspend, ThrowingDecls); auto SortedDecls = llvm::SmallVector<const Decl *, 4>{ThrowingDecls.begin(), ThrowingDecls.end()}; sort(SortedDecls, [](const Decl *A, const Decl *B) { return A->getEndLoc() < B->getEndLoc(); }); for (const auto *D : SortedDecls) { - S.Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept); + Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept); } return ThrowingDecls.empty(); } @@ -724,7 +721,7 @@ return true; StmtResult FinalSuspend = buildSuspends("final_suspend"); - if (FinalSuspend.isInvalid() || !checkNoThrow(*this, FinalSuspend.get())) + if (FinalSuspend.isInvalid() || !checkFinalSuspendNoThrow(FinalSuspend.get())) return true; ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get()); Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -9804,6 +9804,9 @@ void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc, SourceLocation FuncLoc); + /// Check that the expression co_await promise.final_suspend() shall not be + /// potentially-throwing. + bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend); //===--------------------------------------------------------------------===// // OpenCL extensions.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits