modocache created this revision.
modocache added reviewers: GorNishanov, EricWF.

If a user defines a coroutine_traits type that takes an incorrect
number of template parameters, or for some reason they include such
a type in their program, they receive a cryptic error message:
"too few template arguments for class template 'coroutine_traits'".
The problem is that they may not understand how many is the right
number of template arguments.

Add a note diagnostic that explains why the coroutine_traits template
is being instantiated, and with what arguments.

Test Plan: check-clang


Repository:
  rC Clang

https://reviews.llvm.org/D48863

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaCoroutine.cpp
  test/SemaCXX/coroutine-traits-incorrect-argument-types.cpp


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<typename T, typename U>
+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'}}
+}
Index: lib/Sema/SemaCoroutine.cpp
===================================================================
--- lib/Sema/SemaCoroutine.cpp
+++ lib/Sema/SemaCoroutine.cpp
@@ -107,13 +107,22 @@
   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.
+    S.Diag(FD->getLocation(), diag::note_coroutine_types_for_traits_here);
     return QualType();
 
   auto *RD = CoroTrait->getAsCXXRecordDecl();
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 <experimental/coroutine> 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 <new> before defining a coroutine which 
"
   "uses get_return_object_on_allocation_failure()">;


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<typename T, typename U>
+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'}}
+}
Index: lib/Sema/SemaCoroutine.cpp
===================================================================
--- lib/Sema/SemaCoroutine.cpp
+++ lib/Sema/SemaCoroutine.cpp
@@ -107,13 +107,22 @@
   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.
+    S.Diag(FD->getLocation(), diag::note_coroutine_types_for_traits_here);
     return QualType();
 
   auto *RD = CoroTrait->getAsCXXRecordDecl();
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 <experimental/coroutine> 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 <new> before defining a coroutine which "
   "uses get_return_object_on_allocation_failure()">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D48863: [... Brian Gesiak via Phabricator via cfe-commits

Reply via email to