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) |
| 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) |
| 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 |
|
| 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 false | |
|
| 6 | | Returning zero, 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 |