@@ -27,6 +27,10 @@ public struct FileCheckOptions: OptionSet {
27
27
public static let matchFullLines = FileCheckOptions ( rawValue: 1 << 2 )
28
28
/// Disable colored diagnostics.
29
29
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 )
30
34
}
31
35
32
36
/// `FileCheckFD` represents the standard output streams `FileCheck` is capable
@@ -101,6 +105,8 @@ extension FileCheckSource: ExpressibleByStringLiteral {
101
105
/// - parameter FD: The file descriptor to override and read from.
102
106
/// - parameter prefixes: Specifies one or more prefixes to match. By default
103
107
/// these patterns are prefixed with "CHECK".
108
+ /// - parameter globals: Specifies a dictionary of global variables whose
109
+ /// names may be used in capture patterns.
104
110
/// - parameter checkNot: Specifies zero or more prefixes to implicitly reject
105
111
/// in the output stream. This can be used to implement LLVM-verifier-like
106
112
/// checks.
@@ -111,7 +117,15 @@ extension FileCheckSource: ExpressibleByStringLiteral {
111
117
/// file descriptor.
112
118
///
113
119
/// - 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 {
115
129
guard let validPrefixes = validateCheckPrefixes ( prefixes) else {
116
130
print ( " Supplied check-prefix is invalid! Prefixes must be unique and " ,
117
131
" start with a letter and contain only alphanumeric characters, " ,
@@ -154,7 +168,7 @@ public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes
154
168
return false
155
169
}
156
170
157
- return check ( input: input, against: checkStrings, options: options)
171
+ return check ( input: input, against: checkStrings, withGlobals : globals , options: options)
158
172
}
159
173
160
174
private func overrideFDAndCollectOutput( file : FileCheckFD , of block : ( ) -> ( ) ) -> String {
@@ -511,12 +525,17 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
511
525
/// strings read from the check file.
512
526
///
513
527
/// 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 {
515
534
var buffer = Substring ( b)
516
535
var failedChecks = false
517
536
518
537
// This holds all the current filecheck variables.
519
- var variableTable = [ String : String ] ( )
538
+ var variableTable = globals
520
539
521
540
var i = 0
522
541
var j = 0
@@ -543,6 +562,20 @@ private func check(input b : String, against checkStrings : [CheckString], optio
543
562
j += 1
544
563
}
545
564
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
+
546
579
while i != j {
547
580
defer { i += 1 }
548
581
0 commit comments