/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/ADT/Any.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- Any.h - Generic type erased holder of any type -----------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file provides Any, a non-template class modeled in the spirit of |
10 | | // std::any. The idea is to provide a type-safe replacement for C's void*. |
11 | | // It can hold a value of any copy-constructible copy-assignable type |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #ifndef LLVM_ADT_ANY_H |
16 | | #define LLVM_ADT_ANY_H |
17 | | |
18 | | #include "llvm/ADT/STLExtras.h" |
19 | | |
20 | | #include <cassert> |
21 | | #include <memory> |
22 | | #include <type_traits> |
23 | | |
24 | | namespace llvm { |
25 | | |
26 | | class Any { |
27 | | template <typename T> struct TypeId { static const char Id; }; |
28 | | |
29 | | struct StorageBase { |
30 | 4.96k | virtual ~StorageBase() = default; |
31 | | virtual std::unique_ptr<StorageBase> clone() const = 0; |
32 | | virtual const void *id() const = 0; |
33 | | }; |
34 | | |
35 | | template <typename T> struct StorageImpl : public StorageBase { |
36 | 2.54k | explicit StorageImpl(const T &Value) : Value(Value) {} llvm::Any::StorageImpl<llvm::Function const*>::StorageImpl(llvm::Function const* const&) Line | Count | Source | 36 | 1.13k | explicit StorageImpl(const T &Value) : Value(Value) {} |
llvm::Any::StorageImpl<llvm::LazyCallGraph::SCC const*>::StorageImpl(llvm::LazyCallGraph::SCC const* const&) Line | Count | Source | 36 | 212 | explicit StorageImpl(const T &Value) : Value(Value) {} |
llvm::Any::StorageImpl<llvm::Module const*>::StorageImpl(llvm::Module const* const&) Line | Count | Source | 36 | 1.07k | explicit StorageImpl(const T &Value) : Value(Value) {} |
llvm::Any::StorageImpl<llvm::Loop const*>::StorageImpl(llvm::Loop const* const&) Line | Count | Source | 36 | 128 | explicit StorageImpl(const T &Value) : Value(Value) {} |
Unexecuted instantiation: llvm::Any::StorageImpl<polly::Scop const*>::StorageImpl(polly::Scop const* const&) |
37 | | |
38 | 2.39k | explicit StorageImpl(T &&Value) : Value(std::move(Value)) {} llvm::Any::StorageImpl<llvm::Function const*>::StorageImpl(llvm::Function const*&&) Line | Count | Source | 38 | 1.64k | explicit StorageImpl(T &&Value) : Value(std::move(Value)) {} |
llvm::Any::StorageImpl<llvm::LazyCallGraph::SCC const*>::StorageImpl(llvm::LazyCallGraph::SCC const*&&) Line | Count | Source | 38 | 151 | explicit StorageImpl(T &&Value) : Value(std::move(Value)) {} |
llvm::Any::StorageImpl<llvm::Module const*>::StorageImpl(llvm::Module const*&&) Line | Count | Source | 38 | 413 | explicit StorageImpl(T &&Value) : Value(std::move(Value)) {} |
llvm::Any::StorageImpl<llvm::Loop const*>::StorageImpl(llvm::Loop const*&&) Line | Count | Source | 38 | 183 | explicit StorageImpl(T &&Value) : Value(std::move(Value)) {} |
Unexecuted instantiation: llvm::Any::StorageImpl<polly::Scop const*>::StorageImpl(polly::Scop const*&&) |
39 | | |
40 | 2.54k | std::unique_ptr<StorageBase> clone() const override { |
41 | 2.54k | return llvm::make_unique<StorageImpl<T>>(Value); |
42 | 2.54k | } llvm::Any::StorageImpl<llvm::Function const*>::clone() const Line | Count | Source | 40 | 1.13k | std::unique_ptr<StorageBase> clone() const override { | 41 | 1.13k | return llvm::make_unique<StorageImpl<T>>(Value); | 42 | 1.13k | } |
llvm::Any::StorageImpl<llvm::Module const*>::clone() const Line | Count | Source | 40 | 1.07k | std::unique_ptr<StorageBase> clone() const override { | 41 | 1.07k | return llvm::make_unique<StorageImpl<T>>(Value); | 42 | 1.07k | } |
llvm::Any::StorageImpl<llvm::LazyCallGraph::SCC const*>::clone() const Line | Count | Source | 40 | 212 | std::unique_ptr<StorageBase> clone() const override { | 41 | 212 | return llvm::make_unique<StorageImpl<T>>(Value); | 42 | 212 | } |
llvm::Any::StorageImpl<llvm::Loop const*>::clone() const Line | Count | Source | 40 | 128 | std::unique_ptr<StorageBase> clone() const override { | 41 | 128 | return llvm::make_unique<StorageImpl<T>>(Value); | 42 | 128 | } |
Unexecuted instantiation: llvm::Any::StorageImpl<polly::Scop const*>::clone() const |
43 | | |
44 | 2.65k | const void *id() const override { return &TypeId<T>::Id; } llvm::Any::StorageImpl<llvm::Function const*>::id() const Line | Count | Source | 44 | 1.30k | const void *id() const override { return &TypeId<T>::Id; } |
llvm::Any::StorageImpl<llvm::Module const*>::id() const Line | Count | Source | 44 | 888 | const void *id() const override { return &TypeId<T>::Id; } |
llvm::Any::StorageImpl<llvm::LazyCallGraph::SCC const*>::id() const Line | Count | Source | 44 | 306 | const void *id() const override { return &TypeId<T>::Id; } |
llvm::Any::StorageImpl<llvm::Loop const*>::id() const Line | Count | Source | 44 | 154 | const void *id() const override { return &TypeId<T>::Id; } |
Unexecuted instantiation: llvm::Any::StorageImpl<polly::Scop const*>::id() const |
45 | | |
46 | | T Value; |
47 | | |
48 | | private: |
49 | | StorageImpl &operator=(const StorageImpl &Other) = delete; |
50 | | StorageImpl(const StorageImpl &Other) = delete; |
51 | | }; |
52 | | |
53 | | public: |
54 | | Any() = default; |
55 | | |
56 | | Any(const Any &Other) |
57 | 2.55k | : Storage(Other.Storage ? Other.Storage->clone() : nullptr) {} |
58 | | |
59 | | // When T is Any or T is not copy-constructible we need to explicitly disable |
60 | | // the forwarding constructor so that the copy constructor gets selected |
61 | | // instead. |
62 | | template < |
63 | | typename T, |
64 | | typename std::enable_if< |
65 | | llvm::conjunction< |
66 | | llvm::negation<std::is_same<typename std::decay<T>::type, Any>>, |
67 | | // We also disable this overload when an `Any` object can be |
68 | | // converted to the parameter type because in that case, this |
69 | | // constructor may combine with that conversion during overload |
70 | | // resolution for determining copy constructibility, and then |
71 | | // when we try to determine copy constructibility below we may |
72 | | // infinitely recurse. This is being evaluated by the standards |
73 | | // committee as a potential DR in `std::any` as well, but we're |
74 | | // going ahead and adopting it to work-around usage of `Any` with |
75 | | // types that need to be implicitly convertible from an `Any`. |
76 | | llvm::negation<std::is_convertible<Any, typename std::decay<T>::type>>, |
77 | | std::is_copy_constructible<typename std::decay<T>::type>>::value, |
78 | | int>::type = 0> |
79 | 2.39k | Any(T &&Value) { |
80 | 2.39k | using U = typename std::decay<T>::type; |
81 | 2.39k | Storage = llvm::make_unique<StorageImpl<U>>(std::forward<T>(Value)); |
82 | 2.39k | } llvm::Any::Any<llvm::Function const*, 0>(llvm::Function const*&&) Line | Count | Source | 79 | 1.64k | Any(T &&Value) { | 80 | 1.64k | using U = typename std::decay<T>::type; | 81 | 1.64k | Storage = llvm::make_unique<StorageImpl<U>>(std::forward<T>(Value)); | 82 | 1.64k | } |
llvm::Any::Any<llvm::LazyCallGraph::SCC const*, 0>(llvm::LazyCallGraph::SCC const*&&) Line | Count | Source | 79 | 151 | Any(T &&Value) { | 80 | 151 | using U = typename std::decay<T>::type; | 81 | 151 | Storage = llvm::make_unique<StorageImpl<U>>(std::forward<T>(Value)); | 82 | 151 | } |
llvm::Any::Any<llvm::Module const*, 0>(llvm::Module const*&&) Line | Count | Source | 79 | 413 | Any(T &&Value) { | 80 | 413 | using U = typename std::decay<T>::type; | 81 | 413 | Storage = llvm::make_unique<StorageImpl<U>>(std::forward<T>(Value)); | 82 | 413 | } |
llvm::Any::Any<llvm::Loop const*, 0>(llvm::Loop const*&&) Line | Count | Source | 79 | 183 | Any(T &&Value) { | 80 | 183 | using U = typename std::decay<T>::type; | 81 | 183 | Storage = llvm::make_unique<StorageImpl<U>>(std::forward<T>(Value)); | 82 | 183 | } |
Unexecuted instantiation: llvm::Any::Any<polly::Scop const*, 0>(polly::Scop const*&&) |
83 | | |
84 | 2.40k | Any(Any &&Other) : Storage(std::move(Other.Storage)) {} |
85 | | |
86 | 0 | Any &swap(Any &Other) { |
87 | 0 | std::swap(Storage, Other.Storage); |
88 | 0 | return *this; |
89 | 0 | } |
90 | | |
91 | | Any &operator=(Any Other) { |
92 | | Storage = std::move(Other.Storage); |
93 | | return *this; |
94 | | } |
95 | | |
96 | | bool hasValue() const { return !!Storage; } |
97 | | |
98 | 0 | void reset() { Storage.reset(); } |
99 | | |
100 | | private: |
101 | | template <class T> friend T any_cast(const Any &Value); |
102 | | template <class T> friend T any_cast(Any &Value); |
103 | | template <class T> friend T any_cast(Any &&Value); |
104 | | template <class T> friend const T *any_cast(const Any *Value); |
105 | | template <class T> friend T *any_cast(Any *Value); |
106 | | template <typename T> friend bool any_isa(const Any &Value); |
107 | | |
108 | | std::unique_ptr<StorageBase> Storage; |
109 | | }; |
110 | | |
111 | | template <typename T> const char Any::TypeId<T>::Id = 0; |
112 | | |
113 | | |
114 | 2.65k | template <typename T> bool any_isa(const Any &Value) { |
115 | 2.65k | if (!Value.Storage) |
116 | 0 | return false; |
117 | 2.65k | using U = |
118 | 2.65k | typename std::remove_cv<typename std::remove_reference<T>::type>::type; |
119 | 2.65k | return Value.Storage->id() == &Any::TypeId<U>::Id; |
120 | 2.65k | } bool llvm::any_isa<llvm::Module const*>(llvm::Any const&) Line | Count | Source | 114 | 1.42k | template <typename T> bool any_isa(const Any &Value) { | 115 | 1.42k | if (!Value.Storage) | 116 | 0 | return false; | 117 | 1.42k | using U = | 118 | 1.42k | typename std::remove_cv<typename std::remove_reference<T>::type>::type; | 119 | 1.42k | return Value.Storage->id() == &Any::TypeId<U>::Id; | 120 | 1.42k | } |
bool llvm::any_isa<llvm::Function const*>(llvm::Any const&) Line | Count | Source | 114 | 972 | template <typename T> bool any_isa(const Any &Value) { | 115 | 972 | if (!Value.Storage) | 116 | 0 | return false; | 117 | 972 | using U = | 118 | 972 | typename std::remove_cv<typename std::remove_reference<T>::type>::type; | 119 | 972 | return Value.Storage->id() == &Any::TypeId<U>::Id; | 120 | 972 | } |
bool llvm::any_isa<llvm::LazyCallGraph::SCC const*>(llvm::Any const&) Line | Count | Source | 114 | 138 | template <typename T> bool any_isa(const Any &Value) { | 115 | 138 | if (!Value.Storage) | 116 | 0 | return false; | 117 | 138 | using U = | 118 | 138 | typename std::remove_cv<typename std::remove_reference<T>::type>::type; | 119 | 138 | return Value.Storage->id() == &Any::TypeId<U>::Id; | 120 | 138 | } |
bool llvm::any_isa<llvm::Loop const*>(llvm::Any const&) Line | Count | Source | 114 | 122 | template <typename T> bool any_isa(const Any &Value) { | 115 | 122 | if (!Value.Storage) | 116 | 0 | return false; | 117 | 122 | using U = | 118 | 122 | typename std::remove_cv<typename std::remove_reference<T>::type>::type; | 119 | 122 | return Value.Storage->id() == &Any::TypeId<U>::Id; | 120 | 122 | } |
|
121 | | |
122 | | template <class T> T any_cast(const Any &Value) { |
123 | | using U = |
124 | | typename std::remove_cv<typename std::remove_reference<T>::type>::type; |
125 | | return static_cast<T>(*any_cast<U>(&Value)); |
126 | | } |
127 | | |
128 | 108 | template <class T> T any_cast(Any &Value) { |
129 | 108 | using U = |
130 | 108 | typename std::remove_cv<typename std::remove_reference<T>::type>::type; |
131 | 108 | return static_cast<T>(*any_cast<U>(&Value)); |
132 | 108 | } llvm::Module const* llvm::any_cast<llvm::Module const*>(llvm::Any&) Line | Count | Source | 128 | 42 | template <class T> T any_cast(Any &Value) { | 129 | 42 | using U = | 130 | 42 | typename std::remove_cv<typename std::remove_reference<T>::type>::type; | 131 | 42 | return static_cast<T>(*any_cast<U>(&Value)); | 132 | 42 | } |
llvm::Function const* llvm::any_cast<llvm::Function const*>(llvm::Any&) Line | Count | Source | 128 | 42 | template <class T> T any_cast(Any &Value) { | 129 | 42 | using U = | 130 | 42 | typename std::remove_cv<typename std::remove_reference<T>::type>::type; | 131 | 42 | return static_cast<T>(*any_cast<U>(&Value)); | 132 | 42 | } |
llvm::LazyCallGraph::SCC const* llvm::any_cast<llvm::LazyCallGraph::SCC const*>(llvm::Any&) Line | Count | Source | 128 | 14 | template <class T> T any_cast(Any &Value) { | 129 | 14 | using U = | 130 | 14 | typename std::remove_cv<typename std::remove_reference<T>::type>::type; | 131 | 14 | return static_cast<T>(*any_cast<U>(&Value)); | 132 | 14 | } |
llvm::Loop const* llvm::any_cast<llvm::Loop const*>(llvm::Any&) Line | Count | Source | 128 | 10 | template <class T> T any_cast(Any &Value) { | 129 | 10 | using U = | 130 | 10 | typename std::remove_cv<typename std::remove_reference<T>::type>::type; | 131 | 10 | return static_cast<T>(*any_cast<U>(&Value)); | 132 | 10 | } |
|
133 | | |
134 | | template <class T> T any_cast(Any &&Value) { |
135 | | using U = |
136 | | typename std::remove_cv<typename std::remove_reference<T>::type>::type; |
137 | | return static_cast<T>(std::move(*any_cast<U>(&Value))); |
138 | | } |
139 | | |
140 | | template <class T> const T *any_cast(const Any *Value) { |
141 | | using U = |
142 | | typename std::remove_cv<typename std::remove_reference<T>::type>::type; |
143 | | assert(Value && any_isa<T>(*Value) && "Bad any cast!"); |
144 | | if (!Value || !any_isa<U>(*Value)) |
145 | | return nullptr; |
146 | | return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; |
147 | | } |
148 | | |
149 | 108 | template <class T> T *any_cast(Any *Value) { |
150 | 108 | using U = typename std::decay<T>::type; |
151 | 108 | assert(Value && any_isa<U>(*Value) && "Bad any cast!"); |
152 | 108 | if (!Value || !any_isa<U>(*Value)) |
153 | 0 | return nullptr; |
154 | 108 | return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; |
155 | 108 | } llvm::Module const** llvm::any_cast<llvm::Module const*>(llvm::Any*) Line | Count | Source | 149 | 42 | template <class T> T *any_cast(Any *Value) { | 150 | 42 | using U = typename std::decay<T>::type; | 151 | 42 | assert(Value && any_isa<U>(*Value) && "Bad any cast!"); | 152 | 42 | if (!Value || !any_isa<U>(*Value)) | 153 | 0 | return nullptr; | 154 | 42 | return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; | 155 | 42 | } |
llvm::Function const** llvm::any_cast<llvm::Function const*>(llvm::Any*) Line | Count | Source | 149 | 42 | template <class T> T *any_cast(Any *Value) { | 150 | 42 | using U = typename std::decay<T>::type; | 151 | 42 | assert(Value && any_isa<U>(*Value) && "Bad any cast!"); | 152 | 42 | if (!Value || !any_isa<U>(*Value)) | 153 | 0 | return nullptr; | 154 | 42 | return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; | 155 | 42 | } |
llvm::LazyCallGraph::SCC const** llvm::any_cast<llvm::LazyCallGraph::SCC const*>(llvm::Any*) Line | Count | Source | 149 | 14 | template <class T> T *any_cast(Any *Value) { | 150 | 14 | using U = typename std::decay<T>::type; | 151 | 14 | assert(Value && any_isa<U>(*Value) && "Bad any cast!"); | 152 | 14 | if (!Value || !any_isa<U>(*Value)) | 153 | 0 | return nullptr; | 154 | 14 | return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; | 155 | 14 | } |
llvm::Loop const** llvm::any_cast<llvm::Loop const*>(llvm::Any*) Line | Count | Source | 149 | 10 | template <class T> T *any_cast(Any *Value) { | 150 | 10 | using U = typename std::decay<T>::type; | 151 | 10 | assert(Value && any_isa<U>(*Value) && "Bad any cast!"); | 152 | 10 | if (!Value || !any_isa<U>(*Value)) | 153 | 0 | return nullptr; | 154 | 10 | return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; | 155 | 10 | } |
|
156 | | |
157 | | } // end namespace llvm |
158 | | |
159 | | #endif // LLVM_ADT_ANY_H |