@@ -6,6 +6,8 @@ import Foundation
66 import Darwin
77#endif
88
9+ /// `FileCheckOptions` enumerates supported FileCheck options that can be used
10+ /// to modify the behavior of the checking routine.
911public struct FileCheckOptions : OptionSet {
1012 public let rawValue : UInt64
1113
@@ -97,7 +99,7 @@ public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes
9799 " hyphens and underscores " )
98100 return false
99101 }
100- guard let prefixRE = try ? NSRegularExpression ( pattern: validPrefixes. sorted ( by: > ) . joined ( separator: " | " ) , options : [ ] ) else {
102+ guard let prefixRE = try ? NSRegularExpression ( pattern: validPrefixes. sorted ( by: > ) . joined ( separator: " | " ) ) else {
101103 print ( " Unable to combine check-prefix strings into a prefix regular " ,
102104 " expression! This is likely a bug in FileCheck's verification of " ,
103105 " the check-prefix strings. Regular expression parsing failed. " )
@@ -162,7 +164,7 @@ private func overrideFDAndCollectOutput(file : FileCheckFD, of block : () -> ())
162164}
163165
164166private func validateCheckPrefixes( _ prefixes : [ String ] ) -> [ String ] ? {
165- let validator = try ! NSRegularExpression ( pattern: " ^[a-zA-Z0-9_-]*$ " , options : [ ] )
167+ let validator = try ! NSRegularExpression ( pattern: " ^[a-zA-Z0-9_-]*$ " )
166168
167169 for prefix in prefixes {
168170 // Reject empty prefixes.
@@ -174,7 +176,7 @@ private func validateCheckPrefixes(_ prefixes : [String]) -> [String]? {
174176 location: 0 ,
175177 length: prefix. distance ( from: prefix. startIndex, to: prefix. endIndex)
176178 )
177- if validator. matches ( in: prefix, options : [ ] , range: range) . isEmpty {
179+ if validator. matches ( in: prefix, range: range) . isEmpty {
178180 return nil
179181 }
180182 }
@@ -266,7 +268,31 @@ extension UnsafeBufferPointer {
266268 }
267269}
268270
269- func substring( in buffer : UnsafeBufferPointer < CChar > , with range : NSRange ) -> String {
271+ extension CheckLocation {
272+ var message : String {
273+ switch self {
274+ case let . inBuffer( ptr, buf) :
275+ var startPtr = ptr
276+ while startPtr != buf. baseAddress! && startPtr. predecessor ( ) . pointee != ( " \n " as Character ) . utf8CodePoint {
277+ startPtr = startPtr. predecessor ( )
278+ }
279+
280+ var endPtr = ptr
281+ while endPtr != buf. baseAddress!. advanced ( by: buf. endIndex) && endPtr. successor ( ) . pointee != ( " \n " as Character ) . utf8CodePoint {
282+ endPtr = endPtr. successor ( )
283+ }
284+ // One more for good measure.
285+ if endPtr != buf. baseAddress!. advanced ( by: buf. endIndex) {
286+ endPtr = endPtr. successor ( )
287+ }
288+ return substring ( in: buf, with: NSMakeRange ( buf. baseAddress!. distance ( to: startPtr) , startPtr. distance ( to: endPtr) ) )
289+ case let . string( s) :
290+ return s
291+ }
292+ }
293+ }
294+
295+ private func substring( in buffer : UnsafeBufferPointer < CChar > , with range : NSRange ) -> String {
270296 precondition ( range. location + range. length <= buffer. count)
271297 let ptr = buffer. substr ( range. location, range. length)
272298 return String ( bytesNoCopy: UnsafeMutableRawPointer ( mutating: ptr. baseAddress!) , length: range. length, encoding: . utf8, freeWhenDone: false ) ?? " "
@@ -278,7 +304,7 @@ private func findFirstMatch(in inbuffer : UnsafeBufferPointer<CChar>, among pref
278304
279305 while !buffer. isEmpty {
280306 let str = String ( bytesNoCopy: UnsafeMutableRawPointer ( mutating: buffer. baseAddress!) , length: buffer. count, encoding: . utf8, freeWhenDone: false ) !
281- let match = RE . firstMatch ( in: str, options : [ ] , range: NSRange ( location: 0 , length: str. distance ( from: str. startIndex, to: str. endIndex) ) )
307+ let match = RE . firstMatch ( in: str, range: NSRange ( location: 0 , length: str. distance ( from: str. startIndex, to: str. endIndex) ) )
282308 guard let prefix = match else {
283309 return ( " " , . none, lineNumber, buffer)
284310 }
@@ -343,7 +369,7 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
343369 let patBuf = UnsafeBufferPointer < CChar > ( start: buf. baseAddress, count: buf. count - 1 )
344370 let pat = Pattern ( checking: . not, in: buf, pattern: patBuf, withPrefix: " IMPLICIT-CHECK " , at: 0 , options: options) !
345371 // Compute the message from this buffer now for diagnostics later.
346- let msg = CheckLoc . inBuffer ( buf. baseAddress!, buf) . message
372+ let msg = CheckLocation . inBuffer ( buf. baseAddress!, buf) . message
347373 implicitNegativeChecks. append ( Pattern ( copying: pat, at: . string( " IMPLICIT-CHECK-NOT: " + msg) ) )
348374 }
349375 }
@@ -360,11 +386,11 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
360386 lineNumber = ln
361387
362388 // Skip the buffer to the end.
363- buffer = newBuffer. dropFront ( usedPrefix. utf8. count + checkTy. size )
389+ buffer = newBuffer. dropFront ( usedPrefix. utf8. count + checkTy. prefixSize )
364390
365391 // Complain about useful-looking but unsupported suffixes.
366392 if checkTy == . badNot {
367- let loc = CheckLoc . inBuffer ( buffer. baseAddress!, buf)
393+ let loc = CheckLocation . inBuffer ( buffer. baseAddress!, buf)
368394 diagnose ( . error, at: loc, with: " unsupported -NOT combo on prefix ' \( usedPrefix) ' " , options: options)
369395 return [ ]
370396 }
@@ -382,7 +408,7 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
382408 let EOL : Int = buffer. index ( of: ( " \n " as Character ) . utf8CodePoint) ?? buffer. index ( of: ( " \r " as Character ) . utf8CodePoint) !
383409
384410 // Remember the location of the start of the pattern, for diagnostics.
385- let patternLoc = CheckLoc . inBuffer ( buffer. baseAddress!, buf)
411+ let patternLoc = CheckLocation . inBuffer ( buffer. baseAddress!, buf)
386412
387413 // Parse the pattern.
388414 let subBuffer = UnsafeBufferPointer < CChar > ( start: buffer. baseAddress, count: EOL)
@@ -399,7 +425,7 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
399425 // Verify that CHECK-NEXT lines have at least one CHECK line before them.
400426 if ( checkTy == . next || checkTy == . same) && contents. isEmpty {
401427 let type = ( checkTy == . next) ? " NEXT " : " SAME "
402- let loc = CheckLoc . inBuffer ( buffer. baseAddress!, buf)
428+ let loc = CheckLocation . inBuffer ( buffer. baseAddress!, buf)
403429 diagnose ( . error, at: loc, with: " found ' \( usedPrefix) - \( type) ' without previous ' \( usedPrefix) : line " , options: options)
404430 return [ ]
405431 }
@@ -419,7 +445,7 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
419445 let cs = CheckString (
420446 pattern: pat,
421447 prefix: usedPrefix,
422- loc : . string( patternLoc. message) ,
448+ location : . string( patternLoc. message) ,
423449 dagNotStrings: dagNotMatches
424450 )
425451 contents. append ( cs)
@@ -430,9 +456,9 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
430456 // prefix as a filler for the error message.
431457 if !dagNotMatches. isEmpty {
432458 let cs = CheckString (
433- pattern: Pattern ( withType: . EOF ) ,
459+ pattern: Pattern ( withType: . endOfFile ) ,
434460 prefix: prefixes. first!,
435- loc : dagNotMatches. last!. patternLoc,
461+ location : dagNotMatches. last!. patternLoc,
436462 dagNotStrings: dagNotMatches
437463 )
438464 contents. append ( cs)
@@ -454,7 +480,7 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
454480///
455481/// Returns `false` if the input fails to satisfy the checks.
456482private func check( input b : String , against checkStrings : [ CheckString ] , options: FileCheckOptions ) -> Bool {
457- var buffer = b
483+ var buffer = Substring ( b )
458484 var failedChecks = false
459485
460486 // This holds all the current filecheck variables.
@@ -463,7 +489,7 @@ private func check(input b : String, against checkStrings : [CheckString], optio
463489 var i = 0
464490 var j = 0
465491 while true {
466- var checkRegion : String
492+ var checkRegion : Substring
467493 if j == checkStrings. count {
468494 checkRegion = buffer
469495 } else {
@@ -474,14 +500,14 @@ private func check(input b : String, against checkStrings : [CheckString], optio
474500 }
475501
476502 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
477- guard let ( range, mutVariableTable) = checkStr. check ( buffer, true , variableTable, options) else {
503+ guard let ( range, mutVariableTable) = checkStr. check ( String ( buffer) , true , variableTable, options) else {
478504 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
479505 return false
480506 }
481507
482508 variableTable = mutVariableTable
483- checkRegion = String ( buffer [ ..< buffer. index ( buffer. startIndex, offsetBy: NSMaxRange ( range) ) ] )
484- buffer = String ( buffer [ buffer. index ( buffer. startIndex, offsetBy: NSMaxRange ( range) ) ... ] )
509+ checkRegion = buffer [ ..< buffer. index ( buffer. startIndex, offsetBy: NSMaxRange ( range) ) ]
510+ buffer = buffer [ buffer. index ( buffer. startIndex, offsetBy: NSMaxRange ( range) ) ... ]
485511 j += 1
486512 }
487513
@@ -490,13 +516,13 @@ private func check(input b : String, against checkStrings : [CheckString], optio
490516
491517 // Check each string within the scanned region, including a second check
492518 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
493- guard let ( range, mutVarTable) = checkStrings [ i] . check ( checkRegion, false , variableTable, options) else {
519+ guard let ( range, mutVarTable) = checkStrings [ i] . check ( String ( checkRegion) , false , variableTable, options) else {
494520 failedChecks = true
495521 i = j- 1
496522 break
497523 }
498524 variableTable = mutVarTable
499- checkRegion = String ( checkRegion [ checkRegion. index ( checkRegion. startIndex, offsetBy: NSMaxRange ( range) ) ... ] )
525+ checkRegion = checkRegion [ checkRegion. index ( checkRegion. startIndex, offsetBy: NSMaxRange ( range) ) ... ]
500526 }
501527
502528 if j == checkStrings. count {
0 commit comments