aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'clang/unittests/Analysis')
-rw-r--r--clang/unittests/Analysis/CMakeLists.txt1
-rw-r--r--clang/unittests/Analysis/FlowSensitive/CMakeLists.txt1
-rw-r--r--clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp1259
-rw-r--r--clang/unittests/Analysis/FlowSensitive/MockHeaders.h30
-rw-r--r--clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp1238
-rw-r--r--clang/unittests/Analysis/LifetimeSafetyTest.cpp25
6 files changed, 1309 insertions, 1245 deletions
diff --git a/clang/unittests/Analysis/CMakeLists.txt b/clang/unittests/Analysis/CMakeLists.txt
index 52e7d28..e0acf43 100644
--- a/clang/unittests/Analysis/CMakeLists.txt
+++ b/clang/unittests/Analysis/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_unittest(ClangAnalysisTests
clangAST
clangASTMatchers
clangAnalysis
+ clangAnalysisLifetimeSafety
clangBasic
clangFrontend
clangLex
diff --git a/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt b/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
index 3bd4a6e..3508238 100644
--- a/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
+++ b/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
@@ -12,6 +12,7 @@ add_clang_unittest(ClangAnalysisFlowSensitiveTests
LoggerTest.cpp
MapLatticeTest.cpp
MatchSwitchTest.cpp
+ MockHeaders.cpp
MultiVarConstantPropagationTest.cpp
RecordOpsTest.cpp
SignAnalysisTest.cpp
diff --git a/clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp b/clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp
new file mode 100644
index 0000000..c280921
--- /dev/null
+++ b/clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp
@@ -0,0 +1,1259 @@
+//===--- MockHeaders.cpp - Mock headers for dataflow analyses -*- C++ ---*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines mock headers for testing of dataflow analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MockHeaders.h"
+
+namespace clang {
+namespace dataflow {
+namespace test {
+static constexpr char CStdDefHeader[] = R"(
+#ifndef CSTDDEF_H
+#define CSTDDEF_H
+
+namespace std {
+
+typedef decltype(sizeof(char)) size_t;
+
+using nullptr_t = decltype(nullptr);
+
+} // namespace std
+
+#endif // CSTDDEF_H
+)";
+
+static constexpr char StdTypeTraitsHeader[] = R"(
+#ifndef STD_TYPE_TRAITS_H
+#define STD_TYPE_TRAITS_H
+
+#include "cstddef.h"
+
+namespace std {
+
+template <typename T, T V>
+struct integral_constant {
+ static constexpr T value = V;
+};
+
+using true_type = integral_constant<bool, true>;
+using false_type = integral_constant<bool, false>;
+
+template< class T > struct remove_reference {typedef T type;};
+template< class T > struct remove_reference<T&> {typedef T type;};
+template< class T > struct remove_reference<T&&> {typedef T type;};
+
+template <class T>
+ using remove_reference_t = typename remove_reference<T>::type;
+
+template <class T>
+struct remove_extent {
+ typedef T type;
+};
+
+template <class T>
+struct remove_extent<T[]> {
+ typedef T type;
+};
+
+template <class T, size_t N>
+struct remove_extent<T[N]> {
+ typedef T type;
+};
+
+template <class T>
+struct is_array : false_type {};
+
+template <class T>
+struct is_array<T[]> : true_type {};
+
+template <class T, size_t N>
+struct is_array<T[N]> : true_type {};
+
+template <class>
+struct is_function : false_type {};
+
+template <class Ret, class... Args>
+struct is_function<Ret(Args...)> : true_type {};
+
+namespace detail {
+
+template <class T>
+struct type_identity {
+ using type = T;
+}; // or use type_identity (since C++20)
+
+template <class T>
+auto try_add_pointer(int) -> type_identity<typename remove_reference<T>::type*>;
+template <class T>
+auto try_add_pointer(...) -> type_identity<T>;
+
+} // namespace detail
+
+template <class T>
+struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};
+
+template <bool B, class T, class F>
+struct conditional {
+ typedef T type;
+};
+
+template <class T, class F>
+struct conditional<false, T, F> {
+ typedef F type;
+};
+
+template <class T>
+struct remove_cv {
+ typedef T type;
+};
+template <class T>
+struct remove_cv<const T> {
+ typedef T type;
+};
+template <class T>
+struct remove_cv<volatile T> {
+ typedef T type;
+};
+template <class T>
+struct remove_cv<const volatile T> {
+ typedef T type;
+};
+
+template <class T>
+using remove_cv_t = typename remove_cv<T>::type;
+
+template <class T>
+struct decay {
+ private:
+ typedef typename remove_reference<T>::type U;
+
+ public:
+ typedef typename conditional<
+ is_array<U>::value, typename remove_extent<U>::type*,
+ typename conditional<is_function<U>::value, typename add_pointer<U>::type,
+ typename remove_cv<U>::type>::type>::type type;
+};
+
+template <bool B, class T = void>
+struct enable_if {};
+
+template <class T>
+struct enable_if<true, T> {
+ typedef T type;
+};
+
+template <bool B, class T = void>
+using enable_if_t = typename enable_if<B, T>::type;
+
+template <class T, class U>
+struct is_same : false_type {};
+
+template <class T>
+struct is_same<T, T> : true_type {};
+
+template <class T>
+struct is_void : is_same<void, typename remove_cv<T>::type> {};
+
+namespace detail {
+
+template <class T>
+auto try_add_lvalue_reference(int) -> type_identity<T&>;
+template <class T>
+auto try_add_lvalue_reference(...) -> type_identity<T>;
+
+template <class T>
+auto try_add_rvalue_reference(int) -> type_identity<T&&>;
+template <class T>
+auto try_add_rvalue_reference(...) -> type_identity<T>;
+
+} // namespace detail
+
+template <class T>
+struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference<T>(0)) {
+};
+
+template <class T>
+struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference<T>(0)) {
+};
+
+template <class T>
+typename add_rvalue_reference<T>::type declval() noexcept;
+
+namespace detail {
+
+template <class T>
+auto test_returnable(int)
+ -> decltype(void(static_cast<T (*)()>(nullptr)), true_type{});
+template <class>
+auto test_returnable(...) -> false_type;
+
+template <class From, class To>
+auto test_implicitly_convertible(int)
+ -> decltype(void(declval<void (&)(To)>()(declval<From>())), true_type{});
+template <class, class>
+auto test_implicitly_convertible(...) -> false_type;
+
+} // namespace detail
+
+template <class From, class To>
+struct is_convertible
+ : integral_constant<bool,
+ (decltype(detail::test_returnable<To>(0))::value &&
+ decltype(detail::test_implicitly_convertible<From, To>(
+ 0))::value) ||
+ (is_void<From>::value && is_void<To>::value)> {};
+
+template <class From, class To>
+inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
+
+template <class...>
+using void_t = void;
+
+template <class, class T, class... Args>
+struct is_constructible_ : false_type {};
+
+template <class T, class... Args>
+struct is_constructible_<void_t<decltype(T(declval<Args>()...))>, T, Args...>
+ : true_type {};
+
+template <class T, class... Args>
+using is_constructible = is_constructible_<void_t<>, T, Args...>;
+
+template <class T, class... Args>
+inline constexpr bool is_constructible_v = is_constructible<T, Args...>::value;
+
+template <class _Tp>
+struct __uncvref {
+ typedef typename remove_cv<typename remove_reference<_Tp>::type>::type type;
+};
+
+template <class _Tp>
+using __uncvref_t = typename __uncvref<_Tp>::type;
+
+template <bool _Val>
+using _BoolConstant = integral_constant<bool, _Val>;
+
+template <class _Tp, class _Up>
+using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
+
+template <class _Tp, class _Up>
+using _IsNotSame = _BoolConstant<!__is_same(_Tp, _Up)>;
+
+template <bool>
+struct _MetaBase;
+template <>
+struct _MetaBase<true> {
+ template <class _Tp, class _Up>
+ using _SelectImpl = _Tp;
+ template <template <class...> class _FirstFn, template <class...> class,
+ class... _Args>
+ using _SelectApplyImpl = _FirstFn<_Args...>;
+ template <class _First, class...>
+ using _FirstImpl = _First;
+ template <class, class _Second, class...>
+ using _SecondImpl = _Second;
+ template <class _Result, class _First, class... _Rest>
+ using _OrImpl =
+ typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::
+ template _OrImpl<_First, _Rest...>;
+};
+
+template <>
+struct _MetaBase<false> {
+ template <class _Tp, class _Up>
+ using _SelectImpl = _Up;
+ template <template <class...> class, template <class...> class _SecondFn,
+ class... _Args>
+ using _SelectApplyImpl = _SecondFn<_Args...>;
+ template <class _Result, class...>
+ using _OrImpl = _Result;
+};
+
+template <bool _Cond, class _IfRes, class _ElseRes>
+using _If = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>;
+
+template <class... _Rest>
+using _Or = typename _MetaBase<sizeof...(_Rest) !=
+ 0>::template _OrImpl<false_type, _Rest...>;
+
+template <bool _Bp, class _Tp = void>
+using __enable_if_t = typename enable_if<_Bp, _Tp>::type;
+
+template <class...>
+using __expand_to_true = true_type;
+template <class... _Pred>
+__expand_to_true<__enable_if_t<_Pred::value>...> __and_helper(int);
+template <class...>
+false_type __and_helper(...);
+template <class... _Pred>
+using _And = decltype(__and_helper<_Pred...>(0));
+
+template <class _Pred>
+struct _Not : _BoolConstant<!_Pred::value> {};
+
+struct __check_tuple_constructor_fail {
+ static constexpr bool __enable_explicit_default() { return false; }
+ static constexpr bool __enable_implicit_default() { return false; }
+ template <class...>
+ static constexpr bool __enable_explicit() {
+ return false;
+ }
+ template <class...>
+ static constexpr bool __enable_implicit() {
+ return false;
+ }
+};
+
+template <typename, typename _Tp>
+struct __select_2nd {
+ typedef _Tp type;
+};
+template <class _Tp, class _Arg>
+typename __select_2nd<decltype((declval<_Tp>() = declval<_Arg>())),
+ true_type>::type
+__is_assignable_test(int);
+template <class, class>
+false_type __is_assignable_test(...);
+template <class _Tp, class _Arg,
+ bool = is_void<_Tp>::value || is_void<_Arg>::value>
+struct __is_assignable_imp
+ : public decltype((__is_assignable_test<_Tp, _Arg>(0))) {};
+template <class _Tp, class _Arg>
+struct __is_assignable_imp<_Tp, _Arg, true> : public false_type {};
+template <class _Tp, class _Arg>
+struct is_assignable : public __is_assignable_imp<_Tp, _Arg> {};
+
+template <class _Tp>
+struct __libcpp_is_integral : public false_type {};
+template <>
+struct __libcpp_is_integral<bool> : public true_type {};
+template <>
+struct __libcpp_is_integral<char> : public true_type {};
+template <>
+struct __libcpp_is_integral<signed char> : public true_type {};
+template <>
+struct __libcpp_is_integral<unsigned char> : public true_type {};
+template <>
+struct __libcpp_is_integral<wchar_t> : public true_type {};
+template <>
+struct __libcpp_is_integral<short> : public true_type {}; // NOLINT
+template <>
+struct __libcpp_is_integral<unsigned short> : public true_type {}; // NOLINT
+template <>
+struct __libcpp_is_integral<int> : public true_type {};
+template <>
+struct __libcpp_is_integral<unsigned int> : public true_type {};
+template <>
+struct __libcpp_is_integral<long> : public true_type {}; // NOLINT
+template <>
+struct __libcpp_is_integral<unsigned long> : public true_type {}; // NOLINT
+template <>
+struct __libcpp_is_integral<long long> : public true_type {}; // NOLINT
+template <> // NOLINTNEXTLINE
+struct __libcpp_is_integral<unsigned long long> : public true_type {};
+template <class _Tp>
+struct is_integral
+ : public __libcpp_is_integral<typename remove_cv<_Tp>::type> {};
+
+template <class _Tp>
+struct __libcpp_is_floating_point : public false_type {};
+template <>
+struct __libcpp_is_floating_point<float> : public true_type {};
+template <>
+struct __libcpp_is_floating_point<double> : public true_type {};
+template <>
+struct __libcpp_is_floating_point<long double> : public true_type {};
+template <class _Tp>
+struct is_floating_point
+ : public __libcpp_is_floating_point<typename remove_cv<_Tp>::type> {};
+
+template <class _Tp>
+struct is_arithmetic
+ : public integral_constant<bool, is_integral<_Tp>::value ||
+ is_floating_point<_Tp>::value> {};
+
+template <class _Tp>
+struct __libcpp_is_pointer : public false_type {};
+template <class _Tp>
+struct __libcpp_is_pointer<_Tp*> : public true_type {};
+template <class _Tp>
+struct is_pointer : public __libcpp_is_pointer<typename remove_cv<_Tp>::type> {
+};
+
+template <class _Tp>
+struct __libcpp_is_member_pointer : public false_type {};
+template <class _Tp, class _Up>
+struct __libcpp_is_member_pointer<_Tp _Up::*> : public true_type {};
+template <class _Tp>
+struct is_member_pointer
+ : public __libcpp_is_member_pointer<typename remove_cv<_Tp>::type> {};
+
+template <class _Tp>
+struct __libcpp_union : public false_type {};
+template <class _Tp>
+struct is_union : public __libcpp_union<typename remove_cv<_Tp>::type> {};
+
+template <class T>
+struct is_reference : false_type {};
+template <class T>
+struct is_reference<T&> : true_type {};
+template <class T>
+struct is_reference<T&&> : true_type {};
+
+template <class T>
+inline constexpr bool is_reference_v = is_reference<T>::value;
+
+struct __two {
+ char __lx[2];
+};
+
+namespace __is_class_imp {
+template <class _Tp>
+char __test(int _Tp::*);
+template <class _Tp>
+__two __test(...);
+} // namespace __is_class_imp
+template <class _Tp>
+struct is_class
+ : public integral_constant<bool,
+ sizeof(__is_class_imp::__test<_Tp>(0)) == 1 &&
+ !is_union<_Tp>::value> {};
+
+template <class _Tp>
+struct __is_nullptr_t_impl : public false_type {};
+template <>
+struct __is_nullptr_t_impl<nullptr_t> : public true_type {};
+template <class _Tp>
+struct __is_nullptr_t
+ : public __is_nullptr_t_impl<typename remove_cv<_Tp>::type> {};
+template <class _Tp>
+struct is_null_pointer
+ : public __is_nullptr_t_impl<typename remove_cv<_Tp>::type> {};
+
+template <class _Tp>
+struct is_enum
+ : public integral_constant<
+ bool, !is_void<_Tp>::value && !is_integral<_Tp>::value &&
+ !is_floating_point<_Tp>::value && !is_array<_Tp>::value &&
+ !is_pointer<_Tp>::value && !is_reference<_Tp>::value &&
+ !is_member_pointer<_Tp>::value && !is_union<_Tp>::value &&
+ !is_class<_Tp>::value && !is_function<_Tp>::value> {};
+
+template <class _Tp>
+struct is_scalar
+ : public integral_constant<
+ bool, is_arithmetic<_Tp>::value || is_member_pointer<_Tp>::value ||
+ is_pointer<_Tp>::value || __is_nullptr_t<_Tp>::value ||
+ is_enum<_Tp>::value> {};
+template <>
+struct is_scalar<nullptr_t> : public true_type {};
+
+} // namespace std
+
+#endif // STD_TYPE_TRAITS_H
+)";
+
+static constexpr char AbslTypeTraitsHeader[] = R"(
+#ifndef ABSL_TYPE_TRAITS_H
+#define ABSL_TYPE_TRAITS_H
+
+#include "std_type_traits.h"
+
+namespace absl {
+
+template <typename... Ts>
+struct conjunction : std::true_type {};
+
+template <typename T, typename... Ts>
+struct conjunction<T, Ts...>
+ : std::conditional<T::value, conjunction<Ts...>, T>::type {};
+
+template <typename T>
+struct conjunction<T> : T {};
+
+template <typename T>
+struct negation : std::integral_constant<bool, !T::value> {};
+
+template <bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+} // namespace absl
+
+#endif // ABSL_TYPE_TRAITS_H
+)";
+
+static constexpr char StdStringHeader[] = R"(
+#ifndef STRING_H
+#define STRING_H
+
+namespace std {
+
+struct string {
+ string(const char*);
+ ~string();
+ bool empty();
+};
+bool operator!=(const string &LHS, const char *RHS);
+
+} // namespace std
+
+#endif // STRING_H
+)";
+
+static constexpr char StdUtilityHeader[] = R"(
+#ifndef UTILITY_H
+#define UTILITY_H
+
+#include "std_type_traits.h"
+
+namespace std {
+
+template <typename T>
+constexpr remove_reference_t<T>&& move(T&& x);
+
+template <typename T>
+void swap(T& a, T& b) noexcept;
+
+} // namespace std
+
+#endif // UTILITY_H
+)";
+
+static constexpr char StdInitializerListHeader[] = R"(
+#ifndef INITIALIZER_LIST_H
+#define INITIALIZER_LIST_H
+
+namespace std {
+
+template <typename T>
+class initializer_list {
+ public:
+ const T *a, *b;
+ initializer_list() noexcept;
+};
+
+} // namespace std
+
+#endif // INITIALIZER_LIST_H
+)";
+
+static constexpr char StdOptionalHeader[] = R"(
+#include "std_initializer_list.h"
+#include "std_type_traits.h"
+#include "std_utility.h"
+
+namespace std {
+
+struct in_place_t {};
+constexpr in_place_t in_place;
+
+struct nullopt_t {
+ constexpr explicit nullopt_t() {}
+};
+constexpr nullopt_t nullopt;
+
+template <class _Tp>
+struct __optional_destruct_base {
+ constexpr void reset() noexcept;
+};
+
+template <class _Tp>
+struct __optional_storage_base : __optional_destruct_base<_Tp> {
+ constexpr bool has_value() const noexcept;
+};
+
+template <typename _Tp>
+class optional : private __optional_storage_base<_Tp> {
+ using __base = __optional_storage_base<_Tp>;
+
+ public:
+ using value_type = _Tp;
+
+ private:
+ struct _CheckOptionalArgsConstructor {
+ template <class _Up>
+ static constexpr bool __enable_implicit() {
+ return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>;
+ }
+
+ template <class _Up>
+ static constexpr bool __enable_explicit() {
+ return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>;
+ }
+ };
+ template <class _Up>
+ using _CheckOptionalArgsCtor =
+ _If<_IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
+ _IsNotSame<__uncvref_t<_Up>, optional>::value,
+ _CheckOptionalArgsConstructor, __check_tuple_constructor_fail>;
+ template <class _QualUp>
+ struct _CheckOptionalLikeConstructor {
+ template <class _Up, class _Opt = optional<_Up>>
+ using __check_constructible_from_opt =
+ _Or<is_constructible<_Tp, _Opt&>, is_constructible<_Tp, _Opt const&>,
+ is_constructible<_Tp, _Opt&&>, is_constructible<_Tp, _Opt const&&>,
+ is_convertible<_Opt&, _Tp>, is_convertible<_Opt const&, _Tp>,
+ is_convertible<_Opt&&, _Tp>, is_convertible<_Opt const&&, _Tp>>;
+ template <class _Up, class _QUp = _QualUp>
+ static constexpr bool __enable_implicit() {
+ return is_convertible<_QUp, _Tp>::value &&
+ !__check_constructible_from_opt<_Up>::value;
+ }
+ template <class _Up, class _QUp = _QualUp>
+ static constexpr bool __enable_explicit() {
+ return !is_convertible<_QUp, _Tp>::value &&
+ !__check_constructible_from_opt<_Up>::value;
+ }
+ };
+
+ template <class _Up, class _QualUp>
+ using _CheckOptionalLikeCtor =
+ _If<_And<_IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>>::value,
+ _CheckOptionalLikeConstructor<_QualUp>,
+ __check_tuple_constructor_fail>;
+
+
+ template <class _Up, class _QualUp>
+ using _CheckOptionalLikeAssign = _If<
+ _And<
+ _IsNotSame<_Up, _Tp>,
+ is_constructible<_Tp, _QualUp>,
+ is_assignable<_Tp&, _QualUp>
+ >::value,
+ _CheckOptionalLikeConstructor<_QualUp>,
+ __check_tuple_constructor_fail
+ >;
+
+ public:
+ constexpr optional() noexcept {}
+ constexpr optional(const optional&) = default;
+ constexpr optional(optional&&) = default;
+ constexpr optional(nullopt_t) noexcept {}
+
+ template <
+ class _InPlaceT, class... _Args,
+ class = enable_if_t<_And<_IsSame<_InPlaceT, in_place_t>,
+ is_constructible<value_type, _Args...>>::value>>
+ constexpr explicit optional(_InPlaceT, _Args&&... __args);
+
+ template <class _Up, class... _Args,
+ class = enable_if_t<is_constructible_v<
+ value_type, initializer_list<_Up>&, _Args...>>>
+ constexpr explicit optional(in_place_t, initializer_list<_Up> __il,
+ _Args&&... __args);
+
+ template <
+ class _Up = value_type,
+ enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(),
+ int> = 0>
+ constexpr optional(_Up&& __v);
+
+ template <
+ class _Up,
+ enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(),
+ int> = 0>
+ constexpr explicit optional(_Up&& __v);
+
+ template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::
+ template __enable_implicit<_Up>(),
+ int> = 0>
+ constexpr optional(const optional<_Up>& __v);
+
+ template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::
+ template __enable_explicit<_Up>(),
+ int> = 0>
+ constexpr explicit optional(const optional<_Up>& __v);
+
+ template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::
+ template __enable_implicit<_Up>(),
+ int> = 0>
+ constexpr optional(optional<_Up>&& __v);
+
+ template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::
+ template __enable_explicit<_Up>(),
+ int> = 0>
+ constexpr explicit optional(optional<_Up>&& __v);
+
+ constexpr optional& operator=(nullopt_t) noexcept;
+
+ optional& operator=(const optional&);
+
+ optional& operator=(optional&&);
+
+ template <class _Up = value_type,
+ class = enable_if_t<_And<_IsNotSame<__uncvref_t<_Up>, optional>,
+ _Or<_IsNotSame<__uncvref_t<_Up>, value_type>,
+ _Not<is_scalar<value_type>>>,
+ is_constructible<value_type, _Up>,
+ is_assignable<value_type&, _Up>>::value>>
+ constexpr optional& operator=(_Up&& __v);
+
+ template <class _Up, enable_if_t<_CheckOptionalLikeAssign<_Up, _Up const&>::
+ template __enable_assign<_Up>(),
+ int> = 0>
+ constexpr optional& operator=(const optional<_Up>& __v);
+
+ template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::
+ template __enable_assign<_Up>(),
+ int> = 0>
+ constexpr optional& operator=(optional<_Up>&& __v);
+
+ const _Tp& operator*() const&;
+ _Tp& operator*() &;
+ const _Tp&& operator*() const&&;
+ _Tp&& operator*() &&;
+
+ const _Tp* operator->() const;
+ _Tp* operator->();
+
+ const _Tp& value() const&;
+ _Tp& value() &;
+ const _Tp&& value() const&&;
+ _Tp&& value() &&;
+
+ template <typename U>
+ constexpr _Tp value_or(U&& v) const&;
+ template <typename U>
+ _Tp value_or(U&& v) &&;
+
+ template <typename... Args>
+ _Tp& emplace(Args&&... args);
+
+ template <typename U, typename... Args>
+ _Tp& emplace(std::initializer_list<U> ilist, Args&&... args);
+
+ using __base::reset;
+
+ constexpr explicit operator bool() const noexcept;
+ using __base::has_value;
+
+ constexpr void swap(optional& __opt) noexcept;
+};
+
+template <typename T>
+constexpr optional<typename std::decay<T>::type> make_optional(T&& v);
+
+template <typename T, typename... Args>
+constexpr optional<T> make_optional(Args&&... args);
+
+template <typename T, typename U, typename... Args>
+constexpr optional<T> make_optional(std::initializer_list<U> il,
+ Args&&... args);
+
+template <typename T, typename U>
+constexpr bool operator==(const optional<T> &lhs, const optional<U> &rhs);
+template <typename T, typename U>
+constexpr bool operator!=(const optional<T> &lhs, const optional<U> &rhs);
+
+template <typename T>
+constexpr bool operator==(const optional<T> &opt, nullopt_t);
+
+// C++20 and later do not define the following overloads because they are
+// provided by rewritten candidates instead.
+#if __cplusplus < 202002L
+template <typename T>
+constexpr bool operator==(nullopt_t, const optional<T> &opt);
+template <typename T>
+constexpr bool operator!=(const optional<T> &opt, nullopt_t);
+template <typename T>
+constexpr bool operator!=(nullopt_t, const optional<T> &opt);
+#endif // __cplusplus < 202002L
+
+template <typename T, typename U>
+constexpr bool operator==(const optional<T> &opt, const U &value);
+template <typename T, typename U>
+constexpr bool operator==(const T &value, const optional<U> &opt);
+template <typename T, typename U>
+constexpr bool operator!=(const optional<T> &opt, const U &value);
+template <typename T, typename U>
+constexpr bool operator!=(const T &value, const optional<U> &opt);
+
+} // namespace std
+)";
+
+static constexpr char AbslOptionalHeader[] = R"(
+#include "absl_type_traits.h"
+#include "std_initializer_list.h"
+#include "std_type_traits.h"
+#include "std_utility.h"
+
+namespace absl {
+
+struct nullopt_t {
+ constexpr explicit nullopt_t() {}
+};
+constexpr nullopt_t nullopt;
+
+struct in_place_t {};
+constexpr in_place_t in_place;
+
+template <typename T>
+class optional;
+
+namespace optional_internal {
+
+template <typename T, typename U>
+struct is_constructible_convertible_from_optional
+ : std::integral_constant<
+ bool, std::is_constructible<T, optional<U>&>::value ||
+ std::is_constructible<T, optional<U>&&>::value ||
+ std::is_constructible<T, const optional<U>&>::value ||
+ std::is_constructible<T, const optional<U>&&>::value ||
+ std::is_convertible<optional<U>&, T>::value ||
+ std::is_convertible<optional<U>&&, T>::value ||
+ std::is_convertible<const optional<U>&, T>::value ||
+ std::is_convertible<const optional<U>&&, T>::value> {};
+
+template <typename T, typename U>
+struct is_constructible_convertible_assignable_from_optional
+ : std::integral_constant<
+ bool, is_constructible_convertible_from_optional<T, U>::value ||
+ std::is_assignable<T&, optional<U>&>::value ||
+ std::is_assignable<T&, optional<U>&&>::value ||
+ std::is_assignable<T&, const optional<U>&>::value ||
+ std::is_assignable<T&, const optional<U>&&>::value> {};
+
+} // namespace optional_internal
+
+template <typename T>
+class optional {
+ public:
+ constexpr optional() noexcept;
+
+ constexpr optional(nullopt_t) noexcept;
+
+ optional(const optional&) = default;
+
+ optional(optional&&) = default;
+
+ template <typename InPlaceT, typename... Args,
+ absl::enable_if_t<absl::conjunction<
+ std::is_same<InPlaceT, in_place_t>,
+ std::is_constructible<T, Args&&...>>::value>* = nullptr>
+ constexpr explicit optional(InPlaceT, Args&&... args);
+
+ template <typename U, typename... Args,
+ typename = typename std::enable_if<std::is_constructible<
+ T, std::initializer_list<U>&, Args&&...>::value>::type>
+ constexpr explicit optional(in_place_t, std::initializer_list<U> il,
+ Args&&... args);
+
+ template <
+ typename U = T,
+ typename std::enable_if<
+ absl::conjunction<absl::negation<std::is_same<
+ in_place_t, typename std::decay<U>::type>>,
+ absl::negation<std::is_same<
+ optional<T>, typename std::decay<U>::type>>,
+ std::is_convertible<U&&, T>,
+ std::is_constructible<T, U&&>>::value,
+ bool>::type = false>
+ constexpr optional(U&& v);
+
+ template <
+ typename U = T,
+ typename std::enable_if<
+ absl::conjunction<absl::negation<std::is_same<
+ in_place_t, typename std::decay<U>::type>>,
+ absl::negation<std::is_same<
+ optional<T>, typename std::decay<U>::type>>,
+ absl::negation<std::is_convertible<U&&, T>>,
+ std::is_constructible<T, U&&>>::value,
+ bool>::type = false>
+ explicit constexpr optional(U&& v);
+
+ template <typename U,
+ typename std::enable_if<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>,
+ std::is_constructible<T, const U&>,
+ absl::negation<
+ optional_internal::
+ is_constructible_convertible_from_optional<T, U>>,
+ std::is_convertible<const U&, T>>::value,
+ bool>::type = false>
+ optional(const optional<U>& rhs);
+
+ template <typename U,
+ typename std::enable_if<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>,
+ std::is_constructible<T, const U&>,
+ absl::negation<
+ optional_internal::
+ is_constructible_convertible_from_optional<T, U>>,
+ absl::negation<std::is_convertible<const U&, T>>>::value,
+ bool>::type = false>
+ explicit optional(const optional<U>& rhs);
+
+ template <
+ typename U,
+ typename std::enable_if<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+ absl::negation<
+ optional_internal::is_constructible_convertible_from_optional<
+ T, U>>,
+ std::is_convertible<U&&, T>>::value,
+ bool>::type = false>
+ optional(optional<U>&& rhs);
+
+ template <
+ typename U,
+ typename std::enable_if<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+ absl::negation<
+ optional_internal::is_constructible_convertible_from_optional<
+ T, U>>,
+ absl::negation<std::is_convertible<U&&, T>>>::value,
+ bool>::type = false>
+ explicit optional(optional<U>&& rhs);
+
+ optional& operator=(nullopt_t) noexcept;
+
+ optional& operator=(const optional& src);
+
+ optional& operator=(optional&& src);
+
+ template <
+ typename U = T,
+ typename = typename std::enable_if<absl::conjunction<
+ absl::negation<
+ std::is_same<optional<T>, typename std::decay<U>::type>>,
+ absl::negation<
+ absl::conjunction<std::is_scalar<T>,
+ std::is_same<T, typename std::decay<U>::type>>>,
+ std::is_constructible<T, U>, std::is_assignable<T&, U>>::value>::type>
+ optional& operator=(U&& v);
+
+ template <
+ typename U,
+ typename = typename std::enable_if<absl::conjunction<
+ absl::negation<std::is_same<T, U>>,
+ std::is_constructible<T, const U&>, std::is_assignable<T&, const U&>,
+ absl::negation<
+ optional_internal::
+ is_constructible_convertible_assignable_from_optional<
+ T, U>>>::value>::type>
+ optional& operator=(const optional<U>& rhs);
+
+ template <typename U,
+ typename = typename std::enable_if<absl::conjunction<
+ absl::negation<std::is_same<T, U>>, std::is_constructible<T, U>,
+ std::is_assignable<T&, U>,
+ absl::negation<
+ optional_internal::
+ is_constructible_convertible_assignable_from_optional<
+ T, U>>>::value>::type>
+ optional& operator=(optional<U>&& rhs);
+
+ const T& operator*() const&;
+ T& operator*() &;
+ const T&& operator*() const&&;
+ T&& operator*() &&;
+
+ const T* operator->() const;
+ T* operator->();
+
+ const T& value() const&;
+ T& value() &;
+ const T&& value() const&&;
+ T&& value() &&;
+
+ template <typename U>
+ constexpr T value_or(U&& v) const&;
+ template <typename U>
+ T value_or(U&& v) &&;
+
+ template <typename... Args>
+ T& emplace(Args&&... args);
+
+ template <typename U, typename... Args>
+ T& emplace(std::initializer_list<U> ilist, Args&&... args);
+
+ void reset() noexcept;
+
+ constexpr explicit operator bool() const noexcept;
+ constexpr bool has_value() const noexcept;
+
+ void swap(optional& rhs) noexcept;
+};
+
+template <typename T>
+constexpr optional<typename std::decay<T>::type> make_optional(T&& v);
+
+template <typename T, typename... Args>
+constexpr optional<T> make_optional(Args&&... args);
+
+template <typename T, typename U, typename... Args>
+constexpr optional<T> make_optional(std::initializer_list<U> il,
+ Args&&... args);
+
+template <typename T, typename U>
+constexpr bool operator==(const optional<T> &lhs, const optional<U> &rhs);
+template <typename T, typename U>
+constexpr bool operator!=(const optional<T> &lhs, const optional<U> &rhs);
+
+template <typename T>
+constexpr bool operator==(const optional<T> &opt, nullopt_t);
+template <typename T>
+constexpr bool operator==(nullopt_t, const optional<T> &opt);
+template <typename T>
+constexpr bool operator!=(const optional<T> &opt, nullopt_t);
+template <typename T>
+constexpr bool operator!=(nullopt_t, const optional<T> &opt);
+
+template <typename T, typename U>
+constexpr bool operator==(const optional<T> &opt, const U &value);
+template <typename T, typename U>
+constexpr bool operator==(const T &value, const optional<U> &opt);
+template <typename T, typename U>
+constexpr bool operator!=(const optional<T> &opt, const U &value);
+template <typename T, typename U>
+constexpr bool operator!=(const T &value, const optional<U> &opt);
+
+} // namespace absl
+)";
+
+static constexpr char BaseOptionalHeader[] = R"(
+#include "std_initializer_list.h"
+#include "std_type_traits.h"
+#include "std_utility.h"
+
+namespace base {
+
+struct in_place_t {};
+constexpr in_place_t in_place;
+
+struct nullopt_t {
+ constexpr explicit nullopt_t() {}
+};
+constexpr nullopt_t nullopt;
+
+template <typename T>
+class Optional;
+
+namespace internal {
+
+template <typename T>
+using RemoveCvRefT = std::remove_cv_t<std::remove_reference_t<T>>;
+
+template <typename T, typename U>
+struct IsConvertibleFromOptional
+ : std::integral_constant<
+ bool, std::is_constructible<T, Optional<U>&>::value ||
+ std::is_constructible<T, const Optional<U>&>::value ||
+ std::is_constructible<T, Optional<U>&&>::value ||
+ std::is_constructible<T, const Optional<U>&&>::value ||
+ std::is_convertible<Optional<U>&, T>::value ||
+ std::is_convertible<const Optional<U>&, T>::value ||
+ std::is_convertible<Optional<U>&&, T>::value ||
+ std::is_convertible<const Optional<U>&&, T>::value> {};
+
+template <typename T, typename U>
+struct IsAssignableFromOptional
+ : std::integral_constant<
+ bool, IsConvertibleFromOptional<T, U>::value ||
+ std::is_assignable<T&, Optional<U>&>::value ||
+ std::is_assignable<T&, const Optional<U>&>::value ||
+ std::is_assignable<T&, Optional<U>&&>::value ||
+ std::is_assignable<T&, const Optional<U>&&>::value> {};
+
+} // namespace internal
+
+template <typename T>
+class Optional {
+ public:
+ using value_type = T;
+
+ constexpr Optional() = default;
+ constexpr Optional(const Optional& other) noexcept = default;
+ constexpr Optional(Optional&& other) noexcept = default;
+
+ constexpr Optional(nullopt_t);
+
+ template <typename U,
+ typename std::enable_if<
+ std::is_constructible<T, const U&>::value &&
+ !internal::IsConvertibleFromOptional<T, U>::value &&
+ std::is_convertible<const U&, T>::value,
+ bool>::type = false>
+ Optional(const Optional<U>& other) noexcept;
+
+ template <typename U,
+ typename std::enable_if<
+ std::is_constructible<T, const U&>::value &&
+ !internal::IsConvertibleFromOptional<T, U>::value &&
+ !std::is_convertible<const U&, T>::value,
+ bool>::type = false>
+ explicit Optional(const Optional<U>& other) noexcept;
+
+ template <typename U,
+ typename std::enable_if<
+ std::is_constructible<T, U&&>::value &&
+ !internal::IsConvertibleFromOptional<T, U>::value &&
+ std::is_convertible<U&&, T>::value,
+ bool>::type = false>
+ Optional(Optional<U>&& other) noexcept;
+
+ template <typename U,
+ typename std::enable_if<
+ std::is_constructible<T, U&&>::value &&
+ !internal::IsConvertibleFromOptional<T, U>::value &&
+ !std::is_convertible<U&&, T>::value,
+ bool>::type = false>
+ explicit Optional(Optional<U>&& other) noexcept;
+
+ template <class... Args>
+ constexpr explicit Optional(in_place_t, Args&&... args);
+
+ template <class U, class... Args,
+ class = typename std::enable_if<std::is_constructible<
+ value_type, std::initializer_list<U>&, Args...>::value>::type>
+ constexpr explicit Optional(in_place_t, std::initializer_list<U> il,
+ Args&&... args);
+
+ template <
+ typename U = value_type,
+ typename std::enable_if<
+ std::is_constructible<T, U&&>::value &&
+ !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
+ !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
+ std::is_convertible<U&&, T>::value,
+ bool>::type = false>
+ constexpr Optional(U&& value);
+
+ template <
+ typename U = value_type,
+ typename std::enable_if<
+ std::is_constructible<T, U&&>::value &&
+ !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
+ !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
+ !std::is_convertible<U&&, T>::value,
+ bool>::type = false>
+ constexpr explicit Optional(U&& value);
+
+ Optional& operator=(const Optional& other) noexcept;
+
+ Optional& operator=(Optional&& other) noexcept;
+
+ Optional& operator=(nullopt_t);
+
+ template <typename U>
+ typename std::enable_if<
+ !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
+ std::is_constructible<T, U>::value &&
+ std::is_assignable<T&, U>::value &&
+ (!std::is_scalar<T>::value ||
+ !std::is_same<typename std::decay<U>::type, T>::value),
+ Optional&>::type
+ operator=(U&& value) noexcept;
+
+ template <typename U>
+ typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
+ std::is_constructible<T, const U&>::value &&
+ std::is_assignable<T&, const U&>::value,
+ Optional&>::type
+ operator=(const Optional<U>& other) noexcept;
+
+ template <typename U>
+ typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
+ std::is_constructible<T, U>::value &&
+ std::is_assignable<T&, U>::value,
+ Optional&>::type
+ operator=(Optional<U>&& other) noexcept;
+
+ const T& operator*() const&;
+ T& operator*() &;
+ const T&& operator*() const&&;
+ T&& operator*() &&;
+
+ const T* operator->() const;
+ T* operator->();
+
+ const T& value() const&;
+ T& value() &;
+ const T&& value() const&&;
+ T&& value() &&;
+
+ template <typename U>
+ constexpr T value_or(U&& v) const&;
+ template <typename U>
+ T value_or(U&& v) &&;
+
+ template <typename... Args>
+ T& emplace(Args&&... args);
+
+ template <typename U, typename... Args>
+ T& emplace(std::initializer_list<U> ilist, Args&&... args);
+
+ void reset() noexcept;
+
+ constexpr explicit operator bool() const noexcept;
+ constexpr bool has_value() const noexcept;
+
+ void swap(Optional& other);
+};
+
+template <typename T>
+constexpr Optional<typename std::decay<T>::type> make_optional(T&& v);
+
+template <typename T, typename... Args>
+constexpr Optional<T> make_optional(Args&&... args);
+
+template <typename T, typename U, typename... Args>
+constexpr Optional<T> make_optional(std::initializer_list<U> il,
+ Args&&... args);
+
+template <typename T, typename U>
+constexpr bool operator==(const Optional<T> &lhs, const Optional<U> &rhs);
+template <typename T, typename U>
+constexpr bool operator!=(const Optional<T> &lhs, const Optional<U> &rhs);
+
+template <typename T>
+constexpr bool operator==(const Optional<T> &opt, nullopt_t);
+template <typename T>
+constexpr bool operator==(nullopt_t, const Optional<T> &opt);
+template <typename T>
+constexpr bool operator!=(const Optional<T> &opt, nullopt_t);
+template <typename T>
+constexpr bool operator!=(nullopt_t, const Optional<T> &opt);
+
+template <typename T, typename U>
+constexpr bool operator==(const Optional<T> &opt, const U &value);
+template <typename T, typename U>
+constexpr bool operator==(const T &value, const Optional<U> &opt);
+template <typename T, typename U>
+constexpr bool operator!=(const Optional<T> &opt, const U &value);
+template <typename T, typename U>
+constexpr bool operator!=(const T &value, const Optional<U> &opt);
+
+} // namespace base
+)";
+
+std::vector<std::pair<std::string, std::string>> getMockHeaders() {
+ std::vector<std::pair<std::string, std::string>> Headers;
+ Headers.emplace_back("cstddef.h", CStdDefHeader);
+ Headers.emplace_back("std_initializer_list.h", StdInitializerListHeader);
+ Headers.emplace_back("std_string.h", StdStringHeader);
+ Headers.emplace_back("std_type_traits.h", StdTypeTraitsHeader);
+ Headers.emplace_back("std_utility.h", StdUtilityHeader);
+ Headers.emplace_back("std_optional.h", StdOptionalHeader);
+ Headers.emplace_back("absl_type_traits.h", AbslTypeTraitsHeader);
+ Headers.emplace_back("absl_optional.h", AbslOptionalHeader);
+ Headers.emplace_back("base_optional.h", BaseOptionalHeader);
+ return Headers;
+}
+
+} // namespace test
+} // namespace dataflow
+} // namespace clang \ No newline at end of file
diff --git a/clang/unittests/Analysis/FlowSensitive/MockHeaders.h b/clang/unittests/Analysis/FlowSensitive/MockHeaders.h
new file mode 100644
index 0000000..c0b544f
--- /dev/null
+++ b/clang/unittests/Analysis/FlowSensitive/MockHeaders.h
@@ -0,0 +1,30 @@
+//===--- MockHeaders.h - Mock headers for dataflow analyses -*- C++ -----*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines mock headers for testing of dataflow analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOW_SENSITIVE_MOCK_HEADERS_H_
+#define LLVM_CLANG_ANALYSIS_FLOW_SENSITIVE_MOCK_HEADERS_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace clang {
+namespace dataflow {
+namespace test {
+
+std::vector<std::pair<std::string, std::string>> getMockHeaders();
+
+} // namespace test
+} // namespace dataflow
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_FLOW_SENSITIVE_MOCK_HEADERS_H_
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
index 1dd0783..ba509e8 100644
--- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -8,6 +8,7 @@
// FIXME: Move this to clang/unittests/Analysis/FlowSensitive/Models.
#include "clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h"
+#include "MockHeaders.h"
#include "TestingSupport.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchers.h"
@@ -31,1232 +32,6 @@ using namespace test;
using ::testing::ContainerEq;
-// FIXME: Move header definitions in separate file(s).
-static constexpr char CSDtdDefHeader[] = R"(
-#ifndef CSTDDEF_H
-#define CSTDDEF_H
-
-namespace std {
-
-typedef decltype(sizeof(char)) size_t;
-
-using nullptr_t = decltype(nullptr);
-
-} // namespace std
-
-#endif // CSTDDEF_H
-)";
-
-static constexpr char StdTypeTraitsHeader[] = R"(
-#ifndef STD_TYPE_TRAITS_H
-#define STD_TYPE_TRAITS_H
-
-#include "cstddef.h"
-
-namespace std {
-
-template <typename T, T V>
-struct integral_constant {
- static constexpr T value = V;
-};
-
-using true_type = integral_constant<bool, true>;
-using false_type = integral_constant<bool, false>;
-
-template< class T > struct remove_reference {typedef T type;};
-template< class T > struct remove_reference<T&> {typedef T type;};
-template< class T > struct remove_reference<T&&> {typedef T type;};
-
-template <class T>
- using remove_reference_t = typename remove_reference<T>::type;
-
-template <class T>
-struct remove_extent {
- typedef T type;
-};
-
-template <class T>
-struct remove_extent<T[]> {
- typedef T type;
-};
-
-template <class T, size_t N>
-struct remove_extent<T[N]> {
- typedef T type;
-};
-
-template <class T>
-struct is_array : false_type {};
-
-template <class T>
-struct is_array<T[]> : true_type {};
-
-template <class T, size_t N>
-struct is_array<T[N]> : true_type {};
-
-template <class>
-struct is_function : false_type {};
-
-template <class Ret, class... Args>
-struct is_function<Ret(Args...)> : true_type {};
-
-namespace detail {
-
-template <class T>
-struct type_identity {
- using type = T;
-}; // or use type_identity (since C++20)
-
-template <class T>
-auto try_add_pointer(int) -> type_identity<typename remove_reference<T>::type*>;
-template <class T>
-auto try_add_pointer(...) -> type_identity<T>;
-
-} // namespace detail
-
-template <class T>
-struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};
-
-template <bool B, class T, class F>
-struct conditional {
- typedef T type;
-};
-
-template <class T, class F>
-struct conditional<false, T, F> {
- typedef F type;
-};
-
-template <class T>
-struct remove_cv {
- typedef T type;
-};
-template <class T>
-struct remove_cv<const T> {
- typedef T type;
-};
-template <class T>
-struct remove_cv<volatile T> {
- typedef T type;
-};
-template <class T>
-struct remove_cv<const volatile T> {
- typedef T type;
-};
-
-template <class T>
-using remove_cv_t = typename remove_cv<T>::type;
-
-template <class T>
-struct decay {
- private:
- typedef typename remove_reference<T>::type U;
-
- public:
- typedef typename conditional<
- is_array<U>::value, typename remove_extent<U>::type*,
- typename conditional<is_function<U>::value, typename add_pointer<U>::type,
- typename remove_cv<U>::type>::type>::type type;
-};
-
-template <bool B, class T = void>
-struct enable_if {};
-
-template <class T>
-struct enable_if<true, T> {
- typedef T type;
-};
-
-template <bool B, class T = void>
-using enable_if_t = typename enable_if<B, T>::type;
-
-template <class T, class U>
-struct is_same : false_type {};
-
-template <class T>
-struct is_same<T, T> : true_type {};
-
-template <class T>
-struct is_void : is_same<void, typename remove_cv<T>::type> {};
-
-namespace detail {
-
-template <class T>
-auto try_add_lvalue_reference(int) -> type_identity<T&>;
-template <class T>
-auto try_add_lvalue_reference(...) -> type_identity<T>;
-
-template <class T>
-auto try_add_rvalue_reference(int) -> type_identity<T&&>;
-template <class T>
-auto try_add_rvalue_reference(...) -> type_identity<T>;
-
-} // namespace detail
-
-template <class T>
-struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference<T>(0)) {
-};
-
-template <class T>
-struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference<T>(0)) {
-};
-
-template <class T>
-typename add_rvalue_reference<T>::type declval() noexcept;
-
-namespace detail {
-
-template <class T>
-auto test_returnable(int)
- -> decltype(void(static_cast<T (*)()>(nullptr)), true_type{});
-template <class>
-auto test_returnable(...) -> false_type;
-
-template <class From, class To>
-auto test_implicitly_convertible(int)
- -> decltype(void(declval<void (&)(To)>()(declval<From>())), true_type{});
-template <class, class>
-auto test_implicitly_convertible(...) -> false_type;
-
-} // namespace detail
-
-template <class From, class To>
-struct is_convertible
- : integral_constant<bool,
- (decltype(detail::test_returnable<To>(0))::value &&
- decltype(detail::test_implicitly_convertible<From, To>(
- 0))::value) ||
- (is_void<From>::value && is_void<To>::value)> {};
-
-template <class From, class To>
-inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
-
-template <class...>
-using void_t = void;
-
-template <class, class T, class... Args>
-struct is_constructible_ : false_type {};
-
-template <class T, class... Args>
-struct is_constructible_<void_t<decltype(T(declval<Args>()...))>, T, Args...>
- : true_type {};
-
-template <class T, class... Args>
-using is_constructible = is_constructible_<void_t<>, T, Args...>;
-
-template <class T, class... Args>
-inline constexpr bool is_constructible_v = is_constructible<T, Args...>::value;
-
-template <class _Tp>
-struct __uncvref {
- typedef typename remove_cv<typename remove_reference<_Tp>::type>::type type;
-};
-
-template <class _Tp>
-using __uncvref_t = typename __uncvref<_Tp>::type;
-
-template <bool _Val>
-using _BoolConstant = integral_constant<bool, _Val>;
-
-template <class _Tp, class _Up>
-using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
-
-template <class _Tp, class _Up>
-using _IsNotSame = _BoolConstant<!__is_same(_Tp, _Up)>;
-
-template <bool>
-struct _MetaBase;
-template <>
-struct _MetaBase<true> {
- template <class _Tp, class _Up>
- using _SelectImpl = _Tp;
- template <template <class...> class _FirstFn, template <class...> class,
- class... _Args>
- using _SelectApplyImpl = _FirstFn<_Args...>;
- template <class _First, class...>
- using _FirstImpl = _First;
- template <class, class _Second, class...>
- using _SecondImpl = _Second;
- template <class _Result, class _First, class... _Rest>
- using _OrImpl =
- typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::
- template _OrImpl<_First, _Rest...>;
-};
-
-template <>
-struct _MetaBase<false> {
- template <class _Tp, class _Up>
- using _SelectImpl = _Up;
- template <template <class...> class, template <class...> class _SecondFn,
- class... _Args>
- using _SelectApplyImpl = _SecondFn<_Args...>;
- template <class _Result, class...>
- using _OrImpl = _Result;
-};
-
-template <bool _Cond, class _IfRes, class _ElseRes>
-using _If = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>;
-
-template <class... _Rest>
-using _Or = typename _MetaBase<sizeof...(_Rest) !=
- 0>::template _OrImpl<false_type, _Rest...>;
-
-template <bool _Bp, class _Tp = void>
-using __enable_if_t = typename enable_if<_Bp, _Tp>::type;
-
-template <class...>
-using __expand_to_true = true_type;
-template <class... _Pred>
-__expand_to_true<__enable_if_t<_Pred::value>...> __and_helper(int);
-template <class...>
-false_type __and_helper(...);
-template <class... _Pred>
-using _And = decltype(__and_helper<_Pred...>(0));
-
-template <class _Pred>
-struct _Not : _BoolConstant<!_Pred::value> {};
-
-struct __check_tuple_constructor_fail {
- static constexpr bool __enable_explicit_default() { return false; }
- static constexpr bool __enable_implicit_default() { return false; }
- template <class...>
- static constexpr bool __enable_explicit() {
- return false;
- }
- template <class...>
- static constexpr bool __enable_implicit() {
- return false;
- }
-};
-
-template <typename, typename _Tp>
-struct __select_2nd {
- typedef _Tp type;
-};
-template <class _Tp, class _Arg>
-typename __select_2nd<decltype((declval<_Tp>() = declval<_Arg>())),
- true_type>::type
-__is_assignable_test(int);
-template <class, class>
-false_type __is_assignable_test(...);
-template <class _Tp, class _Arg,
- bool = is_void<_Tp>::value || is_void<_Arg>::value>
-struct __is_assignable_imp
- : public decltype((__is_assignable_test<_Tp, _Arg>(0))) {};
-template <class _Tp, class _Arg>
-struct __is_assignable_imp<_Tp, _Arg, true> : public false_type {};
-template <class _Tp, class _Arg>
-struct is_assignable : public __is_assignable_imp<_Tp, _Arg> {};
-
-template <class _Tp>
-struct __libcpp_is_integral : public false_type {};
-template <>
-struct __libcpp_is_integral<bool> : public true_type {};
-template <>
-struct __libcpp_is_integral<char> : public true_type {};
-template <>
-struct __libcpp_is_integral<signed char> : public true_type {};
-template <>
-struct __libcpp_is_integral<unsigned char> : public true_type {};
-template <>
-struct __libcpp_is_integral<wchar_t> : public true_type {};
-template <>
-struct __libcpp_is_integral<short> : public true_type {}; // NOLINT
-template <>
-struct __libcpp_is_integral<unsigned short> : public true_type {}; // NOLINT
-template <>
-struct __libcpp_is_integral<int> : public true_type {};
-template <>
-struct __libcpp_is_integral<unsigned int> : public true_type {};
-template <>
-struct __libcpp_is_integral<long> : public true_type {}; // NOLINT
-template <>
-struct __libcpp_is_integral<unsigned long> : public true_type {}; // NOLINT
-template <>
-struct __libcpp_is_integral<long long> : public true_type {}; // NOLINT
-template <> // NOLINTNEXTLINE
-struct __libcpp_is_integral<unsigned long long> : public true_type {};
-template <class _Tp>
-struct is_integral
- : public __libcpp_is_integral<typename remove_cv<_Tp>::type> {};
-
-template <class _Tp>
-struct __libcpp_is_floating_point : public false_type {};
-template <>
-struct __libcpp_is_floating_point<float> : public true_type {};
-template <>
-struct __libcpp_is_floating_point<double> : public true_type {};
-template <>
-struct __libcpp_is_floating_point<long double> : public true_type {};
-template <class _Tp>
-struct is_floating_point
- : public __libcpp_is_floating_point<typename remove_cv<_Tp>::type> {};
-
-template <class _Tp>
-struct is_arithmetic
- : public integral_constant<bool, is_integral<_Tp>::value ||
- is_floating_point<_Tp>::value> {};
-
-template <class _Tp>
-struct __libcpp_is_pointer : public false_type {};
-template <class _Tp>
-struct __libcpp_is_pointer<_Tp*> : public true_type {};
-template <class _Tp>
-struct is_pointer : public __libcpp_is_pointer<typename remove_cv<_Tp>::type> {
-};
-
-template <class _Tp>
-struct __libcpp_is_member_pointer : public false_type {};
-template <class _Tp, class _Up>
-struct __libcpp_is_member_pointer<_Tp _Up::*> : public true_type {};
-template <class _Tp>
-struct is_member_pointer
- : public __libcpp_is_member_pointer<typename remove_cv<_Tp>::type> {};
-
-template <class _Tp>
-struct __libcpp_union : public false_type {};
-template <class _Tp>
-struct is_union : public __libcpp_union<typename remove_cv<_Tp>::type> {};
-
-template <class T>
-struct is_reference : false_type {};
-template <class T>
-struct is_reference<T&> : true_type {};
-template <class T>
-struct is_reference<T&&> : true_type {};
-
-template <class T>
-inline constexpr bool is_reference_v = is_reference<T>::value;
-
-struct __two {
- char __lx[2];
-};
-
-namespace __is_class_imp {
-template <class _Tp>
-char __test(int _Tp::*);
-template <class _Tp>
-__two __test(...);
-} // namespace __is_class_imp
-template <class _Tp>
-struct is_class
- : public integral_constant<bool,
- sizeof(__is_class_imp::__test<_Tp>(0)) == 1 &&
- !is_union<_Tp>::value> {};
-
-template <class _Tp>
-struct __is_nullptr_t_impl : public false_type {};
-template <>
-struct __is_nullptr_t_impl<nullptr_t> : public true_type {};
-template <class _Tp>
-struct __is_nullptr_t
- : public __is_nullptr_t_impl<typename remove_cv<_Tp>::type> {};
-template <class _Tp>
-struct is_null_pointer
- : public __is_nullptr_t_impl<typename remove_cv<_Tp>::type> {};
-
-template <class _Tp>
-struct is_enum
- : public integral_constant<
- bool, !is_void<_Tp>::value && !is_integral<_Tp>::value &&
- !is_floating_point<_Tp>::value && !is_array<_Tp>::value &&
- !is_pointer<_Tp>::value && !is_reference<_Tp>::value &&
- !is_member_pointer<_Tp>::value && !is_union<_Tp>::value &&
- !is_class<_Tp>::value && !is_function<_Tp>::value> {};
-
-template <class _Tp>
-struct is_scalar
- : public integral_constant<
- bool, is_arithmetic<_Tp>::value || is_member_pointer<_Tp>::value ||
- is_pointer<_Tp>::value || __is_nullptr_t<_Tp>::value ||
- is_enum<_Tp>::value> {};
-template <>
-struct is_scalar<nullptr_t> : public true_type {};
-
-} // namespace std
-
-#endif // STD_TYPE_TRAITS_H
-)";
-
-static constexpr char AbslTypeTraitsHeader[] = R"(
-#ifndef ABSL_TYPE_TRAITS_H
-#define ABSL_TYPE_TRAITS_H
-
-#include "std_type_traits.h"
-
-namespace absl {
-
-template <typename... Ts>
-struct conjunction : std::true_type {};
-
-template <typename T, typename... Ts>
-struct conjunction<T, Ts...>
- : std::conditional<T::value, conjunction<Ts...>, T>::type {};
-
-template <typename T>
-struct conjunction<T> : T {};
-
-template <typename T>
-struct negation : std::integral_constant<bool, !T::value> {};
-
-template <bool B, typename T = void>
-using enable_if_t = typename std::enable_if<B, T>::type;
-
-} // namespace absl
-
-#endif // ABSL_TYPE_TRAITS_H
-)";
-
-static constexpr char StdStringHeader[] = R"(
-#ifndef STRING_H
-#define STRING_H
-
-namespace std {
-
-struct string {
- string(const char*);
- ~string();
- bool empty();
-};
-bool operator!=(const string &LHS, const char *RHS);
-
-} // namespace std
-
-#endif // STRING_H
-)";
-
-static constexpr char StdUtilityHeader[] = R"(
-#ifndef UTILITY_H
-#define UTILITY_H
-
-#include "std_type_traits.h"
-
-namespace std {
-
-template <typename T>
-constexpr remove_reference_t<T>&& move(T&& x);
-
-template <typename T>
-void swap(T& a, T& b) noexcept;
-
-} // namespace std
-
-#endif // UTILITY_H
-)";
-
-static constexpr char StdInitializerListHeader[] = R"(
-#ifndef INITIALIZER_LIST_H
-#define INITIALIZER_LIST_H
-
-namespace std {
-
-template <typename T>
-class initializer_list {
- public:
- const T *a, *b;
- initializer_list() noexcept;
-};
-
-} // namespace std
-
-#endif // INITIALIZER_LIST_H
-)";
-
-static constexpr char StdOptionalHeader[] = R"(
-#include "std_initializer_list.h"
-#include "std_type_traits.h"
-#include "std_utility.h"
-
-namespace std {
-
-struct in_place_t {};
-constexpr in_place_t in_place;
-
-struct nullopt_t {
- constexpr explicit nullopt_t() {}
-};
-constexpr nullopt_t nullopt;
-
-template <class _Tp>
-struct __optional_destruct_base {
- constexpr void reset() noexcept;
-};
-
-template <class _Tp>
-struct __optional_storage_base : __optional_destruct_base<_Tp> {
- constexpr bool has_value() const noexcept;
-};
-
-template <typename _Tp>
-class optional : private __optional_storage_base<_Tp> {
- using __base = __optional_storage_base<_Tp>;
-
- public:
- using value_type = _Tp;
-
- private:
- struct _CheckOptionalArgsConstructor {
- template <class _Up>
- static constexpr bool __enable_implicit() {
- return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>;
- }
-
- template <class _Up>
- static constexpr bool __enable_explicit() {
- return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>;
- }
- };
- template <class _Up>
- using _CheckOptionalArgsCtor =
- _If<_IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
- _IsNotSame<__uncvref_t<_Up>, optional>::value,
- _CheckOptionalArgsConstructor, __check_tuple_constructor_fail>;
- template <class _QualUp>
- struct _CheckOptionalLikeConstructor {
- template <class _Up, class _Opt = optional<_Up>>
- using __check_constructible_from_opt =
- _Or<is_constructible<_Tp, _Opt&>, is_constructible<_Tp, _Opt const&>,
- is_constructible<_Tp, _Opt&&>, is_constructible<_Tp, _Opt const&&>,
- is_convertible<_Opt&, _Tp>, is_convertible<_Opt const&, _Tp>,
- is_convertible<_Opt&&, _Tp>, is_convertible<_Opt const&&, _Tp>>;
- template <class _Up, class _QUp = _QualUp>
- static constexpr bool __enable_implicit() {
- return is_convertible<_QUp, _Tp>::value &&
- !__check_constructible_from_opt<_Up>::value;
- }
- template <class _Up, class _QUp = _QualUp>
- static constexpr bool __enable_explicit() {
- return !is_convertible<_QUp, _Tp>::value &&
- !__check_constructible_from_opt<_Up>::value;
- }
- };
-
- template <class _Up, class _QualUp>
- using _CheckOptionalLikeCtor =
- _If<_And<_IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>>::value,
- _CheckOptionalLikeConstructor<_QualUp>,
- __check_tuple_constructor_fail>;
-
-
- template <class _Up, class _QualUp>
- using _CheckOptionalLikeAssign = _If<
- _And<
- _IsNotSame<_Up, _Tp>,
- is_constructible<_Tp, _QualUp>,
- is_assignable<_Tp&, _QualUp>
- >::value,
- _CheckOptionalLikeConstructor<_QualUp>,
- __check_tuple_constructor_fail
- >;
-
- public:
- constexpr optional() noexcept {}
- constexpr optional(const optional&) = default;
- constexpr optional(optional&&) = default;
- constexpr optional(nullopt_t) noexcept {}
-
- template <
- class _InPlaceT, class... _Args,
- class = enable_if_t<_And<_IsSame<_InPlaceT, in_place_t>,
- is_constructible<value_type, _Args...>>::value>>
- constexpr explicit optional(_InPlaceT, _Args&&... __args);
-
- template <class _Up, class... _Args,
- class = enable_if_t<is_constructible_v<
- value_type, initializer_list<_Up>&, _Args...>>>
- constexpr explicit optional(in_place_t, initializer_list<_Up> __il,
- _Args&&... __args);
-
- template <
- class _Up = value_type,
- enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(),
- int> = 0>
- constexpr optional(_Up&& __v);
-
- template <
- class _Up,
- enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(),
- int> = 0>
- constexpr explicit optional(_Up&& __v);
-
- template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::
- template __enable_implicit<_Up>(),
- int> = 0>
- constexpr optional(const optional<_Up>& __v);
-
- template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::
- template __enable_explicit<_Up>(),
- int> = 0>
- constexpr explicit optional(const optional<_Up>& __v);
-
- template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::
- template __enable_implicit<_Up>(),
- int> = 0>
- constexpr optional(optional<_Up>&& __v);
-
- template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::
- template __enable_explicit<_Up>(),
- int> = 0>
- constexpr explicit optional(optional<_Up>&& __v);
-
- constexpr optional& operator=(nullopt_t) noexcept;
-
- optional& operator=(const optional&);
-
- optional& operator=(optional&&);
-
- template <class _Up = value_type,
- class = enable_if_t<_And<_IsNotSame<__uncvref_t<_Up>, optional>,
- _Or<_IsNotSame<__uncvref_t<_Up>, value_type>,
- _Not<is_scalar<value_type>>>,
- is_constructible<value_type, _Up>,
- is_assignable<value_type&, _Up>>::value>>
- constexpr optional& operator=(_Up&& __v);
-
- template <class _Up, enable_if_t<_CheckOptionalLikeAssign<_Up, _Up const&>::
- template __enable_assign<_Up>(),
- int> = 0>
- constexpr optional& operator=(const optional<_Up>& __v);
-
- template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::
- template __enable_assign<_Up>(),
- int> = 0>
- constexpr optional& operator=(optional<_Up>&& __v);
-
- const _Tp& operator*() const&;
- _Tp& operator*() &;
- const _Tp&& operator*() const&&;
- _Tp&& operator*() &&;
-
- const _Tp* operator->() const;
- _Tp* operator->();
-
- const _Tp& value() const&;
- _Tp& value() &;
- const _Tp&& value() const&&;
- _Tp&& value() &&;
-
- template <typename U>
- constexpr _Tp value_or(U&& v) const&;
- template <typename U>
- _Tp value_or(U&& v) &&;
-
- template <typename... Args>
- _Tp& emplace(Args&&... args);
-
- template <typename U, typename... Args>
- _Tp& emplace(std::initializer_list<U> ilist, Args&&... args);
-
- using __base::reset;
-
- constexpr explicit operator bool() const noexcept;
- using __base::has_value;
-
- constexpr void swap(optional& __opt) noexcept;
-};
-
-template <typename T>
-constexpr optional<typename std::decay<T>::type> make_optional(T&& v);
-
-template <typename T, typename... Args>
-constexpr optional<T> make_optional(Args&&... args);
-
-template <typename T, typename U, typename... Args>
-constexpr optional<T> make_optional(std::initializer_list<U> il,
- Args&&... args);
-
-template <typename T, typename U>
-constexpr bool operator==(const optional<T> &lhs, const optional<U> &rhs);
-template <typename T, typename U>
-constexpr bool operator!=(const optional<T> &lhs, const optional<U> &rhs);
-
-template <typename T>
-constexpr bool operator==(const optional<T> &opt, nullopt_t);
-
-// C++20 and later do not define the following overloads because they are
-// provided by rewritten candidates instead.
-#if __cplusplus < 202002L
-template <typename T>
-constexpr bool operator==(nullopt_t, const optional<T> &opt);
-template <typename T>
-constexpr bool operator!=(const optional<T> &opt, nullopt_t);
-template <typename T>
-constexpr bool operator!=(nullopt_t, const optional<T> &opt);
-#endif // __cplusplus < 202002L
-
-template <typename T, typename U>
-constexpr bool operator==(const optional<T> &opt, const U &value);
-template <typename T, typename U>
-constexpr bool operator==(const T &value, const optional<U> &opt);
-template <typename T, typename U>
-constexpr bool operator!=(const optional<T> &opt, const U &value);
-template <typename T, typename U>
-constexpr bool operator!=(const T &value, const optional<U> &opt);
-
-} // namespace std
-)";
-
-static constexpr char AbslOptionalHeader[] = R"(
-#include "absl_type_traits.h"
-#include "std_initializer_list.h"
-#include "std_type_traits.h"
-#include "std_utility.h"
-
-namespace absl {
-
-struct nullopt_t {
- constexpr explicit nullopt_t() {}
-};
-constexpr nullopt_t nullopt;
-
-struct in_place_t {};
-constexpr in_place_t in_place;
-
-template <typename T>
-class optional;
-
-namespace optional_internal {
-
-template <typename T, typename U>
-struct is_constructible_convertible_from_optional
- : std::integral_constant<
- bool, std::is_constructible<T, optional<U>&>::value ||
- std::is_constructible<T, optional<U>&&>::value ||
- std::is_constructible<T, const optional<U>&>::value ||
- std::is_constructible<T, const optional<U>&&>::value ||
- std::is_convertible<optional<U>&, T>::value ||
- std::is_convertible<optional<U>&&, T>::value ||
- std::is_convertible<const optional<U>&, T>::value ||
- std::is_convertible<const optional<U>&&, T>::value> {};
-
-template <typename T, typename U>
-struct is_constructible_convertible_assignable_from_optional
- : std::integral_constant<
- bool, is_constructible_convertible_from_optional<T, U>::value ||
- std::is_assignable<T&, optional<U>&>::value ||
- std::is_assignable<T&, optional<U>&&>::value ||
- std::is_assignable<T&, const optional<U>&>::value ||
- std::is_assignable<T&, const optional<U>&&>::value> {};
-
-} // namespace optional_internal
-
-template <typename T>
-class optional {
- public:
- constexpr optional() noexcept;
-
- constexpr optional(nullopt_t) noexcept;
-
- optional(const optional&) = default;
-
- optional(optional&&) = default;
-
- template <typename InPlaceT, typename... Args,
- absl::enable_if_t<absl::conjunction<
- std::is_same<InPlaceT, in_place_t>,
- std::is_constructible<T, Args&&...>>::value>* = nullptr>
- constexpr explicit optional(InPlaceT, Args&&... args);
-
- template <typename U, typename... Args,
- typename = typename std::enable_if<std::is_constructible<
- T, std::initializer_list<U>&, Args&&...>::value>::type>
- constexpr explicit optional(in_place_t, std::initializer_list<U> il,
- Args&&... args);
-
- template <
- typename U = T,
- typename std::enable_if<
- absl::conjunction<absl::negation<std::is_same<
- in_place_t, typename std::decay<U>::type>>,
- absl::negation<std::is_same<
- optional<T>, typename std::decay<U>::type>>,
- std::is_convertible<U&&, T>,
- std::is_constructible<T, U&&>>::value,
- bool>::type = false>
- constexpr optional(U&& v);
-
- template <
- typename U = T,
- typename std::enable_if<
- absl::conjunction<absl::negation<std::is_same<
- in_place_t, typename std::decay<U>::type>>,
- absl::negation<std::is_same<
- optional<T>, typename std::decay<U>::type>>,
- absl::negation<std::is_convertible<U&&, T>>,
- std::is_constructible<T, U&&>>::value,
- bool>::type = false>
- explicit constexpr optional(U&& v);
-
- template <typename U,
- typename std::enable_if<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>,
- std::is_constructible<T, const U&>,
- absl::negation<
- optional_internal::
- is_constructible_convertible_from_optional<T, U>>,
- std::is_convertible<const U&, T>>::value,
- bool>::type = false>
- optional(const optional<U>& rhs);
-
- template <typename U,
- typename std::enable_if<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>,
- std::is_constructible<T, const U&>,
- absl::negation<
- optional_internal::
- is_constructible_convertible_from_optional<T, U>>,
- absl::negation<std::is_convertible<const U&, T>>>::value,
- bool>::type = false>
- explicit optional(const optional<U>& rhs);
-
- template <
- typename U,
- typename std::enable_if<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
- absl::negation<
- optional_internal::is_constructible_convertible_from_optional<
- T, U>>,
- std::is_convertible<U&&, T>>::value,
- bool>::type = false>
- optional(optional<U>&& rhs);
-
- template <
- typename U,
- typename std::enable_if<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
- absl::negation<
- optional_internal::is_constructible_convertible_from_optional<
- T, U>>,
- absl::negation<std::is_convertible<U&&, T>>>::value,
- bool>::type = false>
- explicit optional(optional<U>&& rhs);
-
- optional& operator=(nullopt_t) noexcept;
-
- optional& operator=(const optional& src);
-
- optional& operator=(optional&& src);
-
- template <
- typename U = T,
- typename = typename std::enable_if<absl::conjunction<
- absl::negation<
- std::is_same<optional<T>, typename std::decay<U>::type>>,
- absl::negation<
- absl::conjunction<std::is_scalar<T>,
- std::is_same<T, typename std::decay<U>::type>>>,
- std::is_constructible<T, U>, std::is_assignable<T&, U>>::value>::type>
- optional& operator=(U&& v);
-
- template <
- typename U,
- typename = typename std::enable_if<absl::conjunction<
- absl::negation<std::is_same<T, U>>,
- std::is_constructible<T, const U&>, std::is_assignable<T&, const U&>,
- absl::negation<
- optional_internal::
- is_constructible_convertible_assignable_from_optional<
- T, U>>>::value>::type>
- optional& operator=(const optional<U>& rhs);
-
- template <typename U,
- typename = typename std::enable_if<absl::conjunction<
- absl::negation<std::is_same<T, U>>, std::is_constructible<T, U>,
- std::is_assignable<T&, U>,
- absl::negation<
- optional_internal::
- is_constructible_convertible_assignable_from_optional<
- T, U>>>::value>::type>
- optional& operator=(optional<U>&& rhs);
-
- const T& operator*() const&;
- T& operator*() &;
- const T&& operator*() const&&;
- T&& operator*() &&;
-
- const T* operator->() const;
- T* operator->();
-
- const T& value() const&;
- T& value() &;
- const T&& value() const&&;
- T&& value() &&;
-
- template <typename U>
- constexpr T value_or(U&& v) const&;
- template <typename U>
- T value_or(U&& v) &&;
-
- template <typename... Args>
- T& emplace(Args&&... args);
-
- template <typename U, typename... Args>
- T& emplace(std::initializer_list<U> ilist, Args&&... args);
-
- void reset() noexcept;
-
- constexpr explicit operator bool() const noexcept;
- constexpr bool has_value() const noexcept;
-
- void swap(optional& rhs) noexcept;
-};
-
-template <typename T>
-constexpr optional<typename std::decay<T>::type> make_optional(T&& v);
-
-template <typename T, typename... Args>
-constexpr optional<T> make_optional(Args&&... args);
-
-template <typename T, typename U, typename... Args>
-constexpr optional<T> make_optional(std::initializer_list<U> il,
- Args&&... args);
-
-template <typename T, typename U>
-constexpr bool operator==(const optional<T> &lhs, const optional<U> &rhs);
-template <typename T, typename U>
-constexpr bool operator!=(const optional<T> &lhs, const optional<U> &rhs);
-
-template <typename T>
-constexpr bool operator==(const optional<T> &opt, nullopt_t);
-template <typename T>
-constexpr bool operator==(nullopt_t, const optional<T> &opt);
-template <typename T>
-constexpr bool operator!=(const optional<T> &opt, nullopt_t);
-template <typename T>
-constexpr bool operator!=(nullopt_t, const optional<T> &opt);
-
-template <typename T, typename U>
-constexpr bool operator==(const optional<T> &opt, const U &value);
-template <typename T, typename U>
-constexpr bool operator==(const T &value, const optional<U> &opt);
-template <typename T, typename U>
-constexpr bool operator!=(const optional<T> &opt, const U &value);
-template <typename T, typename U>
-constexpr bool operator!=(const T &value, const optional<U> &opt);
-
-} // namespace absl
-)";
-
-static constexpr char BaseOptionalHeader[] = R"(
-#include "std_initializer_list.h"
-#include "std_type_traits.h"
-#include "std_utility.h"
-
-namespace base {
-
-struct in_place_t {};
-constexpr in_place_t in_place;
-
-struct nullopt_t {
- constexpr explicit nullopt_t() {}
-};
-constexpr nullopt_t nullopt;
-
-template <typename T>
-class Optional;
-
-namespace internal {
-
-template <typename T>
-using RemoveCvRefT = std::remove_cv_t<std::remove_reference_t<T>>;
-
-template <typename T, typename U>
-struct IsConvertibleFromOptional
- : std::integral_constant<
- bool, std::is_constructible<T, Optional<U>&>::value ||
- std::is_constructible<T, const Optional<U>&>::value ||
- std::is_constructible<T, Optional<U>&&>::value ||
- std::is_constructible<T, const Optional<U>&&>::value ||
- std::is_convertible<Optional<U>&, T>::value ||
- std::is_convertible<const Optional<U>&, T>::value ||
- std::is_convertible<Optional<U>&&, T>::value ||
- std::is_convertible<const Optional<U>&&, T>::value> {};
-
-template <typename T, typename U>
-struct IsAssignableFromOptional
- : std::integral_constant<
- bool, IsConvertibleFromOptional<T, U>::value ||
- std::is_assignable<T&, Optional<U>&>::value ||
- std::is_assignable<T&, const Optional<U>&>::value ||
- std::is_assignable<T&, Optional<U>&&>::value ||
- std::is_assignable<T&, const Optional<U>&&>::value> {};
-
-} // namespace internal
-
-template <typename T>
-class Optional {
- public:
- using value_type = T;
-
- constexpr Optional() = default;
- constexpr Optional(const Optional& other) noexcept = default;
- constexpr Optional(Optional&& other) noexcept = default;
-
- constexpr Optional(nullopt_t);
-
- template <typename U,
- typename std::enable_if<
- std::is_constructible<T, const U&>::value &&
- !internal::IsConvertibleFromOptional<T, U>::value &&
- std::is_convertible<const U&, T>::value,
- bool>::type = false>
- Optional(const Optional<U>& other) noexcept;
-
- template <typename U,
- typename std::enable_if<
- std::is_constructible<T, const U&>::value &&
- !internal::IsConvertibleFromOptional<T, U>::value &&
- !std::is_convertible<const U&, T>::value,
- bool>::type = false>
- explicit Optional(const Optional<U>& other) noexcept;
-
- template <typename U,
- typename std::enable_if<
- std::is_constructible<T, U&&>::value &&
- !internal::IsConvertibleFromOptional<T, U>::value &&
- std::is_convertible<U&&, T>::value,
- bool>::type = false>
- Optional(Optional<U>&& other) noexcept;
-
- template <typename U,
- typename std::enable_if<
- std::is_constructible<T, U&&>::value &&
- !internal::IsConvertibleFromOptional<T, U>::value &&
- !std::is_convertible<U&&, T>::value,
- bool>::type = false>
- explicit Optional(Optional<U>&& other) noexcept;
-
- template <class... Args>
- constexpr explicit Optional(in_place_t, Args&&... args);
-
- template <class U, class... Args,
- class = typename std::enable_if<std::is_constructible<
- value_type, std::initializer_list<U>&, Args...>::value>::type>
- constexpr explicit Optional(in_place_t, std::initializer_list<U> il,
- Args&&... args);
-
- template <
- typename U = value_type,
- typename std::enable_if<
- std::is_constructible<T, U&&>::value &&
- !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
- !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
- std::is_convertible<U&&, T>::value,
- bool>::type = false>
- constexpr Optional(U&& value);
-
- template <
- typename U = value_type,
- typename std::enable_if<
- std::is_constructible<T, U&&>::value &&
- !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
- !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
- !std::is_convertible<U&&, T>::value,
- bool>::type = false>
- constexpr explicit Optional(U&& value);
-
- Optional& operator=(const Optional& other) noexcept;
-
- Optional& operator=(Optional&& other) noexcept;
-
- Optional& operator=(nullopt_t);
-
- template <typename U>
- typename std::enable_if<
- !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
- std::is_constructible<T, U>::value &&
- std::is_assignable<T&, U>::value &&
- (!std::is_scalar<T>::value ||
- !std::is_same<typename std::decay<U>::type, T>::value),
- Optional&>::type
- operator=(U&& value) noexcept;
-
- template <typename U>
- typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
- std::is_constructible<T, const U&>::value &&
- std::is_assignable<T&, const U&>::value,
- Optional&>::type
- operator=(const Optional<U>& other) noexcept;
-
- template <typename U>
- typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
- std::is_constructible<T, U>::value &&
- std::is_assignable<T&, U>::value,
- Optional&>::type
- operator=(Optional<U>&& other) noexcept;
-
- const T& operator*() const&;
- T& operator*() &;
- const T&& operator*() const&&;
- T&& operator*() &&;
-
- const T* operator->() const;
- T* operator->();
-
- const T& value() const&;
- T& value() &;
- const T&& value() const&&;
- T&& value() &&;
-
- template <typename U>
- constexpr T value_or(U&& v) const&;
- template <typename U>
- T value_or(U&& v) &&;
-
- template <typename... Args>
- T& emplace(Args&&... args);
-
- template <typename U, typename... Args>
- T& emplace(std::initializer_list<U> ilist, Args&&... args);
-
- void reset() noexcept;
-
- constexpr explicit operator bool() const noexcept;
- constexpr bool has_value() const noexcept;
-
- void swap(Optional& other);
-};
-
-template <typename T>
-constexpr Optional<typename std::decay<T>::type> make_optional(T&& v);
-
-template <typename T, typename... Args>
-constexpr Optional<T> make_optional(Args&&... args);
-
-template <typename T, typename U, typename... Args>
-constexpr Optional<T> make_optional(std::initializer_list<U> il,
- Args&&... args);
-
-template <typename T, typename U>
-constexpr bool operator==(const Optional<T> &lhs, const Optional<U> &rhs);
-template <typename T, typename U>
-constexpr bool operator!=(const Optional<T> &lhs, const Optional<U> &rhs);
-
-template <typename T>
-constexpr bool operator==(const Optional<T> &opt, nullopt_t);
-template <typename T>
-constexpr bool operator==(nullopt_t, const Optional<T> &opt);
-template <typename T>
-constexpr bool operator!=(const Optional<T> &opt, nullopt_t);
-template <typename T>
-constexpr bool operator!=(nullopt_t, const Optional<T> &opt);
-
-template <typename T, typename U>
-constexpr bool operator==(const Optional<T> &opt, const U &value);
-template <typename T, typename U>
-constexpr bool operator==(const T &value, const Optional<U> &opt);
-template <typename T, typename U>
-constexpr bool operator!=(const Optional<T> &opt, const U &value);
-template <typename T, typename U>
-constexpr bool operator!=(const T &value, const Optional<U> &opt);
-
-} // namespace base
-)";
-
/// Replaces all occurrences of `Pattern` in `S` with `Replacement`.
static void ReplaceAllOccurrences(std::string &S, const std::string &Pattern,
const std::string &Replacement) {
@@ -1323,16 +98,7 @@ protected:
ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
- std::vector<std::pair<std::string, std::string>> Headers;
- Headers.emplace_back("cstddef.h", CSDtdDefHeader);
- Headers.emplace_back("std_initializer_list.h", StdInitializerListHeader);
- Headers.emplace_back("std_string.h", StdStringHeader);
- Headers.emplace_back("std_type_traits.h", StdTypeTraitsHeader);
- Headers.emplace_back("std_utility.h", StdUtilityHeader);
- Headers.emplace_back("std_optional.h", StdOptionalHeader);
- Headers.emplace_back("absl_type_traits.h", AbslTypeTraitsHeader);
- Headers.emplace_back("absl_optional.h", AbslOptionalHeader);
- Headers.emplace_back("base_optional.h", BaseOptionalHeader);
+ auto Headers = getMockHeaders();
Headers.emplace_back("unchecked_optional_access_test.h", R"(
#include "absl_optional.h"
#include "base_optional.h"
diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
index 169b2d2..0c05184 100644
--- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp
+++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Testing/TestAST.h"
@@ -63,7 +63,7 @@ public:
Analysis = std::make_unique<LifetimeSafetyAnalysis>(*AnalysisCtx, nullptr);
Analysis->run();
- AnnotationToPointMap = Analysis->getTestPoints();
+ AnnotationToPointMap = Analysis->getFactManager().getTestPoints();
}
LifetimeSafetyAnalysis &getAnalysis() { return *Analysis; }
@@ -98,10 +98,11 @@ public:
auto *VD = findDecl<ValueDecl>(VarName);
if (!VD)
return std::nullopt;
- auto OID = Analysis.getOriginIDForDecl(VD);
- if (!OID)
- ADD_FAILURE() << "Origin for '" << VarName << "' not found.";
- return OID;
+ // This assumes the OriginManager's `get` can find an existing origin.
+ // We might need a `find` method on OriginManager to avoid `getOrCreate`
+ // logic in a const-query context if that becomes an issue.
+ return const_cast<OriginManager &>(Analysis.getFactManager().getOriginMgr())
+ .get(*VD);
}
std::vector<LoanID> getLoansForVar(llvm::StringRef VarName) {
@@ -110,7 +111,10 @@ public:
ADD_FAILURE() << "Failed to find VarDecl for '" << VarName << "'";
return {};
}
- std::vector<LoanID> LID = Analysis.getLoanIDForVar(VD);
+ std::vector<LoanID> LID;
+ for (const Loan &L : Analysis.getFactManager().getLoanMgr().getLoans())
+ if (L.Path.D == VD)
+ LID.push_back(L.ID);
if (LID.empty()) {
ADD_FAILURE() << "Loan for '" << VarName << "' not found.";
return {};
@@ -123,7 +127,7 @@ public:
ProgramPoint PP = Runner.getProgramPoint(Annotation);
if (!PP)
return std::nullopt;
- return Analysis.getLoansAtPoint(OID, PP);
+ return Analysis.getLoanPropagation().getLoans(OID, PP);
}
std::optional<std::vector<std::pair<OriginID, LivenessKind>>>
@@ -131,7 +135,10 @@ public:
ProgramPoint PP = Runner.getProgramPoint(Annotation);
if (!PP)
return std::nullopt;
- return Analysis.getLiveOriginsAtPoint(PP);
+ std::vector<std::pair<OriginID, LivenessKind>> Result;
+ for (auto &[OID, Info] : Analysis.getLiveOrigins().getLiveOriginsAt(PP))
+ Result.push_back({OID, Info.Kind});
+ return Result;
}
private: