@@ -74,19 +74,40 @@ public enum CType {
7474extension CType : CustomStringConvertible {
7575 /// Print the part of this type that comes before the declarator, appending
7676 /// it to the provided `result` string.
77- func printBefore( result: inout String ) {
77+ func printBefore( hasEmptyPlaceholder: inout Bool , result: inout String ) {
78+ // Save the value of hasEmptyPlaceholder and restore it once we're done
79+ // here.
80+ let previousHasEmptyPlaceholder = hasEmptyPlaceholder
81+ defer {
82+ hasEmptyPlaceholder = previousHasEmptyPlaceholder
83+ }
84+
7885 switch self {
7986 case . floating( let floating) :
8087 switch floating {
8188 case . float: result += " float "
8289 case . double: result += " double "
8390 }
8491
92+ spaceBeforePlaceHolder (
93+ hasEmptyPlaceholder: hasEmptyPlaceholder,
94+ result: & result
95+ )
96+
8597 case . function( resultType: let resultType, parameters: _, variadic: _) :
86- resultType. printBefore ( result: & result)
98+ let previousHasEmptyPlaceholder = hasEmptyPlaceholder
99+ hasEmptyPlaceholder = false
100+ defer {
101+ hasEmptyPlaceholder = previousHasEmptyPlaceholder
102+ }
103+ resultType. printBefore (
104+ hasEmptyPlaceholder: & hasEmptyPlaceholder,
105+ result: & result
106+ )
87107
88- // FIXME: Clang inserts a parentheses in here if there's a non-empty
89- // placeholder, which is Very Stateful. How should I model that?
108+ if !previousHasEmptyPlaceholder {
109+ result += " ( "
110+ }
90111
91112 case . integral( let integral) :
92113 switch integral {
@@ -97,21 +118,47 @@ extension CType: CustomStringConvertible {
97118 case . size_t: result += " size_t "
98119 }
99120
121+ spaceBeforePlaceHolder (
122+ hasEmptyPlaceholder: hasEmptyPlaceholder,
123+ result: & result
124+ )
125+
100126 case . pointer( let pointee) :
101- pointee. printBefore ( result: & result)
127+ var innerHasEmptyPlaceholder = false
128+ pointee. printBefore (
129+ hasEmptyPlaceholder: & innerHasEmptyPlaceholder,
130+ result: & result
131+ )
102132 result += " * "
103133
104134 case . qualified( const: let isConst, volatile: let isVolatile, type: let underlying) :
105- underlying. printBefore ( result: & result)
135+ if isConst || isVolatile {
136+ hasEmptyPlaceholder = false
137+ }
138+
139+ underlying. printBefore ( hasEmptyPlaceholder: & hasEmptyPlaceholder, result: & result)
106140
107141 // FIXME: "east const" is easier to print correctly, so do that. We could
108142 // follow Clang and decide when it's correct to print "west const" by
109143 // splitting the qualifiers before we get here.
110144 if isConst {
111- result += " const "
145+ result += " const "
146+ hasEmptyPlaceholder = false
147+
148+ spaceBeforePlaceHolder (
149+ hasEmptyPlaceholder: hasEmptyPlaceholder,
150+ result: & result
151+ )
152+
112153 }
113154 if isVolatile {
114- result += " volatile "
155+ result += " volatile "
156+ hasEmptyPlaceholder = false
157+
158+ spaceBeforePlaceHolder (
159+ hasEmptyPlaceholder: hasEmptyPlaceholder,
160+ result: & result
161+ )
115162 }
116163
117164 case . tag( let tag) :
@@ -121,7 +168,18 @@ extension CType: CustomStringConvertible {
121168 case . union( let cUnion) : result += " union \( cUnion. name) "
122169 }
123170
124- case . void: result += " void "
171+ spaceBeforePlaceHolder (
172+ hasEmptyPlaceholder: hasEmptyPlaceholder,
173+ result: & result
174+ )
175+
176+ case . void:
177+ result += " void "
178+
179+ spaceBeforePlaceHolder (
180+ hasEmptyPlaceholder: hasEmptyPlaceholder,
181+ result: & result
182+ )
125183 }
126184 }
127185
@@ -146,13 +204,14 @@ extension CType: CustomStringConvertible {
146204
147205 /// Print the part of the type that comes after the declarator, appending
148206 /// it to the provided `result` string.
149- func printAfter( result: inout String ) {
207+ func printAfter( hasEmptyPlaceholder : inout Bool , result: inout String ) {
150208 switch self {
151209 case . floating, . integral, . tag, . void: break
152210
153211 case . function( resultType: let resultType, parameters: let parameters, variadic: let variadic) :
154- // FIXME: Clang inserts a parentheses in here if there's a non-empty
155- // placeholder, which is Very Stateful. How should I model that?
212+ if !hasEmptyPlaceholder {
213+ result += " ) "
214+ }
156215
157216 result += " ( "
158217
@@ -167,33 +226,53 @@ extension CType: CustomStringConvertible {
167226
168227 result += " ) "
169228
170- resultType. printAfter ( result: & result)
229+ var innerHasEmptyPlaceholder = false
230+ resultType. printAfter (
231+ hasEmptyPlaceholder: & innerHasEmptyPlaceholder,
232+ result: & result
233+ )
171234
172235 case . pointer( let pointee) :
173- pointee. printAfter ( result: & result)
236+ var innerHasEmptyPlaceholder = false
237+ pointee. printAfter (
238+ hasEmptyPlaceholder: & innerHasEmptyPlaceholder,
239+ result: & result
240+ )
174241
175242 case . qualified( const: _, volatile: _, type: let underlying) :
176- underlying. printAfter ( result: & result)
243+ underlying. printAfter (
244+ hasEmptyPlaceholder: & hasEmptyPlaceholder,
245+ result: & result
246+ )
177247 }
178248 }
179249
180250 /// Print this type into a string, with the given placeholder as the name
181251 /// of the entity being declared.
182252 public func print( placeholder: String ? ) -> String {
253+ var hasEmptyPlaceholder = ( placeholder == nil )
183254 var result = " "
184- printBefore ( result: & result)
255+ printBefore ( hasEmptyPlaceholder : & hasEmptyPlaceholder , result: & result)
185256 if let placeholder {
186- result += " "
187257 result += placeholder
188258 }
189- printAfter ( result: & result)
259+ printAfter ( hasEmptyPlaceholder : & hasEmptyPlaceholder , result: & result)
190260 return result
191261 }
192262
193263 /// Render the C type into a string that represents the type in C.
194264 public var description : String {
195265 print ( placeholder: nil )
196266 }
267+
268+ private func spaceBeforePlaceHolder(
269+ hasEmptyPlaceholder: Bool ,
270+ result: inout String
271+ ) {
272+ if !hasEmptyPlaceholder {
273+ result += " "
274+ }
275+ }
197276}
198277
199278extension CType {
0 commit comments