1+ use test_common:: { CommentKind , TestComment } ;
2+
13use crate :: common:: { CompareMode , Config , Debugger } ;
24use crate :: header:: IgnoreDecision ;
35use std:: collections:: HashSet ;
46
57const EXTRA_ARCHS : & [ & str ] = & [ "spirv" ] ;
68
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) ,
1515 } ,
1616 } ,
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+ }
1821 MatchOutcome :: External => IgnoreDecision :: Continue ,
1922 MatchOutcome :: NotADirective => IgnoreDecision :: Continue ,
2023 }
2124}
2225
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) ,
3333 } ,
3434 } ,
35- MatchOutcome :: Invalid => IgnoreDecision :: Error { message : format ! ( "invalid line: {line}" ) } ,
35+ MatchOutcome :: Invalid => {
36+ IgnoreDecision :: Error { message : format ! ( "invalid line: {}" , comment. comment_str( ) ) }
37+ }
3638 MatchOutcome :: External => IgnoreDecision :: Continue ,
3739 MatchOutcome :: NotADirective => IgnoreDecision :: Continue ,
3840 }
3941}
4042
4143/// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86`
4244/// or `normalize-stderr-32bit`.
43- pub ( super ) fn parse_cfg_name_directive < ' a > (
45+ pub ( super ) fn parse_cfg_name_directive < ' line > (
4446 config : & Config ,
45- line : & ' a str ,
47+ comment : & ' line TestComment < ' line > ,
4648 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 ) ,
5355 }
54- let line = & line [ prefix . len ( ) + 1 .. ] ;
56+ }
5557
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 ) ) ;
5876
5977 // Some of the matchers might be "" depending on what the target information is. To avoid
6078 // 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+ )
63126 }
127+ }
64128
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 ( ) ) ;
67138
68139 macro_rules! condition {
69140 (
@@ -75,19 +146,24 @@ pub(super) fn parse_cfg_name_directive<'a>(
75146 // This is not inlined to avoid problems with macro repetitions.
76147 let format_message = || format!( $( $message) * ) ;
77148
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) {
82150 if true $( && $condition) ? {
83- outcome = MatchOutcome :: Match ;
151+ return MatchOutcome :: Match {
152+ message: format_message( ) ,
153+ comment,
154+ } ;
84155 } else {
85- outcome = MatchOutcome :: NoMatch ;
156+ return MatchOutcome :: NoMatch {
157+ message: format_message( ) ,
158+ comment,
159+ } ;
86160 }
87161 }
88162 $( 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+ } ;
91167 } ) ?
92168 } } ;
93169 }
@@ -124,11 +200,6 @@ pub(super) fn parse_cfg_name_directive<'a>(
124200 allowed_names: & target_cfgs. all_oses_and_envs,
125201 message: "when the operating system and target environment are {name}"
126202 }
127- condition ! {
128- name: & target_cfg. abi,
129- allowed_names: & target_cfgs. all_abis,
130- message: "when the ABI is {name}"
131- }
132203 condition ! {
133204 name: & target_cfg. arch,
134205 allowed_names: ContainsEither { a: & target_cfgs. all_archs, b: & EXTRA_ARCHS } ,
@@ -215,64 +286,40 @@ pub(super) fn parse_cfg_name_directive<'a>(
215286 message: "when comparing with {name}" ,
216287 }
217288
218- if prefix == "ignore" && outcome == MatchOutcome :: Invalid {
289+ if prefix == "ignore" {
219290 // Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest.
220291 if name. starts_with ( "tidy-" ) {
221- outcome = MatchOutcome :: External ;
292+ return MatchOutcome :: External ;
222293 }
223294
224295 // Don't error out for ignore-pass, as that is handled elsewhere.
225296 if name == "pass" {
226- outcome = MatchOutcome :: External ;
297+ return MatchOutcome :: External ;
227298 }
228299
229300 // Don't error out for ignore-llvm-version, that has a custom syntax and is handled
230301 // elsewhere.
231302 if name == "llvm-version" {
232- outcome = MatchOutcome :: External ;
303+ return MatchOutcome :: External ;
233304 }
234305
235306 // Don't error out for ignore-llvm-version, that has a custom syntax and is handled
236307 // elsewhere.
237308 if name == "gdb-version" {
238- outcome = MatchOutcome :: External ;
309+ return MatchOutcome :: External ;
239310 }
240311 }
241312
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
248315}
249316
250- /// The result of parse_cfg_name_directive.
251317#[ 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 > {
272319 /// No match.
273- NoMatch ,
320+ NoMatch { message : String , comment : Option < & ' a str > } ,
274321 /// Match.
275- Match ,
322+ Match { message : String , comment : Option < & ' a str > } ,
276323 /// The directive was invalid.
277324 Invalid ,
278325 /// The directive is handled by other parts of our tooling.
0 commit comments