clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ASTConcept.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libclangAST/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libclangAST/obj/../include/clang/AST -I /usr/src/gnu/usr.bin/clang/libclangAST/../../../llvm/clang/include -I /usr/src/gnu/usr.bin/clang/libclangAST/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libclangAST/../include -I /usr/src/gnu/usr.bin/clang/libclangAST/obj -I /usr/src/gnu/usr.bin/clang/libclangAST/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libclangAST/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libclangAST/../../../llvm/clang/lib/AST/ASTConcept.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | #include "clang/AST/ASTConcept.h" |
16 | #include "clang/AST/ASTContext.h" |
17 | #include "clang/AST/Decl.h" |
18 | #include "clang/AST/TemplateBase.h" |
19 | #include "llvm/ADT/ArrayRef.h" |
20 | #include "llvm/ADT/FoldingSet.h" |
21 | using namespace clang; |
22 | |
23 | ASTConstraintSatisfaction::ASTConstraintSatisfaction(const ASTContext &C, |
24 | const ConstraintSatisfaction &Satisfaction): |
25 | NumRecords{Satisfaction.Details.size()}, |
26 | IsSatisfied{Satisfaction.IsSatisfied} { |
27 | for (unsigned I = 0; I < NumRecords; ++I) { |
| 2 | | Assuming 'I' is < field 'NumRecords' | |
|
| 3 | | Loop condition is true. Entering loop body | |
|
28 | auto &Detail = Satisfaction.Details[I]; |
29 | if (Detail.second.is<Expr *>()) |
| 4 | | Calling 'PointerUnion::is' | |
|
| 7 | | Returning from 'PointerUnion::is' | |
|
| |
30 | new (getTrailingObjects<UnsatisfiedConstraintRecord>() + I) |
| 9 | | Calling 'TrailingObjects::getTrailingObjects' | |
|
| 18 | | Returning from 'TrailingObjects::getTrailingObjects' | |
|
| 19 | | Storage provided to placement new is only 0 bytes, whereas the allocated type requires 16 bytes |
|
31 | UnsatisfiedConstraintRecord{Detail.first, |
32 | UnsatisfiedConstraintRecord::second_type( |
33 | Detail.second.get<Expr *>())}; |
34 | else { |
35 | auto &SubstitutionDiagnostic = |
36 | *Detail.second.get<std::pair<SourceLocation, StringRef> *>(); |
37 | unsigned MessageSize = SubstitutionDiagnostic.second.size(); |
38 | char *Mem = new (C) char[MessageSize]; |
39 | memcpy(Mem, SubstitutionDiagnostic.second.data(), MessageSize); |
40 | auto *NewSubstDiag = new (C) std::pair<SourceLocation, StringRef>( |
41 | SubstitutionDiagnostic.first, StringRef(Mem, MessageSize)); |
42 | new (getTrailingObjects<UnsatisfiedConstraintRecord>() + I) |
43 | UnsatisfiedConstraintRecord{Detail.first, |
44 | UnsatisfiedConstraintRecord::second_type( |
45 | NewSubstDiag)}; |
46 | } |
47 | } |
48 | } |
49 | |
50 | |
51 | ASTConstraintSatisfaction * |
52 | ASTConstraintSatisfaction::Create(const ASTContext &C, |
53 | const ConstraintSatisfaction &Satisfaction) { |
54 | std::size_t size = |
55 | totalSizeToAlloc<UnsatisfiedConstraintRecord>( |
56 | Satisfaction.Details.size()); |
57 | void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction)); |
58 | return new (Mem) ASTConstraintSatisfaction(C, Satisfaction); |
| 1 | Calling constructor for 'ASTConstraintSatisfaction' | |
|
59 | } |
60 | |
61 | void ConstraintSatisfaction::Profile( |
62 | llvm::FoldingSetNodeID &ID, const ASTContext &C, |
63 | const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) { |
64 | ID.AddPointer(ConstraintOwner); |
65 | ID.AddInteger(TemplateArgs.size()); |
66 | for (auto &Arg : TemplateArgs) |
67 | Arg.Profile(ID, C); |
68 | } |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #ifndef LLVM_ADT_POINTERUNION_H |
15 | #define LLVM_ADT_POINTERUNION_H |
16 | |
17 | #include "llvm/ADT/DenseMapInfo.h" |
18 | #include "llvm/ADT/PointerIntPair.h" |
19 | #include "llvm/Support/PointerLikeTypeTraits.h" |
20 | #include <cassert> |
21 | #include <cstddef> |
22 | #include <cstdint> |
23 | |
24 | namespace llvm { |
25 | |
26 | template <typename T> struct PointerUnionTypeSelectorReturn { |
27 | using Return = T; |
28 | }; |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | template <typename T1, typename T2, typename RET_EQ, typename RET_NE> |
40 | struct PointerUnionTypeSelector { |
41 | using Return = typename PointerUnionTypeSelectorReturn<RET_NE>::Return; |
42 | }; |
43 | |
44 | template <typename T, typename RET_EQ, typename RET_NE> |
45 | struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> { |
46 | using Return = typename PointerUnionTypeSelectorReturn<RET_EQ>::Return; |
47 | }; |
48 | |
49 | template <typename T1, typename T2, typename RET_EQ, typename RET_NE> |
50 | struct PointerUnionTypeSelectorReturn< |
51 | PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>> { |
52 | using Return = |
53 | typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return; |
54 | }; |
55 | |
56 | namespace pointer_union_detail { |
57 | |
58 | |
59 | constexpr int bitsRequired(unsigned n) { |
60 | return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0; |
61 | } |
62 | |
63 | template <typename... Ts> constexpr int lowBitsAvailable() { |
64 | return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...}); |
65 | } |
66 | |
67 | |
68 | |
69 | |
70 | template <typename T, typename ...Us> struct TypeIndex; |
71 | template <typename T, typename ...Us> struct TypeIndex<T, T, Us...> { |
72 | static constexpr int Index = 0; |
73 | }; |
74 | template <typename T, typename U, typename... Us> |
75 | struct TypeIndex<T, U, Us...> { |
76 | static constexpr int Index = 1 + TypeIndex<T, Us...>::Index; |
77 | }; |
78 | template <typename T> struct TypeIndex<T> { |
79 | static constexpr int Index = 0; |
80 | }; |
81 | |
82 | |
83 | template <typename T, typename...> struct GetFirstType { |
84 | using type = T; |
85 | }; |
86 | |
87 | |
88 | |
89 | template <typename ...PTs> class PointerUnionUIntTraits { |
90 | public: |
91 | static inline void *getAsVoidPointer(void *P) { return P; } |
92 | static inline void *getFromVoidPointer(void *P) { return P; } |
93 | static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>(); |
94 | }; |
95 | |
96 | template <typename Derived, typename ValTy, int I, typename ...Types> |
97 | class PointerUnionMembers; |
98 | |
99 | template <typename Derived, typename ValTy, int I> |
100 | class PointerUnionMembers<Derived, ValTy, I> { |
101 | protected: |
102 | ValTy Val; |
103 | PointerUnionMembers() = default; |
104 | PointerUnionMembers(ValTy Val) : Val(Val) {} |
105 | |
106 | friend struct PointerLikeTypeTraits<Derived>; |
107 | }; |
108 | |
109 | template <typename Derived, typename ValTy, int I, typename Type, |
110 | typename ...Types> |
111 | class PointerUnionMembers<Derived, ValTy, I, Type, Types...> |
112 | : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> { |
113 | using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>; |
114 | public: |
115 | using Base::Base; |
116 | PointerUnionMembers() = default; |
117 | PointerUnionMembers(Type V) |
118 | : Base(ValTy(const_cast<void *>( |
119 | PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), |
120 | I)) {} |
121 | |
122 | using Base::operator=; |
123 | Derived &operator=(Type V) { |
124 | this->Val = ValTy( |
125 | const_cast<void *>(PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), |
126 | I); |
127 | return static_cast<Derived &>(*this); |
128 | }; |
129 | }; |
130 | } |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | template <typename... PTs> |
149 | class PointerUnion |
150 | : public pointer_union_detail::PointerUnionMembers< |
151 | PointerUnion<PTs...>, |
152 | PointerIntPair< |
153 | void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int, |
154 | pointer_union_detail::PointerUnionUIntTraits<PTs...>>, |
155 | 0, PTs...> { |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | using First = typename pointer_union_detail::GetFirstType<PTs...>::type; |
162 | using Base = typename PointerUnion::PointerUnionMembers; |
163 | |
164 | public: |
165 | PointerUnion() = default; |
166 | |
167 | PointerUnion(std::nullptr_t) : PointerUnion() {} |
168 | using Base::Base; |
169 | |
170 | |
171 | |
172 | bool isNull() const { return !this->Val.getPointer(); } |
173 | |
174 | explicit operator bool() const { return !isNull(); } |
175 | |
176 | |
177 | template <typename T> bool is() const { |
178 | constexpr int Index = pointer_union_detail::TypeIndex<T, PTs...>::Index; |
179 | static_assert(Index < sizeof...(PTs), |
180 | "PointerUnion::is<T> given type not in the union"); |
181 | return this->Val.getInt() == Index; |
| 5 | | Assuming the condition is true | |
|
| 6 | | Returning the value 1, which participates in a condition later | |
|
182 | } |
183 | |
184 | |
185 | |
186 | |
187 | template <typename T> T get() const { |
188 | assert(is<T>() && "Invalid accessor called"); |
189 | return PointerLikeTypeTraits<T>::getFromVoidPointer(this->Val.getPointer()); |
190 | } |
191 | |
192 | |
193 | |
194 | template <typename T> T dyn_cast() const { |
195 | if (is<T>()) |
196 | return get<T>(); |
197 | return T(); |
198 | } |
199 | |
200 | |
201 | |
202 | First const *getAddrOfPtr1() const { |
203 | return const_cast<PointerUnion *>(this)->getAddrOfPtr1(); |
204 | } |
205 | |
206 | |
207 | |
208 | First *getAddrOfPtr1() { |
209 | assert(is<First>() && "Val is not the first pointer"); |
210 | assert( |
211 | PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) == |
212 | this->Val.getPointer() && |
213 | "Can't get the address because PointerLikeTypeTraits changes the ptr"); |
214 | return const_cast<First *>( |
215 | reinterpret_cast<const First *>(this->Val.getAddrOfPointer())); |
216 | } |
217 | |
218 | |
219 | const PointerUnion &operator=(std::nullptr_t) { |
220 | this->Val.initWithPointer(nullptr); |
221 | return *this; |
222 | } |
223 | |
224 | |
225 | using Base::operator=; |
226 | |
227 | void *getOpaqueValue() const { return this->Val.getOpaqueValue(); } |
228 | static inline PointerUnion getFromOpaqueValue(void *VP) { |
229 | PointerUnion V; |
230 | V.Val = decltype(V.Val)::getFromOpaqueValue(VP); |
231 | return V; |
232 | } |
233 | }; |
234 | |
235 | template <typename ...PTs> |
236 | bool operator==(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
237 | return lhs.getOpaqueValue() == rhs.getOpaqueValue(); |
238 | } |
239 | |
240 | template <typename ...PTs> |
241 | bool operator!=(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
242 | return lhs.getOpaqueValue() != rhs.getOpaqueValue(); |
243 | } |
244 | |
245 | template <typename ...PTs> |
246 | bool operator<(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
247 | return lhs.getOpaqueValue() < rhs.getOpaqueValue(); |
248 | } |
249 | |
250 | |
251 | |
252 | template <typename ...PTs> |
253 | struct PointerLikeTypeTraits<PointerUnion<PTs...>> { |
254 | static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) { |
255 | return P.getOpaqueValue(); |
256 | } |
257 | |
258 | static inline PointerUnion<PTs...> getFromVoidPointer(void *P) { |
259 | return PointerUnion<PTs...>::getFromOpaqueValue(P); |
260 | } |
261 | |
262 | |
263 | |
264 | static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype( |
265 | PointerUnion<PTs...>::Val)>::NumLowBitsAvailable; |
266 | }; |
267 | |
268 | |
269 | template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> { |
270 | using Union = PointerUnion<PTs...>; |
271 | using FirstInfo = |
272 | DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>; |
273 | |
274 | static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); } |
275 | |
276 | static inline Union getTombstoneKey() { |
277 | return Union(FirstInfo::getTombstoneKey()); |
278 | } |
279 | |
280 | static unsigned getHashValue(const Union &UnionVal) { |
281 | intptr_t key = (intptr_t)UnionVal.getOpaqueValue(); |
282 | return DenseMapInfo<intptr_t>::getHashValue(key); |
283 | } |
284 | |
285 | static bool isEqual(const Union &LHS, const Union &RHS) { |
286 | return LHS == RHS; |
287 | } |
288 | }; |
289 | |
290 | } |
291 | |
292 | #endif // LLVM_ADT_POINTERUNION_H |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | #ifndef LLVM_SUPPORT_TRAILINGOBJECTS_H |
47 | #define LLVM_SUPPORT_TRAILINGOBJECTS_H |
48 | |
49 | #include "llvm/Support/AlignOf.h" |
50 | #include "llvm/Support/Alignment.h" |
51 | #include "llvm/Support/Compiler.h" |
52 | #include "llvm/Support/MathExtras.h" |
53 | #include "llvm/Support/type_traits.h" |
54 | #include <new> |
55 | #include <type_traits> |
56 | |
57 | namespace llvm { |
58 | |
59 | namespace trailing_objects_internal { |
60 | |
61 | |
62 | template <typename First, typename... Rest> class AlignmentCalcHelper { |
63 | private: |
64 | enum { |
65 | FirstAlignment = alignof(First), |
66 | RestAlignment = AlignmentCalcHelper<Rest...>::Alignment, |
67 | }; |
68 | |
69 | public: |
70 | enum { |
71 | Alignment = FirstAlignment > RestAlignment ? FirstAlignment : RestAlignment |
72 | }; |
73 | }; |
74 | |
75 | template <typename First> class AlignmentCalcHelper<First> { |
76 | public: |
77 | enum { Alignment = alignof(First) }; |
78 | }; |
79 | |
80 | |
81 | class TrailingObjectsBase { |
82 | protected: |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | template <typename T> struct OverloadToken {}; |
89 | }; |
90 | |
91 | |
92 | |
93 | |
94 | template <typename Ty1, typename Ty2> struct ExtractSecondType { |
95 | typedef Ty2 type; |
96 | }; |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy, |
107 | typename... MoreTys> |
108 | class TrailingObjectsImpl { |
109 | |
110 | |
111 | }; |
112 | |
113 | template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy, |
114 | typename NextTy, typename... MoreTys> |
115 | class TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy, NextTy, |
116 | MoreTys...> |
117 | : public TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, NextTy, |
118 | MoreTys...> { |
119 | |
120 | typedef TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, NextTy, MoreTys...> |
121 | ParentType; |
122 | |
123 | struct RequiresRealignment { |
124 | static const bool value = alignof(PrevTy) < alignof(NextTy); |
125 | }; |
126 | |
127 | static constexpr bool requiresRealignment() { |
128 | return RequiresRealignment::value; |
129 | } |
130 | |
131 | protected: |
132 | |
133 | using ParentType::getTrailingObjectsImpl; |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | static const NextTy * |
145 | getTrailingObjectsImpl(const BaseTy *Obj, |
146 | TrailingObjectsBase::OverloadToken<NextTy>) { |
147 | auto *Ptr = TopTrailingObj::getTrailingObjectsImpl( |
148 | Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) + |
149 | TopTrailingObj::callNumTrailingObjects( |
150 | Obj, TrailingObjectsBase::OverloadToken<PrevTy>()); |
151 | |
152 | if (requiresRealignment()) |
153 | return reinterpret_cast<const NextTy *>( |
154 | alignAddr(Ptr, Align::Of<NextTy>())); |
155 | else |
156 | return reinterpret_cast<const NextTy *>(Ptr); |
157 | } |
158 | |
159 | static NextTy * |
160 | getTrailingObjectsImpl(BaseTy *Obj, |
161 | TrailingObjectsBase::OverloadToken<NextTy>) { |
162 | auto *Ptr = TopTrailingObj::getTrailingObjectsImpl( |
| |
163 | Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) + |
| 12 | | Passing value via 1st parameter 'Obj' | |
|
164 | TopTrailingObj::callNumTrailingObjects( |
165 | Obj, TrailingObjectsBase::OverloadToken<PrevTy>()); |
166 | |
167 | if (requiresRealignment()) |
| |
168 | return reinterpret_cast<NextTy *>(alignAddr(Ptr, Align::Of<NextTy>())); |
169 | else |
170 | return reinterpret_cast<NextTy *>(Ptr); |
| 15 | | Returning pointer (loaded from 'Ptr') | |
|
171 | } |
172 | |
173 | |
174 | |
175 | |
176 | static constexpr size_t additionalSizeToAllocImpl( |
177 | size_t SizeSoFar, size_t Count1, |
178 | typename ExtractSecondType<MoreTys, size_t>::type... MoreCounts) { |
179 | return ParentType::additionalSizeToAllocImpl( |
180 | (requiresRealignment() ? llvm::alignTo<alignof(NextTy)>(SizeSoFar) |
181 | : SizeSoFar) + |
182 | sizeof(NextTy) * Count1, |
183 | MoreCounts...); |
184 | } |
185 | }; |
186 | |
187 | |
188 | |
189 | template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy> |
190 | class alignas(Align) TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy> |
191 | : public TrailingObjectsBase { |
192 | protected: |
193 | |
194 | |
195 | |
196 | static void getTrailingObjectsImpl(); |
197 | |
198 | static constexpr size_t additionalSizeToAllocImpl(size_t SizeSoFar) { |
199 | return SizeSoFar; |
200 | } |
201 | |
202 | template <bool CheckAlignment> static void verifyTrailingObjectsAlignment() {} |
203 | }; |
204 | |
205 | } |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | template <typename BaseTy, typename... TrailingTys> |
212 | class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl< |
213 | trailing_objects_internal::AlignmentCalcHelper< |
214 | TrailingTys...>::Alignment, |
215 | BaseTy, TrailingObjects<BaseTy, TrailingTys...>, |
216 | BaseTy, TrailingTys...> { |
217 | |
218 | template <int A, typename B, typename T, typename P, typename... M> |
219 | friend class trailing_objects_internal::TrailingObjectsImpl; |
220 | |
221 | template <typename... Tys> class Foo {}; |
222 | |
223 | typedef trailing_objects_internal::TrailingObjectsImpl< |
224 | trailing_objects_internal::AlignmentCalcHelper<TrailingTys...>::Alignment, |
225 | BaseTy, TrailingObjects<BaseTy, TrailingTys...>, BaseTy, TrailingTys...> |
226 | ParentType; |
227 | using TrailingObjectsBase = trailing_objects_internal::TrailingObjectsBase; |
228 | |
229 | using ParentType::getTrailingObjectsImpl; |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | static void verifyTrailingObjectsAssertions() { |
236 | static_assert(std::is_final<BaseTy>(), "BaseTy must be final."); |
237 | } |
238 | |
239 | |
240 | static const BaseTy * |
241 | getTrailingObjectsImpl(const BaseTy *Obj, |
242 | TrailingObjectsBase::OverloadToken<BaseTy>) { |
243 | return Obj; |
244 | } |
245 | |
246 | static BaseTy * |
247 | getTrailingObjectsImpl(BaseTy *Obj, |
248 | TrailingObjectsBase::OverloadToken<BaseTy>) { |
249 | return Obj; |
250 | } |
251 | |
252 | |
253 | |
254 | |
255 | |
256 | |
257 | |
258 | |
259 | static size_t |
260 | callNumTrailingObjects(const BaseTy *Obj, |
261 | TrailingObjectsBase::OverloadToken<BaseTy>) { |
262 | return 1; |
263 | } |
264 | |
265 | template <typename T> |
266 | static size_t callNumTrailingObjects(const BaseTy *Obj, |
267 | TrailingObjectsBase::OverloadToken<T>) { |
268 | return Obj->numTrailingObjects(TrailingObjectsBase::OverloadToken<T>()); |
269 | } |
270 | |
271 | public: |
272 | |
273 | #ifndef _MSC_VER |
274 | using ParentType::OverloadToken; |
275 | #else |
276 | |
277 | |
278 | template <typename T> |
279 | using OverloadToken = typename ParentType::template OverloadToken<T>; |
280 | #endif |
281 | |
282 | |
283 | |
284 | |
285 | template <typename T> const T *getTrailingObjects() const { |
286 | verifyTrailingObjectsAssertions(); |
287 | |
288 | |
289 | return this->getTrailingObjectsImpl( |
290 | static_cast<const BaseTy *>(this), |
291 | TrailingObjectsBase::OverloadToken<T>()); |
292 | } |
293 | |
294 | |
295 | |
296 | |
297 | template <typename T> T *getTrailingObjects() { |
298 | verifyTrailingObjectsAssertions(); |
299 | |
300 | |
301 | return this->getTrailingObjectsImpl( |
| 11 | | Calling 'TrailingObjectsImpl::getTrailingObjectsImpl' | |
|
| 16 | | Returning from 'TrailingObjectsImpl::getTrailingObjectsImpl' | |
|
| |
302 | static_cast<BaseTy *>(this), TrailingObjectsBase::OverloadToken<T>()); |
| 10 | | Passing value via 1st parameter 'Obj' | |
|
303 | } |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | |
310 | |
311 | template <typename... Tys> |
312 | static constexpr std::enable_if_t< |
313 | std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t> |
314 | additionalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType< |
315 | TrailingTys, size_t>::type... Counts) { |
316 | return ParentType::additionalSizeToAllocImpl(0, Counts...); |
317 | } |
318 | |
319 | |
320 | |
321 | |
322 | |
323 | template <typename... Tys> |
324 | static constexpr std::enable_if_t< |
325 | std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t> |
326 | totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType< |
327 | TrailingTys, size_t>::type... Counts) { |
328 | return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...); |
329 | } |
330 | |
331 | TrailingObjects() = default; |
332 | TrailingObjects(const TrailingObjects &) = delete; |
333 | TrailingObjects(TrailingObjects &&) = delete; |
334 | TrailingObjects &operator=(const TrailingObjects &) = delete; |
335 | TrailingObjects &operator=(TrailingObjects &&) = delete; |
336 | |
337 | |
338 | |
339 | |
340 | |
341 | |
342 | |
343 | |
344 | |
345 | |
346 | |
347 | |
348 | |
349 | |
350 | |
351 | |
352 | template <typename... Tys> struct FixedSizeStorage { |
353 | template <size_t... Counts> struct with_counts { |
354 | enum { Size = totalSizeToAlloc<Tys...>(Counts...) }; |
355 | struct type { |
356 | alignas(BaseTy) char buffer[Size]; |
357 | }; |
358 | }; |
359 | }; |
360 | |
361 | |
362 | class FixedSizeStorageOwner { |
363 | public: |
364 | FixedSizeStorageOwner(BaseTy *p) : p(p) {} |
365 | ~FixedSizeStorageOwner() { |
366 | assert(p && "FixedSizeStorageOwner owns null?"); |
367 | p->~BaseTy(); |
368 | } |
369 | |
370 | BaseTy *get() { return p; } |
371 | const BaseTy *get() const { return p; } |
372 | |
373 | private: |
374 | FixedSizeStorageOwner(const FixedSizeStorageOwner &) = delete; |
375 | FixedSizeStorageOwner(FixedSizeStorageOwner &&) = delete; |
376 | FixedSizeStorageOwner &operator=(const FixedSizeStorageOwner &) = delete; |
377 | FixedSizeStorageOwner &operator=(FixedSizeStorageOwner &&) = delete; |
378 | |
379 | BaseTy *const p; |
380 | }; |
381 | }; |
382 | |
383 | } |
384 | |
385 | #endif |