Squashed 'third_party/GSL/' content from commit 0cebbd7

Change-Id: Iffb2e32f2f45297ac6d3e82168cd9df4ac5acc2f
git-subtree-dir: third_party/GSL
git-subtree-split: 0cebbd77bfc21acbf1cc05983ad626539eeeb8e0
diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp
new file mode 100644
index 0000000..1cb9c10
--- /dev/null
+++ b/tests/notnull_tests.cpp
@@ -0,0 +1,390 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
+
+#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
+
+#include <algorithm> // for addressof
+#include <memory>    // for shared_ptr, make_shared, operator<, opera...
+#include <sstream>   // for operator<<, ostringstream, basic_ostream:...
+#include <stdint.h>  // for uint16_t
+#include <string>    // for basic_string, operator==, string, operator<<
+#include <typeinfo>  // for type_info
+
+namespace gsl {
+struct fail_fast;
+}  // namespace gsl
+
+using namespace gsl;
+
+struct MyBase
+{
+};
+struct MyDerived : public MyBase
+{
+};
+struct Unrelated
+{
+};
+
+// stand-in for a user-defined ref-counted class
+template <typename T>
+struct RefCounted
+{
+    RefCounted(T* p) : p_(p) {}
+    operator T*() { return p_; }
+    T* p_;
+};
+
+// user defined smart pointer with comparison operators returning non bool value
+template <typename T>
+struct CustomPtr
+{
+    CustomPtr(T* p) : p_(p) {}
+    operator T*() { return p_; }
+    bool operator!=(std::nullptr_t) const { return p_ != nullptr; }
+    T* p_ = nullptr;
+};
+
+template <typename T, typename U>
+std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
+{
+    return reinterpret_cast<const void*>(lhs.p_) == reinterpret_cast<const void*>(rhs.p_) ? "true"
+                                                                                          : "false";
+}
+
+template <typename T, typename U>
+std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
+{
+    return reinterpret_cast<const void*>(lhs.p_) != reinterpret_cast<const void*>(rhs.p_) ? "true"
+                                                                                          : "false";
+}
+
+template <typename T, typename U>
+std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
+{
+    return reinterpret_cast<const void*>(lhs.p_) < reinterpret_cast<const void*>(rhs.p_) ? "true"
+                                                                                         : "false";
+}
+
+template <typename T, typename U>
+std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
+{
+    return reinterpret_cast<const void*>(lhs.p_) > reinterpret_cast<const void*>(rhs.p_) ? "true"
+                                                                                         : "false";
+}
+
+template <typename T, typename U>
+std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
+{
+    return reinterpret_cast<const void*>(lhs.p_) <= reinterpret_cast<const void*>(rhs.p_) ? "true"
+                                                                                          : "false";
+}
+
+template <typename T, typename U>
+std::string operator>=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
+{
+    return reinterpret_cast<const void*>(lhs.p_) >= reinterpret_cast<const void*>(rhs.p_) ? "true"
+                                                                                          : "false";
+}
+
+struct NonCopyableNonMovable
+{
+    NonCopyableNonMovable() = default;
+    NonCopyableNonMovable(const NonCopyableNonMovable&) = delete;
+    NonCopyableNonMovable& operator=(const NonCopyableNonMovable&) = delete;
+    NonCopyableNonMovable(NonCopyableNonMovable&&) = delete;
+    NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete;
+};
+
+bool helper(not_null<int*> p) { return *p == 12; }
+bool helper_const(not_null<const int*> p) { return *p == 12; }
+
+TEST_CASE("TestNotNullConstructors")
+{
+#ifdef CONFIRM_COMPILATION_ERRORS
+    not_null<int*> p = nullptr;         // yay...does not compile!
+    not_null<std::vector<char>*> p = 0; // yay...does not compile!
+    not_null<int*> p;                   // yay...does not compile!
+    std::unique_ptr<int> up = std::make_unique<int>(120);
+    not_null<int*> p = up;
+
+    // Forbid non-nullptr assignable types
+    not_null<std::vector<int>> f(std::vector<int>{1});
+    not_null<int> z(10);
+    not_null<std::vector<int>> y({1, 2});
+#endif
+    int i = 12;
+    auto rp = RefCounted<int>(&i);
+    not_null<int*> p(rp);
+    CHECK(p.get() == &i);
+
+    not_null<std::shared_ptr<int>> x(
+        std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
+
+#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
+    int* pi = nullptr;
+    CHECK_THROWS_AS(not_null<decltype(pi)>(pi), fail_fast);
+#endif    
+}
+
+template<typename T>
+void ostream_helper(T v)
+{
+    not_null<T*> p(&v);
+    {
+        std::ostringstream os;
+        std::ostringstream ref;
+        os << p;
+        ref << &v;
+        CHECK(os.str() == ref.str());
+    }
+    {
+        std::ostringstream os;
+        std::ostringstream ref;
+        os << *p;
+        ref << v;
+        CHECK(os.str() == ref.str());
+    }
+}
+
+TEST_CASE("TestNotNullostream")
+{
+    ostream_helper<int>(17);
+    ostream_helper<float>(21.5f);
+    ostream_helper<double>(3.4566e-7f);
+    ostream_helper<char>('c');
+    ostream_helper<uint16_t>(0x0123u);
+    ostream_helper<const char*>("cstring");
+    ostream_helper<std::string>("string");
+}
+
+
+TEST_CASE("TestNotNullCasting")
+{
+    MyBase base;
+    MyDerived derived;
+    Unrelated unrelated;
+    not_null<Unrelated*> u{&unrelated};
+    (void) u;
+    not_null<MyDerived*> p{&derived};
+    not_null<MyBase*> q(&base);
+    q = p; // allowed with heterogeneous copy ctor
+    CHECK(q == p);
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+    q = u; // no viable conversion possible between MyBase* and Unrelated*
+    p = q; // not possible to implicitly convert MyBase* to MyDerived*
+
+    not_null<Unrelated*> r = p;
+    not_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p);
+#endif
+    not_null<Unrelated*> t(reinterpret_cast<Unrelated*>(p.get()));
+    CHECK(reinterpret_cast<void*>(p.get()) == reinterpret_cast<void*>(t.get()));
+}
+
+TEST_CASE("TestNotNullAssignment")
+{
+    int i = 12;
+    not_null<int*> p(&i);
+    CHECK(helper(p));
+
+    int* q = nullptr;
+    CHECK_THROWS_AS(p = not_null<int*>(q), fail_fast);
+}
+
+TEST_CASE("TestNotNullRawPointerComparison")
+{
+    int ints[2] = {42, 43};
+    int* p1 = &ints[0];
+    const int* p2 = &ints[1];
+
+    using NotNull1 = not_null<decltype(p1)>;
+    using NotNull2 = not_null<decltype(p2)>;
+
+    CHECK((NotNull1(p1) == NotNull1(p1)) == true);
+    CHECK((NotNull1(p1) == NotNull2(p2)) == false);
+
+    CHECK((NotNull1(p1) != NotNull1(p1)) == false);
+    CHECK((NotNull1(p1) != NotNull2(p2)) == true);
+
+    CHECK((NotNull1(p1) < NotNull1(p1)) == false);
+    CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2));
+    CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1));
+
+    CHECK((NotNull1(p1) > NotNull1(p1)) == false);
+    CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2));
+    CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1));
+
+    CHECK((NotNull1(p1) <= NotNull1(p1)) == true);
+    CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
+    CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
+
+}
+
+TEST_CASE("TestNotNullDereferenceOperator")
+{
+    {
+        auto sp1 = std::make_shared<NonCopyableNonMovable>();
+
+        using NotNullSp1 = not_null<decltype(sp1)>;
+        CHECK(typeid(*sp1) == typeid(*NotNullSp1(sp1))); 
+        CHECK(std::addressof(*NotNullSp1(sp1)) == std::addressof(*sp1));
+    }
+
+    {
+        int ints[1] = { 42 };
+        CustomPtr<int> p1(&ints[0]);
+
+        using NotNull1 = not_null<decltype(p1)>;
+        CHECK(typeid(*NotNull1(p1)) == typeid(*p1));
+        CHECK(*NotNull1(p1) == 42);
+        *NotNull1(p1) = 43;
+        CHECK(ints[0] == 43);
+    }
+
+    {
+        int v = 42;
+        gsl::not_null<int*> p(&v);
+        CHECK(typeid(*p) == typeid(*(&v)));
+        *p = 43;
+        CHECK(v == 43);
+    }
+}
+
+TEST_CASE("TestNotNullSharedPtrComparison")
+{
+    auto sp1 = std::make_shared<int>(42);
+    auto sp2 = std::make_shared<const int>(43);
+
+    using NotNullSp1 = not_null<decltype(sp1)>;
+    using NotNullSp2 = not_null<decltype(sp2)>;
+
+    CHECK((NotNullSp1(sp1) == NotNullSp1(sp1)) == true);
+    CHECK((NotNullSp1(sp1) == NotNullSp2(sp2)) == false);
+
+    CHECK((NotNullSp1(sp1) != NotNullSp1(sp1)) == false);
+    CHECK((NotNullSp1(sp1) != NotNullSp2(sp2)) == true);
+
+    CHECK((NotNullSp1(sp1) < NotNullSp1(sp1)) == false);
+    CHECK((NotNullSp1(sp1) < NotNullSp2(sp2)) == (sp1 < sp2));
+    CHECK((NotNullSp2(sp2) < NotNullSp1(sp1)) == (sp2 < sp1));
+
+    CHECK((NotNullSp1(sp1) > NotNullSp1(sp1)) == false);
+    CHECK((NotNullSp1(sp1) > NotNullSp2(sp2)) == (sp1 > sp2));
+    CHECK((NotNullSp2(sp2) > NotNullSp1(sp1)) == (sp2 > sp1));
+
+    CHECK((NotNullSp1(sp1) <= NotNullSp1(sp1)) == true);
+    CHECK((NotNullSp1(sp1) <= NotNullSp2(sp2)) == (sp1 <= sp2));
+    CHECK((NotNullSp2(sp2) <= NotNullSp1(sp1)) == (sp2 <= sp1));
+
+    CHECK((NotNullSp1(sp1) >= NotNullSp1(sp1)) == true);
+    CHECK((NotNullSp1(sp1) >= NotNullSp2(sp2)) == (sp1 >= sp2));
+    CHECK((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1));
+}
+
+TEST_CASE("TestNotNullCustomPtrComparison")
+{
+    int ints[2] = {42, 43};
+    CustomPtr<int> p1(&ints[0]);
+    CustomPtr<const int> p2(&ints[1]);
+
+    using NotNull1 = not_null<decltype(p1)>;
+    using NotNull2 = not_null<decltype(p2)>;
+
+    CHECK((NotNull1(p1) == NotNull1(p1)) == "true");
+    CHECK((NotNull1(p1) == NotNull2(p2)) == "false");
+
+    CHECK((NotNull1(p1) != NotNull1(p1)) == "false");
+    CHECK((NotNull1(p1) != NotNull2(p2)) == "true");
+
+    CHECK((NotNull1(p1) < NotNull1(p1)) == "false");
+    CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2));
+    CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1));
+
+    CHECK((NotNull1(p1) > NotNull1(p1)) == "false");
+    CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2));
+    CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1));
+
+    CHECK((NotNull1(p1) <= NotNull1(p1)) == "true");
+    CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
+    CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
+
+    CHECK((NotNull1(p1) >= NotNull1(p1)) == "true");
+    CHECK((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2));
+    CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1));
+}
+
+
+#if defined(__cplusplus) && (__cplusplus >= 201703L)
+TEST_CASE("TestNotNullConstructorTypeDeduction")
+{
+    {
+        int i = 42;
+
+        not_null x{&i};
+        helper(not_null{&i});
+        helper_const(not_null{&i});
+
+        CHECK(*x == 42);
+    }
+
+    {
+        int i = 42;
+        int* p = &i;
+
+        not_null x{p};
+        helper(not_null{p});
+        helper_const(not_null{p});
+
+        CHECK(*x == 42);
+    }
+
+    {
+        auto workaround_macro = []() {
+            int* p1 = nullptr;
+            not_null x{p1};
+        };
+        CHECK_THROWS_AS(workaround_macro(), fail_fast);
+    }
+
+    {
+        auto workaround_macro = []() {
+            const int* p1 = nullptr;
+            not_null x{p1};
+        };
+        CHECK_THROWS_AS(workaround_macro(), fail_fast);
+    }
+
+    {
+        int* p = nullptr;
+
+        CHECK_THROWS_AS(helper(not_null{p}), fail_fast);
+        CHECK_THROWS_AS(helper_const(not_null{p}), fail_fast);
+    }
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+    {
+        not_null x{nullptr};
+        helper(not_null{nullptr});
+        helper_const(not_null{nullptr});
+    }
+#endif
+}
+#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)
+
+static_assert(std::is_nothrow_move_constructible<not_null<void *>>::value, "not_null must be no-throw move constructible");