Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -9050,6 +9050,9 @@ def err_implied_coroutine_type_not_found : Error< "%0 type was not found; include before defining " "a coroutine">; +def note_coroutine_types_for_traits_here : Note< + "the coroutine traits class template is being instantiated using the return " + "type, followed by the parameter types, of this coroutine">; def err_implicit_coroutine_std_nothrow_type_not_found : Error< "std::nothrow was not found; include before defining a coroutine which " "uses get_return_object_on_allocation_failure()">; Index: lib/Sema/SemaCoroutine.cpp =================================================================== --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -107,13 +107,21 @@ for (QualType T : FnType->getParamTypes()) AddArg(T); - // Build the template-id. + // Try to instantiate the coroutine traits template specialization, referred + // to in [temp.names]p1 as a template-id. QualType CoroTrait = S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args); - if (CoroTrait.isNull()) + if (CoroTrait.isNull()) { + // The instantiation failed; maybe the user defined a coroutine_traits that + // did something strange, like one that takes a non-type template parameter. + S.Diag(FD->getLocation(), diag::note_coroutine_types_for_traits_here); return QualType(); + } + if (S.RequireCompleteType(KwLoc, CoroTrait, diag::err_coroutine_type_missing_specialization)) + // The particular specialization is missing. For example, the user may have + // forward-declared it. return QualType(); auto *RD = CoroTrait->getAsCXXRecordDecl(); Index: test/SemaCXX/coroutine-traits-incorrect-argument-types.cpp =================================================================== --- /dev/null +++ test/SemaCXX/coroutine-traits-incorrect-argument-types.cpp @@ -0,0 +1,21 @@ +// 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 { // expected-note {{template is declared here}} + struct promise_type {}; // expected-note@-1 {{template is declared here}} +}; +}} // namespace std::experimental + +void too_few_types_for_coroutine_traits() { // expected-note {{the coroutine traits class template is being instantiated using the return type, followed by the parameter types, of this coroutine}} + co_return; // expected-error {{too few template arguments for class template 'coroutine_traits'}} +} + +void too_many_types_for_coroutine_traits(int x, float y) { // expected-note {{the coroutine traits class template is being instantiated using the return type, followed by the parameter types, of this coroutine}} + co_return; // expected-error {{too many template arguments for class template 'coroutine_traits'}} +}