1
+ use test_common:: { CommentKind , TestComment } ;
2
+
1
3
use crate :: common:: { CompareMode , Config , Debugger } ;
2
4
use crate :: header:: IgnoreDecision ;
3
5
use std:: collections:: HashSet ;
4
6
5
7
const EXTRA_ARCHS : & [ & str ] = & [ "spirv" ] ;
6
8
7
- pub ( super ) fn handle_ignore ( config : & Config , line : & str ) -> IgnoreDecision {
8
- let parsed = parse_cfg_name_directive ( config, line, "ignore" ) ;
9
- match parsed. outcome {
10
- MatchOutcome :: NoMatch => IgnoreDecision :: Continue ,
11
- MatchOutcome :: Match => IgnoreDecision :: Ignore {
12
- reason : match parsed. comment {
13
- Some ( comment) => format ! ( "ignored {} ({comment})" , parsed. pretty_reason. unwrap( ) ) ,
14
- None => format ! ( "ignored {}" , parsed. pretty_reason. unwrap( ) ) ,
9
+ pub ( super ) fn handle_ignore ( config : & Config , comment : TestComment < ' _ > ) -> IgnoreDecision {
10
+ match parse_cfg_name_directive ( config, & comment, "ignore" ) {
11
+ MatchOutcome :: Match { message, comment } => IgnoreDecision :: Ignore {
12
+ reason : match comment {
13
+ Some ( comment) => format ! ( "ignored {} ({comment})" , message) ,
14
+ None => format ! ( "ignored {}" , message) ,
15
15
} ,
16
16
} ,
17
- MatchOutcome :: Invalid => IgnoreDecision :: Error { message : format ! ( "invalid line: {line}" ) } ,
17
+ MatchOutcome :: NoMatch { .. } => IgnoreDecision :: Continue ,
18
+ MatchOutcome :: Invalid => {
19
+ IgnoreDecision :: Error { message : format ! ( "invalid line: {}" , comment. comment_str( ) ) }
20
+ }
18
21
MatchOutcome :: External => IgnoreDecision :: Continue ,
19
22
MatchOutcome :: NotADirective => IgnoreDecision :: Continue ,
20
23
}
21
24
}
22
25
23
- pub ( super ) fn handle_only ( config : & Config , line : & str ) -> IgnoreDecision {
24
- let parsed = parse_cfg_name_directive ( config, line, "only" ) ;
25
- match parsed. outcome {
26
- MatchOutcome :: Match => IgnoreDecision :: Continue ,
27
- MatchOutcome :: NoMatch => IgnoreDecision :: Ignore {
28
- reason : match parsed. comment {
29
- Some ( comment) => {
30
- format ! ( "only executed {} ({comment})" , parsed. pretty_reason. unwrap( ) )
31
- }
32
- None => format ! ( "only executed {}" , parsed. pretty_reason. unwrap( ) ) ,
26
+ pub ( super ) fn handle_only ( config : & Config , comment : TestComment < ' _ > ) -> IgnoreDecision {
27
+ match parse_cfg_name_directive ( config, & comment, "only" ) {
28
+ MatchOutcome :: Match { .. } => IgnoreDecision :: Continue ,
29
+ MatchOutcome :: NoMatch { message, comment } => IgnoreDecision :: Ignore {
30
+ reason : match comment {
31
+ Some ( comment) => format ! ( "only executed {} ({comment})" , message) ,
32
+ None => format ! ( "only executed {}" , message) ,
33
33
} ,
34
34
} ,
35
- MatchOutcome :: Invalid => IgnoreDecision :: Error { message : format ! ( "invalid line: {line}" ) } ,
35
+ MatchOutcome :: Invalid => {
36
+ IgnoreDecision :: Error { message : format ! ( "invalid line: {}" , comment. comment_str( ) ) }
37
+ }
36
38
MatchOutcome :: External => IgnoreDecision :: Continue ,
37
39
MatchOutcome :: NotADirective => IgnoreDecision :: Continue ,
38
40
}
39
41
}
40
42
41
43
/// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86`
42
44
/// or `normalize-stderr-32bit`.
43
- pub ( super ) fn parse_cfg_name_directive < ' a > (
45
+ pub ( super ) fn parse_cfg_name_directive < ' line > (
44
46
config : & Config ,
45
- line : & ' a str ,
47
+ comment : & ' line TestComment < ' line > ,
46
48
prefix : & str ,
47
- ) -> ParsedNameDirective < ' a > {
48
- if !line . as_bytes ( ) . starts_with ( prefix . as_bytes ( ) ) {
49
- return ParsedNameDirective :: not_a_directive ( ) ;
50
- }
51
- if line . as_bytes ( ) . get ( prefix . len ( ) ) != Some ( & b'-' ) {
52
- return ParsedNameDirective :: not_a_directive ( ) ;
49
+ ) -> MatchOutcome < ' line > {
50
+ match comment . comment ( ) {
51
+ CommentKind :: Compiletest ( line ) => {
52
+ parse_cfg_name_directive_compiletest ( config , line , prefix )
53
+ }
54
+ CommentKind :: UiTest ( line ) => parse_cfg_name_directive_ui_test ( config , line , prefix ) ,
53
55
}
54
- let line = & line [ prefix . len ( ) + 1 .. ] ;
56
+ }
55
57
56
- let ( name, comment) =
57
- line. split_once ( & [ ':' , ' ' ] ) . map ( |( l, c) | ( l, Some ( c) ) ) . unwrap_or ( ( line, None ) ) ;
58
+ fn directive_name_for_line < ' line , ' p > (
59
+ line : & ' line str ,
60
+ prefix : & ' p str ,
61
+ ) -> Option < ( & ' line str , Option < & ' line str > ) > {
62
+ // Directives start with a specified prefix, and are immediately followed by a '-'.
63
+ let expected_start = format ! ( "{}-" , prefix) ;
64
+ let after_prefix = if line. starts_with ( expected_start. as_str ( ) ) {
65
+ & line[ expected_start. len ( ) ..]
66
+ } else {
67
+ return None ;
68
+ } ;
69
+
70
+ // If there is a ':' or a ' ' (space), split the name off, and consider the rest of the line to
71
+ // be a "comment" that is ignored.
72
+ let ( name, comment) = after_prefix
73
+ . split_once ( & [ ':' , ' ' ] )
74
+ . map ( |( l, c) | ( l. trim ( ) , Some ( c) ) )
75
+ . unwrap_or ( ( after_prefix, None ) ) ;
58
76
59
77
// Some of the matchers might be "" depending on what the target information is. To avoid
60
78
// problems we outright reject empty directives.
61
- if name == "" {
62
- return ParsedNameDirective :: not_a_directive ( ) ;
79
+ if name == "" { None } else { Some ( ( name, comment) ) }
80
+ }
81
+
82
+ fn parse_cfg_name_directive_ui_test < ' line > (
83
+ config : & Config ,
84
+ line : & ' line str ,
85
+ prefix : & str ,
86
+ ) -> MatchOutcome < ' line > {
87
+ let Some ( ( name, comment) ) = directive_name_for_line ( line, prefix) else {
88
+ return MatchOutcome :: NotADirective ;
89
+ } ;
90
+ let comment = comment. map ( |c| c. trim ( ) . trim_start_matches ( '-' ) . trim ( ) ) ;
91
+
92
+ let target_cfg = config. target_cfg ( ) ;
93
+
94
+ if name == "on-host" {
95
+ unimplemented ! ( "idk what to do about this yet" )
96
+ } else if let Some ( bits) = name. strip_suffix ( "bit" ) {
97
+ let Ok ( bits) = bits. parse :: < u32 > ( ) else {
98
+ // "invalid ignore/only filter ending in 'bit': {bits:?} is not a valid bitwdith"
99
+ return MatchOutcome :: Invalid ;
100
+ } ;
101
+
102
+ let message = format ! ( "when the pointer width is {}" , target_cfg. pointer_width) ;
103
+ if bits == target_cfg. pointer_width {
104
+ MatchOutcome :: Match { message, comment }
105
+ } else {
106
+ MatchOutcome :: NoMatch { message, comment }
107
+ }
108
+ } else if let Some ( triple_substr) = name. strip_prefix ( "target-" ) {
109
+ let message = format ! ( "when the target is {}" , config. target) ;
110
+ if config. target . contains ( triple_substr) {
111
+ MatchOutcome :: Match { message, comment }
112
+ } else {
113
+ MatchOutcome :: NoMatch { message, comment }
114
+ }
115
+ } else if let Some ( triple_substr) = name. strip_prefix ( "host-" ) {
116
+ let message = format ! ( "when the host is {}" , config. host) ;
117
+ if config. host . contains ( triple_substr) {
118
+ MatchOutcome :: Match { message, comment }
119
+ } else {
120
+ MatchOutcome :: NoMatch { message, comment }
121
+ }
122
+ } else {
123
+ panic ! (
124
+ "`{name}` is not a valid condition, expected `on-host`, /[0-9]+bit/, /host-.*/, or /target-.*/"
125
+ )
63
126
}
127
+ }
64
128
65
- let mut outcome = MatchOutcome :: Invalid ;
66
- let mut message = None ;
129
+ fn parse_cfg_name_directive_compiletest < ' a > (
130
+ config : & Config ,
131
+ line : & ' a str ,
132
+ prefix : & str ,
133
+ ) -> MatchOutcome < ' a > {
134
+ let Some ( ( name, comment) ) = directive_name_for_line ( line, prefix) else {
135
+ return MatchOutcome :: NotADirective ;
136
+ } ;
137
+ let comment = comment. map ( |c| c. trim ( ) . trim_start_matches ( '-' ) . trim ( ) ) ;
67
138
68
139
macro_rules! condition {
69
140
(
@@ -75,19 +146,24 @@ pub(super) fn parse_cfg_name_directive<'a>(
75
146
// This is not inlined to avoid problems with macro repetitions.
76
147
let format_message = || format!( $( $message) * ) ;
77
148
78
- if outcome != MatchOutcome :: Invalid {
79
- // Ignore all other matches if we already found one
80
- } else if $name. custom_matches( name) {
81
- message = Some ( format_message( ) ) ;
149
+ if $name. custom_matches( name) {
82
150
if true $( && $condition) ? {
83
- outcome = MatchOutcome :: Match ;
151
+ return MatchOutcome :: Match {
152
+ message: format_message( ) ,
153
+ comment,
154
+ } ;
84
155
} else {
85
- outcome = MatchOutcome :: NoMatch ;
156
+ return MatchOutcome :: NoMatch {
157
+ message: format_message( ) ,
158
+ comment,
159
+ } ;
86
160
}
87
161
}
88
162
$( else if $allowed_names. custom_contains( name) {
89
- message = Some ( format_message( ) ) ;
90
- outcome = MatchOutcome :: NoMatch ;
163
+ return MatchOutcome :: NoMatch {
164
+ message: format_message( ) ,
165
+ comment,
166
+ } ;
91
167
} ) ?
92
168
} } ;
93
169
}
@@ -124,11 +200,6 @@ pub(super) fn parse_cfg_name_directive<'a>(
124
200
allowed_names: & target_cfgs. all_oses_and_envs,
125
201
message: "when the operating system and target environment are {name}"
126
202
}
127
- condition ! {
128
- name: & target_cfg. abi,
129
- allowed_names: & target_cfgs. all_abis,
130
- message: "when the ABI is {name}"
131
- }
132
203
condition ! {
133
204
name: & target_cfg. arch,
134
205
allowed_names: ContainsEither { a: & target_cfgs. all_archs, b: & EXTRA_ARCHS } ,
@@ -215,64 +286,40 @@ pub(super) fn parse_cfg_name_directive<'a>(
215
286
message: "when comparing with {name}" ,
216
287
}
217
288
218
- if prefix == "ignore" && outcome == MatchOutcome :: Invalid {
289
+ if prefix == "ignore" {
219
290
// Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest.
220
291
if name. starts_with ( "tidy-" ) {
221
- outcome = MatchOutcome :: External ;
292
+ return MatchOutcome :: External ;
222
293
}
223
294
224
295
// Don't error out for ignore-pass, as that is handled elsewhere.
225
296
if name == "pass" {
226
- outcome = MatchOutcome :: External ;
297
+ return MatchOutcome :: External ;
227
298
}
228
299
229
300
// Don't error out for ignore-llvm-version, that has a custom syntax and is handled
230
301
// elsewhere.
231
302
if name == "llvm-version" {
232
- outcome = MatchOutcome :: External ;
303
+ return MatchOutcome :: External ;
233
304
}
234
305
235
306
// Don't error out for ignore-llvm-version, that has a custom syntax and is handled
236
307
// elsewhere.
237
308
if name == "gdb-version" {
238
- outcome = MatchOutcome :: External ;
309
+ return MatchOutcome :: External ;
239
310
}
240
311
}
241
312
242
- ParsedNameDirective {
243
- name : Some ( name) ,
244
- comment : comment. map ( |c| c. trim ( ) . trim_start_matches ( '-' ) . trim ( ) ) ,
245
- outcome,
246
- pretty_reason : message,
247
- }
313
+ // Did not match any known condition, emit an error.
314
+ MatchOutcome :: Invalid
248
315
}
249
316
250
- /// The result of parse_cfg_name_directive.
251
317
#[ derive( Clone , PartialEq , Debug ) ]
252
- pub ( super ) struct ParsedNameDirective < ' a > {
253
- pub ( super ) name : Option < & ' a str > ,
254
- pub ( super ) pretty_reason : Option < String > ,
255
- pub ( super ) comment : Option < & ' a str > ,
256
- pub ( super ) outcome : MatchOutcome ,
257
- }
258
-
259
- impl ParsedNameDirective < ' _ > {
260
- fn not_a_directive ( ) -> Self {
261
- Self {
262
- name : None ,
263
- pretty_reason : None ,
264
- comment : None ,
265
- outcome : MatchOutcome :: NotADirective ,
266
- }
267
- }
268
- }
269
-
270
- #[ derive( Clone , Copy , PartialEq , Debug ) ]
271
- pub ( super ) enum MatchOutcome {
318
+ pub ( super ) enum MatchOutcome < ' a > {
272
319
/// No match.
273
- NoMatch ,
320
+ NoMatch { message : String , comment : Option < & ' a str > } ,
274
321
/// Match.
275
- Match ,
322
+ Match { message : String , comment : Option < & ' a str > } ,
276
323
/// The directive was invalid.
277
324
Invalid ,
278
325
/// The directive is handled by other parts of our tooling.
0 commit comments