@@ -27,6 +27,10 @@ public struct FileCheckOptions: OptionSet {
2727 public static let matchFullLines = FileCheckOptions ( rawValue: 1 << 2 )
2828 /// Disable colored diagnostics.
2929 public static let disableColors = FileCheckOptions ( rawValue: 1 << 3 )
30+ /// Enables scoping for variables defined in patterns. Variables with names
31+ /// that do not start with `$` will be reset at the beginning of each
32+ /// `CHECK-LABEL` block.
33+ public static let scopedVariables = FileCheckOptions ( rawValue: 1 << 4 )
3034}
3135
3236/// `FileCheckFD` represents the standard output streams `FileCheck` is capable
@@ -101,6 +105,8 @@ extension FileCheckSource: ExpressibleByStringLiteral {
101105/// - parameter FD: The file descriptor to override and read from.
102106/// - parameter prefixes: Specifies one or more prefixes to match. By default
103107/// these patterns are prefixed with "CHECK".
108+ /// - parameter globals: Specifies a dictionary of global variables whose
109+ /// names may be used in capture patterns.
104110/// - parameter checkNot: Specifies zero or more prefixes to implicitly reject
105111/// in the output stream. This can be used to implement LLVM-verifier-like
106112/// checks.
@@ -111,7 +117,15 @@ extension FileCheckSource: ExpressibleByStringLiteral {
111117/// file descriptor.
112118///
113119/// - returns: Whether or not FileCheck succeeded in verifying the file.
114- public func fileCheckOutput( of FD : FileCheckFD = . stdout, withPrefixes prefixes : [ String ] = [ " CHECK " ] , checkNot : [ String ] = [ ] , against source : FileCheckSource = #file, options: FileCheckOptions = [ ] , block : ( ) -> ( ) ) -> Bool {
120+ public func fileCheckOutput(
121+ of FD : FileCheckFD = . stdout,
122+ withPrefixes prefixes : [ String ] = [ " CHECK " ] ,
123+ withGlobals globals: [ String : String ] = [ : ] ,
124+ checkNot : [ String ] = [ ] ,
125+ against source : FileCheckSource = #file,
126+ options: FileCheckOptions = [ ] ,
127+ block : ( ) -> ( )
128+ ) -> Bool {
115129 guard let validPrefixes = validateCheckPrefixes ( prefixes) else {
116130 print ( " Supplied check-prefix is invalid! Prefixes must be unique and " ,
117131 " start with a letter and contain only alphanumeric characters, " ,
@@ -154,7 +168,7 @@ public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes
154168 return false
155169 }
156170
157- return check ( input: input, against: checkStrings, options: options)
171+ return check ( input: input, against: checkStrings, withGlobals : globals , options: options)
158172}
159173
160174private func overrideFDAndCollectOutput( file : FileCheckFD , of block : ( ) -> ( ) ) -> String {
@@ -511,12 +525,17 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
511525/// strings read from the check file.
512526///
513527/// Returns `false` if the input fails to satisfy the checks.
514- private func check( input b : String , against checkStrings : [ CheckString ] , options: FileCheckOptions ) -> Bool {
528+ private func check(
529+ input b : String ,
530+ against checkStrings : [ CheckString ] ,
531+ withGlobals globals: [ String : String ] ,
532+ options: FileCheckOptions
533+ ) -> Bool {
515534 var buffer = Substring ( b)
516535 var failedChecks = false
517536
518537 // This holds all the current filecheck variables.
519- var variableTable = [ String : String ] ( )
538+ var variableTable = globals
520539
521540 var i = 0
522541 var j = 0
@@ -543,6 +562,20 @@ private func check(input b : String, against checkStrings : [CheckString], optio
543562 j += 1
544563 }
545564
565+ // Remove local variables from the variable table. Global variables
566+ // (start with `$`) are preserved.
567+ if options. contains ( . scopedVariables) {
568+ var localVariables = [ String] ( )
569+ localVariables. reserveCapacity ( 16 )
570+ for (k, v) in variableTable where !k. hasPrefix ( " $ " ) {
571+ localVariables. append ( k)
572+ }
573+
574+ for k in localVariables {
575+ variableTable. removeValue ( forKey: k)
576+ }
577+ }
578+
546579 while i != j {
547580 defer { i += 1 }
548581
0 commit comments