Skip to content

Commit 4f38403

Browse files
committed
stdlib: fix bugs in StaticString.isASCII and add tests
rdar://18301485 rdar://18139547 Swift SVN r22356
1 parent 41a48f2 commit 4f38403

File tree

2 files changed

+143
-3
lines changed

2 files changed

+143
-3
lines changed

stdlib/core/StaticString.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ public struct StaticString
8484
/// `byteSize` is unspecified.
8585
@transparent
8686
public var byteSize: Word {
87+
_precondition(
88+
hasPointerRepresentation,
89+
"StaticString should have pointer representation")
8790
return Word(_byteSize)
8891
}
8992

@@ -99,7 +102,7 @@ public struct StaticString
99102
/// `isASCII` is unspecified.
100103
@transparent
101104
public var isASCII: Bool {
102-
return (UWord(_flags) & 0x2) == 1
105+
return (UWord(_flags) & 0x2) == 0x2
103106
}
104107

105108
/// Invoke `body` with a buffer containing the UTF-8 code units of
@@ -146,7 +149,7 @@ public struct StaticString
146149
) {
147150
self._startPtrOrData = start
148151
self._byteSize = byteSize
149-
self._flags = Bool(isASCII) ? 0x2.value : 0.value
152+
self._flags = Bool(isASCII) ? 0x2.value : 0x0.value
150153
}
151154

152155
@transparent
@@ -156,7 +159,7 @@ public struct StaticString
156159
self._startPtrOrData =
157160
unsafeBitCast(UWord(UInt32(unicodeScalar)), COpaquePointer.self)._rawValue
158161
self._byteSize = 0.value
159-
self._flags = 0.value
162+
self._flags = UnicodeScalar(unicodeScalar).isASCII() ? 0x3.value : 0x1.value
160163
}
161164

162165
@effects(readonly)

test/stdlib/StaticString.swift

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// RUN: %target-build-swift -parse-stdlib -Xfrontend -disable-access-control -module-name a %s -o %t.out
2+
// RUN: %target-run %t.out
3+
4+
import Swift
5+
import StdlibUnittest
6+
7+
var StaticStringTestSuite = TestSuite("StaticString")
8+
9+
StaticStringTestSuite.test("PointerRepresentation/ASCII/Empty") {
10+
let str = StaticString()
11+
expectEqual(0, str.byteSize)
12+
expectTrue(str.hasPointerRepresentation)
13+
expectTrue(str.isASCII)
14+
str.withUTF8Buffer {
15+
utf8 in
16+
expectEqual(0, utf8.count)
17+
}
18+
expectEqual("", str.stringValue)
19+
20+
expectPrinted("", str)
21+
expectDebugPrinted("\"\"", str)
22+
}
23+
24+
StaticStringTestSuite.test("PointerRepresentation/ASCII") {
25+
let str: StaticString = "abc"
26+
expectEqual(0x61, str.utf8Start[0])
27+
expectEqual(0x62, str.utf8Start[1])
28+
expectEqual(0x63, str.utf8Start[2])
29+
expectEqual(3, str.byteSize)
30+
expectTrue(str.hasPointerRepresentation)
31+
expectTrue(str.isASCII)
32+
str.withUTF8Buffer {
33+
utf8 -> () in
34+
expectEqual(3, utf8.count)
35+
expectEqual(0x61, utf8[0])
36+
expectEqual(0x62, utf8[1])
37+
expectEqual(0x63, utf8[2])
38+
}
39+
expectEqual("abc", str.stringValue)
40+
41+
expectPrinted("abc", str)
42+
expectDebugPrinted("\"abc\"", str)
43+
}
44+
45+
StaticStringTestSuite.test("PointerRepresentation/NonASCII") {
46+
let str: StaticString = "абв"
47+
expectEqual(0xd0, str.utf8Start[0])
48+
expectEqual(0xb0, str.utf8Start[1])
49+
expectEqual(0xd0, str.utf8Start[2])
50+
expectEqual(0xb1, str.utf8Start[3])
51+
expectEqual(0xd0, str.utf8Start[4])
52+
expectEqual(0xb2, str.utf8Start[5])
53+
expectEqual(6, str.byteSize)
54+
expectTrue(str.hasPointerRepresentation)
55+
expectFalse(str.isASCII)
56+
str.withUTF8Buffer {
57+
utf8 -> () in
58+
expectEqual(6, utf8.count)
59+
expectEqual(0xd0, utf8[0])
60+
expectEqual(0xb0, utf8[1])
61+
expectEqual(0xd0, utf8[2])
62+
expectEqual(0xb1, utf8[3])
63+
expectEqual(0xd0, utf8[4])
64+
expectEqual(0xb2, utf8[5])
65+
}
66+
expectEqual("абв", str.stringValue)
67+
68+
expectPrinted("абв", str)
69+
expectDebugPrinted("\"абв\"", str)
70+
}
71+
72+
StaticStringTestSuite.test("PointerRepresentation/unicodeScalar")
73+
.crashOutputMatches("StaticString should have Unicode scalar representation")
74+
.code {
75+
let str: StaticString = "abc"
76+
let strOpaque = _opaqueIdentity(str)
77+
expectCrashLater()
78+
strOpaque.unicodeScalar
79+
}
80+
81+
StaticStringTestSuite.test("UnicodeScalarRepresentation/ASCII") {
82+
// The type checker does not call the UnicodeScalar initializer even if
83+
// passed a literal that consists from a single Unicode scalar.
84+
85+
// U+005A LATIN CAPITAL LETTER Z
86+
let str = StaticString(_builtinUnicodeScalarLiteral: UInt32(0x5a).value)
87+
expectEqual("Z", str.unicodeScalar)
88+
expectFalse(str.hasPointerRepresentation)
89+
expectTrue(str.isASCII)
90+
str.withUTF8Buffer {
91+
utf8 -> () in
92+
expectEqual(1, utf8.count)
93+
expectEqual(0x5a, utf8[0])
94+
}
95+
expectEqual("Z", str.stringValue)
96+
97+
expectPrinted("Z", str)
98+
expectDebugPrinted("\"Z\"", str)
99+
}
100+
101+
StaticStringTestSuite.test("UnicodeScalarRepresentation/NonASCII") {
102+
// U+042B CYRILLIC CAPITAL LETTER YERU
103+
let str = StaticString(_builtinUnicodeScalarLiteral: UInt32(0x042b).value)
104+
expectEqual("Ы", str.unicodeScalar)
105+
expectFalse(str.hasPointerRepresentation)
106+
expectFalse(str.isASCII)
107+
str.withUTF8Buffer {
108+
utf8 -> () in
109+
expectEqual(0xd0, utf8[0])
110+
expectEqual(0xab, utf8[1])
111+
}
112+
expectEqual("Ы", str.stringValue)
113+
114+
expectPrinted("Ы", str)
115+
expectDebugPrinted("\"Ы\"", str)
116+
}
117+
118+
StaticStringTestSuite.test("UnicodeScalarRepresentation/utf8Start")
119+
.crashOutputMatches("StaticString should have pointer representation")
120+
.code {
121+
let str = StaticString(_builtinUnicodeScalarLiteral: UInt32(0x5a).value)
122+
let strOpaque = _opaqueIdentity(str)
123+
expectCrashLater()
124+
strOpaque.utf8Start
125+
}
126+
127+
StaticStringTestSuite.test("UnicodeScalarRepresentation/byteSize")
128+
.crashOutputMatches("StaticString should have pointer representation")
129+
.code {
130+
let str = StaticString(_builtinUnicodeScalarLiteral: UInt32(0x5a).value)
131+
let strOpaque = _opaqueIdentity(str)
132+
expectCrashLater()
133+
strOpaque.byteSize
134+
}
135+
136+
runAllTests()
137+

0 commit comments

Comments
 (0)