Add a new modules test to ensure we dont rebreak diagnostic
authorErich Keane <erich.keane@intel.com>
Thu, 2 Feb 2023 14:39:53 +0000 (06:39 -0800)
committerErich Keane <erich.keane@intel.com>
Thu, 2 Feb 2023 15:16:41 +0000 (07:16 -0800)
Fixes: 60336
Seemingly the concepts sugaring patch caused us to not catch this
situation, which has been confirmed to be a valid error.  Make sure that
we catch this situation in the future, particularly if the concepts
sugaring patch gets re added.

clang/test/Modules/GH60336.cpp [new file with mode: 0644]

diff --git a/clang/test/Modules/GH60336.cpp b/clang/test/Modules/GH60336.cpp
new file mode 100644 (file)
index 0000000..fefbd37
--- /dev/null
@@ -0,0 +1,78 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x c++ -std=c++20 %s -verify -fmodules -fmodules-cache-path=%t
+#pragma clang module build std
+module std   [system] {
+  module concepts     [system] {
+      module assignable         [system] {
+    }
+    export *
+  }
+  module functional     [system] {
+    export *
+  }
+
+
+  module type_traits     [system] {
+    export *
+  }
+}
+
+#pragma clang module contents
+#pragma clang module begin std.type_traits
+namespace std {
+template<class _Tp, class _Up>
+concept same_as = __is_same(_Tp, _Up);
+
+template <class...>
+struct common_reference;
+
+template <class _Tp, class _Up> struct common_reference<_Tp, _Up>
+{
+    using type = _Tp;
+};
+}
+#pragma clang module end // type_traits
+
+#pragma clang module begin std.concepts.assignable
+#pragma clang module import std.type_traits
+namespace std {
+template<class _Tp, class _Up>
+concept common_reference_with =
+  same_as<typename common_reference<_Tp, _Up>::type, typename common_reference<_Up, _Tp>::type>;
+}
+namespace std {
+template<class _Lhs, class _Rhs>
+concept assignable_from =
+  common_reference_with<const __remove_reference_t(_Lhs)&, const __remove_reference_t(_Rhs)&> ;
+}
+#pragma clang module end // std.concepts.assignable
+
+#pragma clang module begin std.functional
+#pragma clang module import std.concepts.assignable
+namespace std {
+template<class _Sp, class _Ip>
+concept sentinel_for = assignable_from<_Ip&, _Ip>;
+template <class _Sp, class _Ip>
+concept nothrow_sentinel_for = sentinel_for<_Sp, _Ip>;
+}
+#pragma clang module end   // std::functional
+#pragma clang module endbuild // contents
+
+
+#pragma clang module import std.functional
+constexpr bool ntsf_subsumes_sf(std::nothrow_sentinel_for<char*> auto) requires true {
+  return true;
+}
+constexpr bool ntsf_subsumes_sf(std::sentinel_for<char*> auto);
+static_assert(ntsf_subsumes_sf("foo"));
+
+// Note: Doing diagnostics verify lines in the individual modules isn't
+// permitted, and using 'bookmarks' in a module also doesn't work, so we're 
+// forced to diagnose this by line-number.
+//
+// Check to ensure that this error happens, prior to a revert of a concepts
+// sugaring patch, this diagnostic didn't happen correctly.
+
+// expected-error@* {{partial specialization of 'common_reference<_Tp, _Up>' must be imported from module 'std.type_traits' before it is required}}
+// expected-note@63 {{while substituting into concept arguments here}}
+// expected-note@*{{partial specialization declared here is not reachable}}