CaseyCarter created this revision.
CaseyCarter added reviewers: mclow.lists, EricWF.

Like the title says, the first batch of tests.

I'll stop at three chunks for now - that should be enough to get some reviewer 
feedback and keep me busy making changes.


https://reviews.llvm.org/D49122

Files:
  test/std/concepts/concepts.lang/concept.commonref/common_reference.pass.cpp
  test/std/concepts/concepts.lang/concept.convertibleto/convertible_to.pass.cpp
  test/std/concepts/concepts.lang/concept.derivedfrom/derived_from.pass.cpp
  test/std/concepts/concepts.lang/concept.same/same.pass.cpp
  test/std/concepts/lit.local.cfg

Index: test/std/concepts/lit.local.cfg
===================================================================
--- /dev/null
+++ test/std/concepts/lit.local.cfg
@@ -0,0 +1,9 @@
+# If the compiler doesn't support concepts, mark all of the tests under
+# this directory as unsupported.
+if 'concepts' not in config.available_features:
+  config.unsupported = True
+elif 'fconcepts' in config.available_features:
+  # The compiler supports concepts only with the flag - require it.
+  import copy
+  config.test_format.cxx = copy.deepcopy(config.test_format.cxx)
+  config.test_format.cxx.compile_flags += ['-fconcepts']
Index: test/std/concepts/concepts.lang/concept.same/same.pass.cpp
===================================================================
--- /dev/null
+++ test/std/concepts/concepts.lang/concept.same/same.pass.cpp
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+#include <concepts>
+#include <type_traits>
+
+static_assert(std::Same<int, int>);
+static_assert(std::Same<double, double>);
+static_assert(!std::Same<double, int>);
+static_assert(!std::Same<int, double>);
+
+// Test that `Same<A,B>` subsumes `Same<B,A>` (with reversed args).
+template <class A, class B>
+    requires std::Same<B, A>
+constexpr bool foo() {
+    return false;
+}
+
+template <class A, class B>
+    requires std::Same<A, B> && std::is_integral_v<A>
+constexpr bool foo() {
+    return true;
+}
+
+static_assert(!foo<int*, int*>());
+static_assert(foo<int, int>());
+
+template <class T, class U>
+void test_same() {
+    static_assert( std::Same<T, U>);
+    static_assert(!std::Same<const T, U>);
+    static_assert(!std::Same<T, const U>);
+    static_assert( std::Same<const T, const U>);
+}
+
+template <class T, class U>
+void test_same_ref() {
+    static_assert(std::Same<T, U>);
+    static_assert(std::Same<const T, U>);
+    static_assert(std::Same<T, const U>);
+    static_assert(std::Same<const T, const U>);
+}
+
+template <class T, class U>
+void test_not_same() {
+    static_assert(!std::Same<T, U>);
+}
+
+struct Class
+{
+    ~Class();
+};
+
+int main() {
+    test_same<int, int>();
+    test_same<void, void>();
+    test_same<Class, Class>();
+    test_same<int*, int*>();
+    test_same_ref<int&, int&>();
+
+    test_not_same<int, void>();
+    test_not_same<void, Class>();
+    test_not_same<Class, int*>();
+    test_not_same<int*, int&>();
+    test_not_same<int&, int>();
+}
Index: test/std/concepts/concepts.lang/concept.derivedfrom/derived_from.pass.cpp
===================================================================
--- /dev/null
+++ test/std/concepts/concepts.lang/concept.derivedfrom/derived_from.pass.cpp
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+#include <concepts>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <class Derived, class Base>
+void test_derived_from() {
+    static_assert(std::DerivedFrom<Derived, Base>);
+    static_assert(std::DerivedFrom<const Derived, Base>);
+    static_assert(std::DerivedFrom<Derived, const Base>);
+    static_assert(std::DerivedFrom<const Derived, const Base>);
+}
+
+template <class Derived, class Base>
+void test_not_derived_from() {
+    static_assert(!std::DerivedFrom<Derived, Base>);
+}
+
+struct B {};
+struct B1 : B {};
+struct B2 : B {};
+struct D : private B1, private B2 {};
+
+int main() {
+    test_derived_from<B1, B>();
+    test_derived_from<B2, B>();
+    test_derived_from<B, B>();
+
+    test_not_derived_from<D, B>();
+    test_not_derived_from<D, B1>();
+    test_not_derived_from<D, B2>();
+    test_not_derived_from<B, D>();
+    test_not_derived_from<D&, B&>();
+    test_not_derived_from<D[3], B[3]>();
+    test_not_derived_from<int, int>();
+}
Index: test/std/concepts/concepts.lang/concept.convertibleto/convertible_to.pass.cpp
===================================================================
--- /dev/null
+++ test/std/concepts/concepts.lang/concept.convertibleto/convertible_to.pass.cpp
@@ -0,0 +1,298 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+#include <cassert>
+#include <concepts>
+
+template <class From, class To>
+void test_convertible_to() {
+    static_assert(std::ConvertibleTo<From, To>);
+    static_assert(std::ConvertibleTo<const From, To>);
+    static_assert(std::ConvertibleTo<From, const To>);
+    static_assert(std::ConvertibleTo<const From, const To>);
+}
+
+template <class From, class To>
+void test_not_convertible_to() {
+    static_assert(!std::ConvertibleTo<From, To>);
+    static_assert(!std::ConvertibleTo<const From, To>);
+    static_assert(!std::ConvertibleTo<From, const To>);
+    static_assert(!std::ConvertibleTo<const From, const To>);
+}
+
+using Function = void();
+using ConstFunction = void() const;
+using Array = char[1];
+
+struct StringType {
+    StringType(const char*) {}
+};
+
+class NonCopyable {
+    NonCopyable(NonCopyable&);
+};
+
+template <typename T>
+class CannotInstantiate {
+    enum { X = T::ThisExpressionWillBlowUp };
+};
+
+namespace X {
+    struct A { A() = default; A(int) {} };
+
+    enum class result {
+        exact, convertible, unrelated
+    };
+
+    result f(A) {
+        return result::exact;
+    }
+
+    template <std::ConvertibleTo<A> T>
+    result f(T&&) {
+        return result::convertible;
+    }
+
+    template <class T>
+    result f(T) {
+        return result::unrelated;
+    }
+} // unnamed namespace
+
+int main() {
+    // void
+    test_convertible_to<void, void>();
+    test_not_convertible_to<void, Function>();
+    test_not_convertible_to<void, Function&>();
+    test_not_convertible_to<void, Function*>();
+    test_not_convertible_to<void, Array>();
+    test_not_convertible_to<void, Array&>();
+    test_not_convertible_to<void, char>();
+    test_not_convertible_to<void, char&>();
+    test_not_convertible_to<void, char*>();
+    test_not_convertible_to<char, void>();
+
+    // Function
+    test_not_convertible_to<Function, void>();
+    test_not_convertible_to<Function, Function>();
+    test_convertible_to<Function, Function&>();
+    test_convertible_to<Function, Function*>();
+    test_convertible_to<Function, Function*const>();
+
+    static_assert(std::ConvertibleTo<Function, Function&&>);
+
+    test_not_convertible_to<Function, Array>();
+    test_not_convertible_to<Function, Array&>();
+    test_not_convertible_to<Function, char>();
+    test_not_convertible_to<Function, char&>();
+    test_not_convertible_to<Function, char*>();
+
+    // Function&
+    test_not_convertible_to<Function&, void>();
+    test_not_convertible_to<Function&, Function>();
+    test_convertible_to<Function&, Function&>();
+
+    test_convertible_to<Function&, Function*>();
+    test_not_convertible_to<Function&, Array>();
+    test_not_convertible_to<Function&, Array&>();
+    test_not_convertible_to<Function&, char>();
+    test_not_convertible_to<Function&, char&>();
+    test_not_convertible_to<Function&, char*>();
+
+    // Function*
+    test_not_convertible_to<Function*, void>();
+    test_not_convertible_to<Function*, Function>();
+    test_not_convertible_to<Function*, Function&>();
+    test_convertible_to<Function*, Function*>();
+
+    test_not_convertible_to<Function*, Array>();
+    test_not_convertible_to<Function*, Array&>();
+    test_not_convertible_to<Function*, char>();
+    test_not_convertible_to<Function*, char&>();
+    test_not_convertible_to<Function*, char*>();
+
+    // Non-referencable function type
+    static_assert(!std::ConvertibleTo<ConstFunction, Function>);
+    static_assert(!std::ConvertibleTo<ConstFunction, Function*>);
+    static_assert(!std::ConvertibleTo<ConstFunction, Function&>);
+    static_assert(!std::ConvertibleTo<ConstFunction, Function&&>);
+    static_assert(!std::ConvertibleTo<Function*, ConstFunction>);
+    static_assert(!std::ConvertibleTo<Function&, ConstFunction>);
+    static_assert(!std::ConvertibleTo<ConstFunction, ConstFunction>);
+    static_assert(!std::ConvertibleTo<ConstFunction, void>);
+
+    // Array
+    test_not_convertible_to<Array, void>();
+    test_not_convertible_to<Array, Function>();
+    test_not_convertible_to<Array, Function&>();
+    test_not_convertible_to<Array, Function*>();
+    test_not_convertible_to<Array, Array>();
+
+    static_assert(!std::ConvertibleTo<Array, Array&>);
+    static_assert( std::ConvertibleTo<Array, const Array&>);
+    static_assert(!std::ConvertibleTo<Array, const volatile Array&>);
+
+    static_assert(!std::ConvertibleTo<const Array, Array&>);
+    static_assert( std::ConvertibleTo<const Array, const Array&>);
+    static_assert(!std::ConvertibleTo<Array, volatile Array&>);
+    static_assert(!std::ConvertibleTo<Array, const volatile Array&>);
+
+    static_assert( std::ConvertibleTo<Array, Array&&>);
+    static_assert( std::ConvertibleTo<Array, const Array&&>);
+    static_assert( std::ConvertibleTo<Array, volatile Array&&>);
+    static_assert( std::ConvertibleTo<Array, const volatile Array&&>);
+    static_assert( std::ConvertibleTo<const Array, const Array&&>);
+    static_assert(!std::ConvertibleTo<Array&, Array&&>);
+    static_assert(!std::ConvertibleTo<Array&&, Array&>);
+
+    test_not_convertible_to<Array, char>();
+    test_not_convertible_to<Array, char&>();
+
+    static_assert(std::ConvertibleTo<Array, char*>);
+    static_assert(std::ConvertibleTo<Array, const char*>);
+    static_assert(std::ConvertibleTo<Array, char* const>);
+    static_assert(std::ConvertibleTo<Array, char* const volatile>);
+
+    static_assert(!std::ConvertibleTo<const Array, char*>);
+    static_assert( std::ConvertibleTo<const Array, const char*>);
+
+    static_assert(!std::ConvertibleTo<char[42][42], char*>);
+    static_assert(!std::ConvertibleTo<char[][1], char*>);
+
+    // Array&
+    test_not_convertible_to<Array&, void>();
+    test_not_convertible_to<Array&, Function>();
+    test_not_convertible_to<Array&, Function&>();
+    test_not_convertible_to<Array&, Function*>();
+    test_not_convertible_to<Array&, Array>();
+
+    static_assert( std::ConvertibleTo<Array&, Array&>);
+    static_assert( std::ConvertibleTo<Array&, const Array&>);
+    static_assert(!std::ConvertibleTo<const Array&, Array&>);
+    static_assert( std::ConvertibleTo<const Array&, const Array&>);
+
+    test_not_convertible_to<Array&, char>();
+    test_not_convertible_to<Array&, char&>();
+
+    static_assert( std::ConvertibleTo<Array&, char*>);
+    static_assert( std::ConvertibleTo<Array&, const char*>);
+    static_assert(!std::ConvertibleTo<const Array&, char*>);
+    static_assert( std::ConvertibleTo<const Array&, const char*>);
+
+    static_assert(std::ConvertibleTo<Array, StringType>);
+    static_assert(std::ConvertibleTo<char(&)[], StringType>);
+
+    // char
+    test_not_convertible_to<char, void>();
+    test_not_convertible_to<char, Function>();
+    test_not_convertible_to<char, Function&>();
+    test_not_convertible_to<char, Function*>();
+    test_not_convertible_to<char, Array>();
+    test_not_convertible_to<char, Array&>();
+
+    test_convertible_to<char, char>();
+
+    static_assert(!std::ConvertibleTo<char, char&>);
+    static_assert( std::ConvertibleTo<char, const char&>);
+    static_assert(!std::ConvertibleTo<const char, char&>);
+    static_assert( std::ConvertibleTo<const char, const char&>);
+
+    test_not_convertible_to<char, char*>();
+
+    // char&
+    test_not_convertible_to<char&, void>();
+    test_not_convertible_to<char&, Function>();
+    test_not_convertible_to<char&, Function&>();
+    test_not_convertible_to<char&, Function*>();
+    test_not_convertible_to<char&, Array>();
+    test_not_convertible_to<char&, Array&>();
+
+    test_convertible_to<char&, char>();
+
+    static_assert( std::ConvertibleTo<char&, char&>);
+    static_assert( std::ConvertibleTo<char&, const char&>);
+    static_assert(!std::ConvertibleTo<const char&, char&>);
+    static_assert( std::ConvertibleTo<const char&, const char&>);
+
+    test_not_convertible_to<char&, char*>();
+
+    // char*
+    test_not_convertible_to<char*, void>();
+    test_not_convertible_to<char*, Function>();
+    test_not_convertible_to<char*, Function&>();
+    test_not_convertible_to<char*, Function*>();
+    test_not_convertible_to<char*, Array>();
+    test_not_convertible_to<char*, Array&>();
+
+    test_not_convertible_to<char*, char>();
+    test_not_convertible_to<char*, char&>();
+
+    static_assert( std::ConvertibleTo<char*, char*>);
+    static_assert( std::ConvertibleTo<char*, const char*>);
+    static_assert(!std::ConvertibleTo<const char*, char*>);
+    static_assert( std::ConvertibleTo<const char*, const char*>);
+
+    // NonCopyable
+    static_assert( std::ConvertibleTo<NonCopyable&, NonCopyable&>);
+    static_assert( std::ConvertibleTo<NonCopyable&, const NonCopyable&>);
+    static_assert( std::ConvertibleTo<NonCopyable&, const volatile NonCopyable&>);
+    static_assert( std::ConvertibleTo<NonCopyable&, volatile NonCopyable&>);
+    static_assert( std::ConvertibleTo<const NonCopyable&, const NonCopyable&>);
+    static_assert( std::ConvertibleTo<const NonCopyable&, const volatile NonCopyable&>);
+    static_assert( std::ConvertibleTo<volatile NonCopyable&, const volatile NonCopyable&>);
+    static_assert( std::ConvertibleTo<const volatile NonCopyable&, const volatile NonCopyable&>);
+    static_assert(!std::ConvertibleTo<const NonCopyable&, NonCopyable&>);
+
+    test_not_convertible_to<NonCopyable&, NonCopyable>();
+
+    // Ensure that CannotInstantiate is not instantiated by is_convertible when it is not needed.
+    // For example CannotInstantiate is instatiated as a part of ADL lookup for arguments of type CannotInstantiate*.
+    static_assert(std::ConvertibleTo<CannotInstantiate<int>*, CannotInstantiate<int>*>);
+
+    {
+        using namespace X;
+        assert(f(A{}) == result::exact);
+        { const A a{}; assert(f(a) == result::exact); }
+        assert(f(42) == result::convertible);
+        assert(f("foo") == result::unrelated);
+    }
+
+    {
+        struct B {};
+        struct D : B {};
+
+        test_convertible_to<B, B>();
+        test_convertible_to<D, D>();
+        test_convertible_to<D, B>();
+        test_not_convertible_to<B, D>();
+    }
+
+    {
+        struct Z;
+        struct X {
+            X() = default;
+            explicit X(Z) = delete;
+        };
+        struct Y1 {
+            operator X() const;
+        };
+        struct Y2 {
+            explicit operator X() const;
+        };
+        struct Z {
+            operator X() const;
+        };
+        test_convertible_to<Y1, X>();     // Both implicitly and explicitly convertible
+        test_not_convertible_to<Y2, X>(); // Only explicitly convertible
+        test_not_convertible_to<Z, X>();  // Only implicitly convertible
+    }
+}
Index: test/std/concepts/concepts.lang/concept.commonref/common_reference.pass.cpp
===================================================================
--- /dev/null
+++ test/std/concepts/concepts.lang/concept.commonref/common_reference.pass.cpp
@@ -0,0 +1,173 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+#include <concepts>
+#include <functional>
+#include <type_traits>
+
+using std::CommonReference;
+using std::void_t;
+
+template <class, class = void>
+constexpr bool is_trait = false;
+template <class T>
+constexpr bool is_trait<T, std::void_t<typename T::type>> = true;
+
+struct X {};
+struct Y { explicit Y(X){} };
+
+namespace std
+{
+    template <> struct common_type<X, Y> { using type = Y; };
+    template <> struct common_type<Y, X> { using type = Y; };
+}
+
+static_assert(std::is_same<std::common_reference_t<int&&, int const&, int volatile&>, int const volatile&>());
+static_assert(std::is_same<std::common_reference_t<int&&, int const&, float&>, float>());
+static_assert(!is_trait<std::common_reference<int, short, int, char*>>);
+
+static_assert(std::is_same<std::common_reference_t<int, short>, int>::value);
+static_assert(std::is_same<std::common_reference_t<int, short&>, int>::value);
+static_assert(std::is_same<std::common_reference_t<int&, short&>, int>::value);
+static_assert(std::is_same<std::common_reference_t<int&, short>, int>::value);
+
+// tricky volatile reference case
+static_assert(std::is_same<std::common_reference_t<int&&, int volatile&>, int>::value);
+static_assert(std::is_same<std::common_reference_t<int volatile&, int&&>, int>::value);
+static_assert(std::is_same<std::common_reference_t<int const volatile&&, int volatile&&>, int const volatile&&>::value);
+static_assert(std::is_same<std::common_reference_t<int&&, int const&, int volatile&>, int const volatile&>());
+
+// Array types?? Yup!
+static_assert(std::is_same<std::common_reference_t<int (&)[10], int (&&)[10]>, int const(&)[10]>::value);
+static_assert(std::is_same<std::common_reference_t<int const (&)[10], int volatile (&)[10]>, int const volatile(&)[10]>::value);
+static_assert(std::is_same<std::common_reference_t<int (&)[10], int (&)[11]>, int *>::value);
+
+struct X2 {};
+struct Y2 {};
+struct Z2 {};
+
+namespace std
+{
+    template <>
+    struct common_type<X2, Y2>
+    {
+        using type = Z2;
+    };
+    template <>
+    struct common_type<Y2, X2>
+    {
+        using type = Z2;
+    };
+} // namespace std
+
+template <class T, class U>
+void test_common_ref() {
+    static_assert(CommonReference<T, U>);
+    static_assert(CommonReference<U, T>);
+}
+
+template <class T, class U>
+void test_not_common_ref() {
+    static_assert(!CommonReference<T, U>);
+    static_assert(!CommonReference<U, T>);
+}
+
+int main() {
+    test_common_ref<int, int>();
+    test_common_ref<int, double>();
+    test_common_ref<double, int>();
+    test_common_ref<double, double>();
+    test_not_common_ref<void, int>();
+    test_not_common_ref<int*, int>();
+    test_common_ref<void*, int*>();
+    test_common_ref<double,long long>();
+    test_common_ref<void, void>();
+
+    test_not_common_ref<X, Y>();
+
+    {
+        struct AA {
+            AA() = default;
+            AA(AA&&) = delete;
+            AA(AA const&) = delete;
+        };
+        struct BB : AA { };
+
+        test_common_ref<AA&, BB&>();
+        test_common_ref<AA&&, BB&&>();
+        test_not_common_ref<AA, BB>();
+    }
+
+    {
+        struct B {};
+        struct D : B {};
+
+        test_common_ref<B&, D&>();
+        test_common_ref<B&, D const&>();
+        test_common_ref<B const&, D&>();
+        test_common_ref<B const&, D const&>();
+
+        test_common_ref<B&&, D&&>();
+        test_common_ref<B&&, D const&&>();
+        test_common_ref<B const&&, D&&>();
+        test_common_ref<B const&&, D const&&>();
+
+        test_common_ref<B&, D&&>();
+        test_common_ref<B&, D const&&>();
+        test_common_ref<B const&, D&&>();
+        test_common_ref<B const&, D const&&>();
+
+        test_common_ref<B&&, D&>();
+        test_common_ref<B&&, D const&>();
+        test_common_ref<B const&&, D&>();
+        test_common_ref<B const&&, D const&>();
+
+        test_common_ref<B&&, D&&>();
+        test_common_ref<B&&, D const&&>();
+        test_common_ref<B const&&, D&&>();
+        test_common_ref<B const&&, D const&&>();
+    }
+
+    {
+        // https://github.com/ericniebler/stl2/issues/338
+        struct MyIntRef { MyIntRef(int&); };
+        test_common_ref<int&, MyIntRef>();
+    }
+
+    {
+        struct noncopyable {
+            noncopyable() = default;
+            noncopyable(noncopyable&&) = default;
+            noncopyable& operator=(noncopyable&&) = default;
+        };
+        struct noncopyable2 : noncopyable {};
+
+        test_not_common_ref<noncopyable const&, noncopyable>();
+        test_common_ref<noncopyable const&, noncopyable&>();
+        test_not_common_ref<noncopyable2 const&, noncopyable>();
+        test_common_ref<noncopyable2 const&, noncopyable&&>();
+        test_not_common_ref<noncopyable const&, noncopyable2>();
+        test_common_ref<noncopyable const&, noncopyable2 const&>();
+    }
+
+    {
+        static_assert(std::is_same_v<Z2,
+            std::common_reference_t<X2&, Y2 const&>>);
+        test_not_common_ref<X2&, Y2 const&>();
+    }
+
+    {
+        struct B {};
+        struct C { C() = default; C(B); C(int); };
+        test_common_ref<B, C>();
+    }
+}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to