1010//
1111//===----------------------------------------------------------------------===//
1212
13+ #if SWIFT_SYNTAX_BUILD_USING_CMAKE
14+ // The CMake bulid of swift-syntax does not build the _AtomicBool module because swift-syntax's CMake build is
15+ // Swift-only. Fake an `AtomicBool` type that is not actually atomic. This should be acceptable for the following
16+ // reasons:
17+ // - `AtomicBool` is only used for the `hasParent` assertion, so release compilers don't rely on it
18+ // - The compiler is single-threaded so it it is safe from race conditions on `AtomicBool`.
19+ fileprivate struct AtomicBool {
20+ var value : Bool
21+
22+ init ( initialValue: Bool ) {
23+ self . value = initialValue
24+ }
25+ }
26+ #else
27+ import _AtomicBool
28+ #endif
29+
1330/// A syntax arena owns the memory for all syntax nodes within it.
1431///
1532/// The following is only relevant if you are accessing the raw syntax tree using
@@ -52,7 +69,7 @@ public class SyntaxArena {
5269 ///
5370 /// - Important: This is only intended to be used for assertions to catch
5471 /// retain cycles in syntax arenas.
55- var hasParent : Bool
72+ fileprivate var hasParent : AtomicBool
5673 #endif
5774
5875 /// Construct a new ``SyntaxArena`` in which syntax nodes can be allocated.
@@ -64,7 +81,7 @@ public class SyntaxArena {
6481 self . allocator = BumpPtrAllocator ( initialSlabSize: slabSize)
6582 self . childRefs = [ ]
6683 #if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
67- self . hasParent = false
84+ self . hasParent = AtomicBool ( initialValue : false )
6885 #endif
6986 }
7087
@@ -141,7 +158,7 @@ public class SyntaxArena {
141158
142159 #if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
143160 precondition (
144- !self . hasParent,
161+ !self . hasParent. value ,
145162 " an arena can't have a new child once it's owned by other arenas "
146163 )
147164 #endif
@@ -285,16 +302,12 @@ struct SyntaxArenaRef: Hashable, @unchecked Sendable {
285302 #if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
286303 /// Accessor for ther underlying's `SyntaxArena.hasParent`
287304 var hasParent : Bool {
288- // FIXME: This accesses mutable state across actor boundaries and is thus not concurrency-safe.
289- // We should use an atomic for `hasParent` to make it concurrency safe.
290- value. hasParent
305+ value. hasParent. value
291306 }
292307
293308 /// Sets the `SyntaxArena.hasParent` on the referenced arena.
294309 func setHasParent( _ newValue: Bool ) {
295- // FIXME: This modifies mutable state across actor boundaries and is thus not concurrency-safe.
296- // We should use an atomic for `hasParent` to make it concurrency safe.
297- value. hasParent = newValue
310+ value. hasParent. value = newValue
298311 }
299312 #endif
300313
0 commit comments