[PATCH] D51741: [coro]Pass rvalue reference for named local variable to return_value
tks2103 created this revision. tks2103 added reviewers: modocache, GorNishanov. Herald added a subscriber: cfe-commits. tks2103 edited the summary of this revision. Addressing https://bugs.llvm.org/show_bug.cgi?id=37265. Implements [class.copy]/33 of coroutines TS When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a return or co_return statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for the copy or the return_value overload to call is first performed as if the object were designated by an rvalue. Repository: rC Clang https://reviews.llvm.org/D51741 Files: lib/Sema/SemaCoroutine.cpp test/SemaCXX/coroutine-rvo.cpp Index: test/SemaCXX/coroutine-rvo.cpp === --- /dev/null +++ test/SemaCXX/coroutine-rvo.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -stdlib=libc++ -std=c++1z -fcoroutines-ts -fsyntax-only + +namespace std::experimental { +template struct coroutine_handle { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; + +template <> struct coroutine_handle { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template + coroutine_handle(coroutine_handle) noexcept; +}; + +template +struct void_t_imp { + using type = void; +}; +template +using void_t = typename void_t_imp::type; + +template +struct traits_sfinae_base {}; + +template +struct traits_sfinae_base> { + using promise_type = typename T::promise_type; +}; + +template +struct coroutine_traits : public traits_sfinae_base {}; +} + +struct suspend_never { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct MoveOnly { + MoveOnly() {}; + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&) noexcept {}; + ~MoveOnly() {}; +}; + +template +struct task { + struct promise_type { +auto initial_suspend() { return suspend_never{}; } +auto final_suspend() { return suspend_never{}; } +auto get_return_object() { return task{}; } +static void unhandled_exception() {} +void return_value(T&& value) {} + }; +}; + +task f() { + MoveOnly value; + co_return value; +} + +int main() { + f(); + return 0; +} + +// expected-no-diagnostics Index: lib/Sema/SemaCoroutine.cpp === --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -841,6 +841,16 @@ E = R.get(); } + // Move the return value if we can + if (E) { +InitializedEntity Entity = +InitializedEntity::InitializeResult(Loc, E->getType(), false); +ExprResult MoveResult = +this->PerformMoveOrCopyInitialization(Entity, nullptr, E->getType(), E); +if (MoveResult.get()) + E = MoveResult.get(); + } + // FIXME: If the operand is a reference to a variable that's about to go out // of scope, we should treat the operand as an xvalue for this overload // resolution. Index: test/SemaCXX/coroutine-rvo.cpp === --- /dev/null +++ test/SemaCXX/coroutine-rvo.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -stdlib=libc++ -std=c++1z -fcoroutines-ts -fsyntax-only + +namespace std::experimental { +template struct coroutine_handle { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; + +template <> struct coroutine_handle { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template + coroutine_handle(coroutine_handle) noexcept; +}; + +template +struct void_t_imp { + using type = void; +}; +template +using void_t = typename void_t_imp::type; + +template +struct traits_sfinae_base {}; + +template +struct traits_sfinae_base> { + using promise_type = typename T::promise_type; +}; + +template +struct coroutine_traits : public traits_sfinae_base {}; +} + +struct suspend_never { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct MoveOnly { + MoveOnly() {}; + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&) noexcept {}; + ~MoveOnly() {}; +}; + +template +struct task { + struct promise_type { +auto initial_suspend() { return suspend_never{}; } +auto final_suspend() { return suspend_never{}; } +auto get_return_object() { return task{}; } +static void unhandled_exception() {} +void return_value(T&& value) {} + }; +}; + +task f() { + Mov
[PATCH] D51741: [coro]Pass rvalue reference for named local variable to return_value
tks2103 added a comment. currently changes the behavior for a few cases: something like void coro() { co_return {4}; } throws `illegal initializer type 'void'` Repository: rC Clang https://reviews.llvm.org/D51741 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51741: [coro]Pass rvalue reference for named local variable to return_value
tks2103 added a comment. also fails https://github.com/llvm-mirror/clang/blob/master/test/SemaCXX/coroutines.cpp#L494 with `address of overloaded function 'g' does not match required type ''` also fails https://github.com/llvm-mirror/clang/blob/master/test/SemaCXX/coroutines.cpp#L505 with `address of overloaded function 'g' does not match required type ''` Repository: rC Clang https://reviews.llvm.org/D51741 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51741: [coro]Pass rvalue reference for named local variable to return_value
tks2103 updated this revision to Diff 164265. tks2103 added a comment. get NRVOCandidate to determine if we should try to move return var Repository: rC Clang https://reviews.llvm.org/D51741 Files: lib/Sema/SemaCoroutine.cpp test/SemaCXX/coroutine-rvo.cpp Index: test/SemaCXX/coroutine-rvo.cpp === --- /dev/null +++ test/SemaCXX/coroutine-rvo.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -stdlib=libc++ -std=c++1z -fcoroutines-ts -fsyntax-only + +namespace std::experimental { +template struct coroutine_handle { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; + +template <> struct coroutine_handle { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template + coroutine_handle(coroutine_handle) noexcept; +}; + +template +struct void_t_imp { + using type = void; +}; +template +using void_t = typename void_t_imp::type; + +template +struct traits_sfinae_base {}; + +template +struct traits_sfinae_base> { + using promise_type = typename T::promise_type; +}; + +template +struct coroutine_traits : public traits_sfinae_base {}; +} + +struct suspend_never { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct MoveOnly { + MoveOnly() {}; + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&) noexcept {}; + ~MoveOnly() {}; +}; + +template +struct task { + struct promise_type { +auto initial_suspend() { return suspend_never{}; } +auto final_suspend() { return suspend_never{}; } +auto get_return_object() { return task{}; } +static void unhandled_exception() {} +void return_value(T&& value) {} + }; +}; + +task f() { + MoveOnly value; + co_return value; +} + +int main() { + f(); + return 0; +} + +// expected-no-diagnostics Index: lib/Sema/SemaCoroutine.cpp === --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -841,6 +841,19 @@ E = R.get(); } + // Move the return value if we can + if (E) { +auto NRVOCandidate = this->getCopyElisionCandidate(E->getType(), E, CES_AsIfByStdMove); +if (NRVOCandidate) { + InitializedEntity Entity = + InitializedEntity::InitializeResult(Loc, E->getType(), NRVOCandidate); + ExprResult MoveResult = + this->PerformMoveOrCopyInitialization(Entity, NRVOCandidate, E->getType(), E); + if (MoveResult.get()) +E = MoveResult.get(); +} + } + // FIXME: If the operand is a reference to a variable that's about to go out // of scope, we should treat the operand as an xvalue for this overload // resolution. Index: test/SemaCXX/coroutine-rvo.cpp === --- /dev/null +++ test/SemaCXX/coroutine-rvo.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -stdlib=libc++ -std=c++1z -fcoroutines-ts -fsyntax-only + +namespace std::experimental { +template struct coroutine_handle { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; + +template <> struct coroutine_handle { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template + coroutine_handle(coroutine_handle) noexcept; +}; + +template +struct void_t_imp { + using type = void; +}; +template +using void_t = typename void_t_imp::type; + +template +struct traits_sfinae_base {}; + +template +struct traits_sfinae_base> { + using promise_type = typename T::promise_type; +}; + +template +struct coroutine_traits : public traits_sfinae_base {}; +} + +struct suspend_never { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct MoveOnly { + MoveOnly() {}; + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&) noexcept {}; + ~MoveOnly() {}; +}; + +template +struct task { + struct promise_type { +auto initial_suspend() { return suspend_never{}; } +auto final_suspend() { return suspend_never{}; } +auto get_return_object() { return task{}; } +static void unhandled_exception() {} +void return_value(T&& value) {} + }; +}; + +task f() { + MoveOnly value; + co_return value; +} + +int main() { + f(); + return 0; +} + +// expected-no-diagnostics Index: lib/Sema/SemaCoroutine.cpp === --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -841,6 +841,19 @@ E = R.get(); } + // Move the return value if we can + if (E) { +auto NRVOCandidate = this->getCopyElisionCandidate(E->getType(), E, CES_AsIfByStdMove); +if (NRVOCandidate) { + InitializedEntity Entity = + InitializedEntity::InitializeResult
[PATCH] D51741: [coro]Pass rvalue reference for named local variable to return_value
tks2103 added a comment. ping @GorNishanov Repository: rC Clang https://reviews.llvm.org/D51741 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51741: [coro]Pass rvalue reference for named local variable to return_value
tks2103 added a comment. ping @GorNishanov Repository: rC Clang https://reviews.llvm.org/D51741 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51741: [coro]Pass rvalue reference for named local variable to return_value
tks2103 added a comment. ping @GorNishanov SAVE ME GOR! YOU'RE MY ONLY HOPE! Repository: rC Clang https://reviews.llvm.org/D51741 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51741: [coro]Pass rvalue reference for named local variable to return_value
tks2103 updated this revision to Diff 168380. tks2103 added a comment. comply with clang-format Repository: rC Clang https://reviews.llvm.org/D51741 Files: lib/Sema/SemaCoroutine.cpp test/SemaCXX/coroutine-rvo.cpp Index: test/SemaCXX/coroutine-rvo.cpp === --- /dev/null +++ test/SemaCXX/coroutine-rvo.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -stdlib=libc++ -std=c++1z -fcoroutines-ts -fsyntax-only + +namespace std::experimental { +template struct coroutine_handle { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; + +template <> struct coroutine_handle { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template + coroutine_handle(coroutine_handle) noexcept; +}; + +template +struct void_t_imp { + using type = void; +}; +template +using void_t = typename void_t_imp::type; + +template +struct traits_sfinae_base {}; + +template +struct traits_sfinae_base> { + using promise_type = typename T::promise_type; +}; + +template +struct coroutine_traits : public traits_sfinae_base {}; +} + +struct suspend_never { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct MoveOnly { + MoveOnly() {}; + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&) noexcept {}; + ~MoveOnly() {}; +}; + +template +struct task { + struct promise_type { +auto initial_suspend() { return suspend_never{}; } +auto final_suspend() { return suspend_never{}; } +auto get_return_object() { return task{}; } +static void unhandled_exception() {} +void return_value(T&& value) {} + }; +}; + +task f() { + MoveOnly value; + co_return value; +} + +int main() { + f(); + return 0; +} + +// expected-no-diagnostics Index: lib/Sema/SemaCoroutine.cpp === --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -841,6 +841,19 @@ E = R.get(); } + // Move the return value if we can + if (E) { +auto NRVOCandidate = this->getCopyElisionCandidate(E->getType(), E, CES_AsIfByStdMove); +if (NRVOCandidate) { + InitializedEntity Entity = + InitializedEntity::InitializeResult(Loc, E->getType(), NRVOCandidate); + ExprResult MoveResult = this->PerformMoveOrCopyInitialization( + Entity, NRVOCandidate, E->getType(), E); + if (MoveResult.get()) +E = MoveResult.get(); +} + } + // FIXME: If the operand is a reference to a variable that's about to go out // of scope, we should treat the operand as an xvalue for this overload // resolution. Index: test/SemaCXX/coroutine-rvo.cpp === --- /dev/null +++ test/SemaCXX/coroutine-rvo.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -stdlib=libc++ -std=c++1z -fcoroutines-ts -fsyntax-only + +namespace std::experimental { +template struct coroutine_handle { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; + +template <> struct coroutine_handle { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template + coroutine_handle(coroutine_handle) noexcept; +}; + +template +struct void_t_imp { + using type = void; +}; +template +using void_t = typename void_t_imp::type; + +template +struct traits_sfinae_base {}; + +template +struct traits_sfinae_base> { + using promise_type = typename T::promise_type; +}; + +template +struct coroutine_traits : public traits_sfinae_base {}; +} + +struct suspend_never { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct MoveOnly { + MoveOnly() {}; + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&) noexcept {}; + ~MoveOnly() {}; +}; + +template +struct task { + struct promise_type { +auto initial_suspend() { return suspend_never{}; } +auto final_suspend() { return suspend_never{}; } +auto get_return_object() { return task{}; } +static void unhandled_exception() {} +void return_value(T&& value) {} + }; +}; + +task f() { + MoveOnly value; + co_return value; +} + +int main() { + f(); + return 0; +} + +// expected-no-diagnostics Index: lib/Sema/SemaCoroutine.cpp === --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -841,6 +841,19 @@ E = R.get(); } + // Move the return value if we can + if (E) { +auto NRVOCandidate = this->getCopyElisionCandidate(E->getType(), E, CES_AsIfByStdMove); +if (NRVOCandidate) { + InitializedEntity Entity = + InitializedEntity::InitializeResult(Loc, E->getType(), NRVOCandidate); +
[PATCH] D51741: [coro]Pass rvalue reference for named local variable to return_value
tks2103 added a comment. @modocache I do need someone to land this for me! Take it away! Repository: rC Clang https://reviews.llvm.org/D51741 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48981: Add caching when looking up coroutine_traits
tks2103 created this revision. tks2103 added reviewers: GorNishanov, modocache. Currently clang looks up the coroutine_traits ClassTemplateDecl everytime it looks up the promise type. This is unnecessary as coroutine_traits doesn't change between promise type lookups. This diff caches the coroutine_traits lookup. Test Plan: I added log statements in the new `lookupCoroutineTraits` function to ensure that `LookupQualifiedName` was only called once even when multiple coroutines existed in the source file. Repository: rC Clang https://reviews.llvm.org/D48981 Files: include/clang/Sema/Sema.h lib/Sema/Sema.cpp lib/Sema/SemaCoroutine.cpp Index: lib/Sema/SemaCoroutine.cpp === --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -60,20 +60,8 @@ return QualType(); } - LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"), - FuncLoc, Sema::LookupOrdinaryName); - if (!S.LookupQualifiedName(Result, StdExp)) { -S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found) -<< "std::experimental::coroutine_traits"; -return QualType(); - } - - ClassTemplateDecl *CoroTraits = Result.getAsSingle(); + ClassTemplateDecl *CoroTraits = S.lookupCoroutineTraits(KwLoc, FuncLoc); if (!CoroTraits) { -Result.suppressDiagnostics(); -// We found something weird. Complain about the first thing we found. -NamedDecl *Found = *Result.begin(); -S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits); return QualType(); } @@ -1538,3 +1526,27 @@ return StmtError(); return Res; } + +ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc, + SourceLocation FuncLoc) { + if (!StdCoroutineTraitsCache) { +if (auto StdExp = lookupStdExperimentalNamespace()) { + LookupResult Result(*this, + &PP.getIdentifierTable().get("coroutine_traits"), + FuncLoc, LookupOrdinaryName); + if (!LookupQualifiedName(Result, StdExp)) { +Diag(KwLoc, diag::err_implied_coroutine_type_not_found) +<< "std::experimental::coroutine_traits"; +return nullptr; + } + if (!(StdCoroutineTraitsCache = +Result.getAsSingle())) { +Result.suppressDiagnostics(); +NamedDecl *Found = *Result.begin(); +Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits); +return nullptr; + } +} + } + return StdCoroutineTraitsCache; +} Index: lib/Sema/Sema.cpp === --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -131,9 +131,9 @@ IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), - CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), - NSValueDecl(nullptr), NSStringDecl(nullptr), - StringWithUTF8StringMethod(nullptr), + StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr), + MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), NSValueDecl(nullptr), + NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false), Index: include/clang/Sema/Sema.h === --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -824,6 +824,10 @@ /// \. ClassTemplateDecl *StdInitializerList; + /// The C++ "std::coroutine_traits" template, which is defined in + /// \ + ClassTemplateDecl *StdCoroutineTraitsCache; + /// The C++ "type_info" declaration, which is defined in \. RecordDecl *CXXTypeInfoDecl; @@ -8572,6 +8576,8 @@ bool buildCoroutineParameterMoves(SourceLocation Loc); VarDecl *buildCoroutinePromise(SourceLocation Loc); void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); + ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc, + SourceLocation FuncLoc); //======// // OpenCL extensions. Index: lib/Sema/SemaCoroutine.cpp === --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -60,20 +60,8 @@ return QualType(); } - LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"), - FuncLoc, Sema::LookupOrdinaryName); - if (!S.LookupQualifiedName(Result, StdExp)) { -S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found) -
[PATCH] D48981: Add caching when looking up coroutine_traits
tks2103 added a comment. ping @modocache @GorNishanov Repository: rC Clang https://reviews.llvm.org/D48981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49099: Remove qualtype qualifier in coroutine error to prevent assert in debug
tks2103 created this revision. tks2103 added reviewers: modocache, GorNishanov. A forward-declared coroutine_traits should trip an error; we need a complete type. Unfortunately, in debug mode only, we trip an assert when attempting to provide the fully qualified type for the error message. If you try to compile a program with a forward-declared coroutine_traits in debug mode, clang will crash. I've included a test for the behavior and removed the q modifier on the error message. This prevents the crash in debug mode and does not change the behavior for the error message on a forward-declaration of a coroutine_traits type. Test Plan: I've included a test for the forward-declaration. Repository: rC Clang https://reviews.llvm.org/D49099 Files: include/clang/Basic/DiagnosticSemaKinds.td test/SemaCXX/coroutine-traits-undefined-template.cpp Index: test/SemaCXX/coroutine-traits-undefined-template.cpp === --- /dev/null +++ test/SemaCXX/coroutine-traits-undefined-template.cpp @@ -0,0 +1,21 @@ +// test/SemaCXX/coroutine-traits-undefined-template.cpp + +// This file contains references to sections of the Coroutines TS, which can be +// found at http://wg21.link/coroutines. + +// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -Wunused-result + +namespace std { +namespace experimental { + +template +struct coroutine_traits { + struct promise_type {}; +}; + +template<> struct coroutine_traits; // expected-note {{forward declaration of 'std::experimental::coroutine_traits'}} +}} // namespace std::experimental + +void uses_forward_declaration() { + co_return; // expected-error {{this function cannot be a coroutine: missing definition of specialization 'coroutine_traits'}} +} Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -9071,7 +9071,7 @@ "this function cannot be a coroutine: %0 is an incomplete type">; def err_coroutine_type_missing_specialization : Error< "this function cannot be a coroutine: missing definition of " - "specialization %q0">; + "specialization %0">; def err_coroutine_promise_incompatible_return_functions : Error< "the coroutine promise type %0 declares both 'return_value' and 'return_void'">; def err_coroutine_promise_requires_return_function : Error< Index: test/SemaCXX/coroutine-traits-undefined-template.cpp === --- /dev/null +++ test/SemaCXX/coroutine-traits-undefined-template.cpp @@ -0,0 +1,21 @@ +// test/SemaCXX/coroutine-traits-undefined-template.cpp + +// This file contains references to sections of the Coroutines TS, which can be +// found at http://wg21.link/coroutines. + +// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -Wunused-result + +namespace std { +namespace experimental { + +template +struct coroutine_traits { + struct promise_type {}; +}; + +template<> struct coroutine_traits; // expected-note {{forward declaration of 'std::experimental::coroutine_traits'}} +}} // namespace std::experimental + +void uses_forward_declaration() { + co_return; // expected-error {{this function cannot be a coroutine: missing definition of specialization 'coroutine_traits'}} +} Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -9071,7 +9071,7 @@ "this function cannot be a coroutine: %0 is an incomplete type">; def err_coroutine_type_missing_specialization : Error< "this function cannot be a coroutine: missing definition of " - "specialization %q0">; + "specialization %0">; def err_coroutine_promise_incompatible_return_functions : Error< "the coroutine promise type %0 declares both 'return_value' and 'return_void'">; def err_coroutine_promise_requires_return_function : Error< ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49099: Remove qualtype qualifier in coroutine error to prevent assert in debug
tks2103 added a comment. @modocache please commit on my behalf please =) Repository: rC Clang https://reviews.llvm.org/D49099 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48981: Add caching when looking up coroutine_traits
tks2103 added a comment. ping @modocache @GorNishanov Repository: rC Clang https://reviews.llvm.org/D48981 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits