@@ -72,6 +72,25 @@ public enum FileCheckFD {
7272 }
7373}
7474
75+ /// `FileCheckSource` enumerates possible sources of Check Strings that act as
76+ /// the model against which output is checked.
77+ public enum FileCheckSource {
78+ /// A path to a file that will be opened and parsed for check strings. If the
79+ /// file path is invalid, checking will abort.
80+ case filePath( String )
81+ /// A buffer of check strings.
82+ case buffer( String )
83+ }
84+
85+ /// - Bug: (SR-3258) Expansion of magic literals like #file does not behave
86+ /// correctly when in argument position. Making it convertible from String
87+ /// does do the expansion for some reason.
88+ extension FileCheckSource : ExpressibleByStringLiteral {
89+ public init ( stringLiteral value: String ) {
90+ self = . filePath( value)
91+ }
92+ }
93+
7594/// Reads from the given output stream and runs a file verification procedure
7695/// by comparing the output to a specified result.
7796///
@@ -92,7 +111,7 @@ public enum FileCheckFD {
92111/// file descriptor.
93112///
94113/// - returns: Whether or not FileCheck succeeded in verifying the file.
95- public func fileCheckOutput( of FD : FileCheckFD = . stdout, withPrefixes prefixes : [ String ] = [ " CHECK " ] , checkNot : [ String ] = [ ] , against file : String = #file, options: FileCheckOptions = [ ] , block : ( ) -> ( ) ) -> Bool {
114+ public func fileCheckOutput( of FD : FileCheckFD = . stdout, withPrefixes prefixes : [ String ] = [ " CHECK " ] , checkNot : [ String ] = [ ] , against source : FileCheckSource = #file, options: FileCheckOptions = [ ] , block : ( ) -> ( ) ) -> Bool {
96115 guard let validPrefixes = validateCheckPrefixes ( prefixes) else {
97116 print ( " Supplied check-prefix is invalid! Prefixes must be unique and " ,
98117 " start with a letter and contain only alphanumeric characters, " ,
@@ -109,16 +128,25 @@ public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes
109128 let input = overrideFDAndCollectOutput ( file: FD, of: block)
110129 if input. isEmpty {
111130 guard options. contains ( . allowEmptyInput) else {
112- print ( " FileCheck error: input from file descriptor \( FD) is empty. \n " )
131+ print ( " FileCheck error: input from file descriptor \( FD) is empty. " )
113132 return false
114133 }
115134
116135 return true
117136 }
118137
119- guard let contents = try ? String ( contentsOfFile: file, encoding: . utf8) else {
120- return false
138+ let contents : String
139+ switch source {
140+ case . filePath( let file) :
141+ guard let openFile = try ? String ( contentsOfFile: file, encoding: . utf8) else {
142+ print ( " FileCheck error: unable to open check file at path \( file) . " )
143+ return false
144+ }
145+ contents = openFile
146+ case . buffer( let buf) :
147+ contents = buf
121148 }
149+
122150 let buf = contents. cString ( using: . utf8) ? . withUnsafeBufferPointer { buffer in
123151 return readCheckStrings ( in: buffer, withPrefixes: validPrefixes, checkNot: checkNot, options: options, prefixRE)
124152 }
@@ -407,7 +435,9 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
407435 }
408436
409437 // Scan ahead to the end of line.
410- let EOL : Int = buffer. index ( of: ( " \n " as Character ) . utf8CodePoint) ?? buffer. index ( of: ( " \r " as Character ) . utf8CodePoint) !
438+ let EOL : Int = buffer. index ( of: ( " \n " as Character ) . utf8CodePoint)
439+ ?? buffer. index ( of: ( " \r " as Character ) . utf8CodePoint)
440+ ?? buffer. count - 1
411441
412442 // Remember the location of the start of the pattern, for diagnostics.
413443 let patternLoc = CheckLocation . inBuffer ( buffer. baseAddress!, buf)
0 commit comments