aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/temp/temp.fct.spec/temp.deduct/p7.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CXX/temp/temp.fct.spec/temp.deduct/p7.cpp')
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/p7.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/p7.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/p7.cpp
index bc074ba25e..f0ab7b8ea7 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/p7.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/p7.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
+// RUN: %clang_cc1 -std=c++2a -verify %s
struct Q { typedef int type; };
@@ -20,3 +21,36 @@ template<typename T, template<typename T::type...> class ...X> void c(T);
int &c(...);
int &c_disabled = c(0);
int &c_enabled = c(Q()); // expected-error {{cannot bind to a temporary of type 'void'}}
+
+// The substitution proceeds in lexical order and stops when a condition that
+// causes deduction to fail is encountered.
+#if __cplusplus > 201702L
+namespace reversed_operator_substitution_order {
+ struct X { X(int); };
+ struct Y { Y(int); };
+ struct Cat {};
+ namespace no_adl {
+ Cat operator<=>(Y, X);
+ bool operator<(int, Cat);
+
+ template<typename T> struct indirect_sizeof {
+ static_assert(sizeof(T) != 0);
+ static const auto value = sizeof(T);
+ };
+
+ // We should substitute into the construction of the X object before the
+ // construction of the Y object, so this is a SFINAE case rather than a
+ // hard error. This requires substitution to proceed in lexical order
+ // despite the prior rewrite to
+ // 0 < (Y(...) <=> X(...))
+ template<typename T> float &f(
+ decltype(
+ X(sizeof(T)) < Y(indirect_sizeof<T>::value)
+ )
+ );
+ template<typename T> int &f(...);
+ }
+ int &r = no_adl::f<void>(true);
+ float &s = no_adl::f<int>(true);
+}
+#endif