File tree Expand file tree Collapse file tree 1 file changed +49
-0
lines changed Expand file tree Collapse file tree 1 file changed +49
-0
lines changed Original file line number Diff line number Diff line change @@ -149,6 +149,55 @@ class KnownSizeSet {
149149 size_t size () const { return numElements; }
150150};
151151
152+ // / Embed a reference to a Bitfield container inside a longer-lived object so
153+ // / the bitfield container can be stack allocated with a properly nested minimal
154+ // / lifetime. Accessing the container outside the scope of it's stack allocation
155+ // / results in a nullptr dereference.
156+ // /
157+ // / struct Parent {
158+ // / BitfieldRef<Container> container;
159+ // /
160+ // / void performWithContainer(SILFunction *function) {
161+ // / BitfieldRef<Container>::StackState state(container, functon);
162+ // /
163+ // / assert(container->isValid());
164+ // / }
165+ // / };
166+ // /
167+ // / TODO: give this variadic template parameters to support a BitfieldContainer
168+ // / whose constructor takes more than a single SILFunction argument.
169+ template <typename BitfieldContainer> struct BitfieldRef {
170+ BitfieldContainer *ref = nullptr ;
171+
172+ BitfieldRef () {}
173+
174+ BitfieldContainer &operator *() const {
175+ assert (ref);
176+ return *ref;
177+ }
178+
179+ BitfieldContainer *operator ->() const {
180+ assert (ref);
181+ return ref;
182+ }
183+
184+ // Stack-allocated state must be nested relative to other node bitfields.
185+ struct StackState {
186+ BitfieldRef &ref;
187+ BitfieldContainer container;
188+
189+ StackState (BitfieldRef &ref, SILFunction *function)
190+ : ref(ref), container(function) {
191+ ref.ref = &container;
192+ }
193+
194+ ~StackState () { ref.ref = nullptr ; }
195+ };
196+
197+ private:
198+ BitfieldRef (const BitfieldRef &) = delete ;
199+ };
200+
152201} // namespace swift
153202
154203#endif
You can’t perform that action at this time.
0 commit comments