Skip to content

Commit 4da171a

Browse files
committed
[Utils] Add custom prefix support to update-verify-tests
Custom prefixes can now be provided with --prefix. The default remains 'expected'.
1 parent 3ed872c commit 4da171a

File tree

4 files changed

+98
-69
lines changed

4 files changed

+98
-69
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
void foo() {
2+
a = 2; // check-error{{asdf}}
3+
// expected-error@-1{ignored}}
4+
}
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
void foo() {
2+
a = 2; // check-error{{use of undeclared identifier 'a'}}
3+
// expected-error@-1{ignored}}
4+
}
5+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# RUN: cp %S/Inputs/non-default-prefix.c %t.c && not %clang_cc1 -verify=check %t.c 2>&1 | %update-verify-tests --prefix check
2+
# RUN: diff -u %S/Inputs/non-default-prefix.c.expected %t.c
3+
# RUN: %clang_cc1 -verify=check %t.c
4+

clang/utils/update-verify-tests.py

Lines changed: 84 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import sys
22
import re
3+
import argparse
34

45
"""
56
Pipe output from clang's -verify into this script to have the test case updated to expect the actual diagnostic output.
@@ -10,7 +11,6 @@
1011
diffs. If inaccurate their count will be updated, or the check removed entirely.
1112
1213
Missing features:
13-
- custom prefix support (-verify=my-prefix)
1414
- multiple prefixes on the same line (-verify=my-prefix,my-other-prefix)
1515
- multiple prefixes on separate RUN lines (RUN: -verify=my-prefix\nRUN: -verify my-other-prefix)
1616
- regexes with expected-*-re: existing ones will be left untouched if accurate, but the script will abort if there are any
@@ -27,16 +27,16 @@ class KnownException(Exception):
2727
pass
2828

2929

30-
def parse_error_category(s):
31-
if "no expected directives found" in line:
30+
def parse_error_category(s, prefix):
31+
if "no expected directives found" in s:
3232
return None
3333
parts = s.split("diagnostics")
3434
diag_category = parts[0]
3535
category_parts = parts[0].strip().strip("'").split("-")
3636
expected = category_parts[0]
37-
if expected != "expected":
37+
if expected != prefix:
3838
raise Exception(
39-
f"expected 'expected', but found '{expected}'. Custom verify prefixes are not supported."
39+
f"expected prefix '{prefix}', but found '{expected}'. Multiple verify prefixes are not supported."
4040
)
4141
diag_category = category_parts[1]
4242
if "seen but not expected" in parts[1]:
@@ -84,6 +84,7 @@ def render(self):
8484
class Diag:
8585
def __init__(
8686
self,
87+
prefix,
8788
diag_content,
8889
category,
8990
parsed_target_line_n,
@@ -94,6 +95,7 @@ def __init__(
9495
whitespace_strings,
9596
is_from_source_file,
9697
):
98+
self.prefix = prefix
9799
self.diag_content = diag_content
98100
self.category = category
99101
self.parsed_target_line_n = parsed_target_line_n
@@ -183,14 +185,14 @@ def render(self):
183185
been parsed as whitespace3_s.
184186
"""
185187
whitespace2_s = ""
186-
return f"//{whitespace1_s}expected-{self.category}{re_s}{line_location_s}{whitespace2_s}{count_s}{whitespace3_s}{{{{{self.diag_content}}}}}"
188+
return f"//{whitespace1_s}{self.prefix}-{self.category}{re_s}{line_location_s}{whitespace2_s}{count_s}{whitespace3_s}{{{{{self.diag_content}}}}}"
187189

188190
expected_diag_re = re.compile(
189-
r"//(\s*)expected-(note|warning|error)(-re)?(@[+-]?\d+)?(?:(\s*)(\d+))?(\s*)\{\{(.*)\}\}"
191+
r"//(\s*)([a-zA-Z]+)-(note|warning|error)(-re)?(@[+-]?\d+)?(?:(\s*)(\d+))?(\s*)\{\{(.*)\}\}"
190192
)
191193

192194

193-
def parse_diag(line, filename, lines):
195+
def parse_diag(line, filename, lines, prefix):
194196
s = line.content
195197
ms = expected_diag_re.findall(s)
196198
if not ms:
@@ -201,6 +203,7 @@ def parse_diag(line, filename, lines):
201203
)
202204
[
203205
whitespace1_s,
206+
check_prefix,
204207
category_s,
205208
re_s,
206209
target_line_s,
@@ -209,6 +212,8 @@ def parse_diag(line, filename, lines):
209212
whitespace3_s,
210213
diag_s,
211214
] = ms[0]
215+
if check_prefix != prefix:
216+
return None
212217
if not target_line_s:
213218
target_line_n = 0
214219
is_absolute = False
@@ -225,6 +230,7 @@ def parse_diag(line, filename, lines):
225230
line.content = expected_diag_re.sub("{{DIAG}}", s)
226231

227232
return Diag(
233+
prefix,
228234
diag_s,
229235
category_s,
230236
target_line_n,
@@ -263,7 +269,7 @@ def get_indent(s):
263269
def orig_line_n_to_new_line_n(line_n, orig_lines):
264270
return orig_lines[line_n - 1].line_n
265271

266-
def add_diag(orig_line_n, diag_s, diag_category, lines, orig_lines):
272+
def add_diag(orig_line_n, diag_s, diag_category, lines, orig_lines, prefix):
267273
line_n = orig_line_n_to_new_line_n(orig_line_n, orig_lines)
268274
target = lines[line_n - 1]
269275
for other in target.targeting_diags:
@@ -301,7 +307,7 @@ def add_diag(orig_line_n, diag_s, diag_category, lines, orig_lines):
301307

302308
whitespace_strings = prev_line.diag.whitespace_strings if prev_line.diag else None
303309
new_diag = Diag(
304-
diag_s, diag_category, total_offset, False, 1, new_line, False, whitespace_strings, False,
310+
prefix, diag_s, diag_category, total_offset, False, 1, new_line, False, whitespace_strings, False,
305311
)
306312
new_line.diag = new_diag
307313
new_diag.set_target(target)
@@ -328,16 +334,16 @@ def has_live_diags(lines):
328334
return True
329335
return False
330336

331-
def get_expected_no_diags_line_n(lines):
337+
def get_expected_no_diags_line_n(lines, prefix):
332338
for line in lines:
333-
if "expected-no-diagnostics" in line.content:
339+
if f"{prefix}-no-diagnostics" in line.content:
334340
return line.line_n
335341
return None
336342

337343
updated_test_files = set()
338344

339345

340-
def update_test_file(filename, diag_errors):
346+
def update_test_file(filename, diag_errors, prefix):
341347
print(f"updating test file {filename}")
342348
if filename in updated_test_files:
343349
print(
@@ -348,10 +354,10 @@ def update_test_file(filename, diag_errors):
348354
with open(filename, "r") as f:
349355
lines = [Line(line, i + 1) for i, line in enumerate(f.readlines())]
350356
orig_lines = list(lines)
351-
expected_no_diags_line_n = get_expected_no_diags_line_n(orig_lines)
357+
expected_no_diags_line_n = get_expected_no_diags_line_n(orig_lines, prefix)
352358

353359
for line in lines:
354-
diag = parse_diag(line, filename, lines)
360+
diag = parse_diag(line, filename, lines, prefix)
355361
if diag:
356362
line.diag = diag
357363
diag.set_target(lines[diag.absolute_target() - 1])
@@ -385,7 +391,7 @@ def update_test_file(filename, diag_errors):
385391
if other_diag:
386392
other_diag.increment_count()
387393
else:
388-
add_diag(line_n, diag_s, diag_category, lines, orig_lines)
394+
add_diag(line_n, diag_s, diag_category, lines, orig_lines, prefix)
389395
remove_dead_diags(lines)
390396
has_diags = has_live_diags(lines)
391397
with open(filename, "w") as f:
@@ -397,71 +403,80 @@ def update_test_file(filename, diag_errors):
397403
f.write(line.render())
398404

399405

400-
def update_test_files(errors):
406+
def update_test_files(errors, prefix):
401407
errors_by_file = {}
402408
for (filename, line, diag_s), (diag_category, seen) in errors:
403409
if filename not in errors_by_file:
404410
errors_by_file[filename] = []
405411
errors_by_file[filename].append((line, diag_s, diag_category, seen))
406412
for filename, diag_errors in errors_by_file.items():
407413
try:
408-
update_test_file(filename, diag_errors)
414+
update_test_file(filename, diag_errors, prefix)
409415
except KnownException as e:
410416
print(f"{filename} - ERROR: {e}")
411417
print("continuing...")
412418

413-
414-
curr = []
415-
curr_category = None
416-
curr_run_line = None
417-
lines_since_run = []
418-
skip_to_next_file = False
419-
for line in sys.stdin.readlines():
420-
lines_since_run.append(line)
421-
try:
422-
if line.startswith("RUN:"):
423-
if curr:
424-
update_test_files(curr)
419+
def check_expectations(tool_output, prefix):
420+
curr = []
421+
curr_category = None
422+
curr_run_line = None
423+
lines_since_run = []
424+
skip_to_next_file = False
425+
for line in tool_output:
426+
lines_since_run.append(line)
427+
try:
428+
if line.startswith("RUN:"):
429+
if curr:
430+
update_test_files(curr, prefix)
431+
curr = []
432+
lines_since_run = [line]
433+
curr_run_line = line
434+
else:
435+
for line in lines_since_run:
436+
print(line, end="")
437+
print("====================")
438+
if lines_since_run:
439+
print("no mismatching diagnostics found since last RUN line")
440+
skip_to_next_file = False
441+
continue
442+
if skip_to_next_file:
443+
continue
444+
if line.startswith("error: "):
445+
curr_category = parse_error_category(line[len("error: ") :], prefix)
446+
continue
447+
448+
diag_error = parse_diag_error(line.strip())
449+
if diag_error:
450+
curr.append((diag_error, curr_category))
451+
except KnownException as e:
452+
print(f"Error while parsing: {e}")
453+
if curr:
454+
print("skipping to next file")
425455
curr = []
426-
lines_since_run = [line]
427-
curr_run_line = line
428-
else:
429-
for line in lines_since_run:
430-
print(line, end="")
431-
print("====================")
432-
if lines_since_run:
433-
print("no mismatching diagnostics found since last RUN line")
434-
skip_to_next_file = False
435-
continue
436-
if skip_to_next_file:
437-
continue
438-
if line.startswith("error: "):
439-
curr_category = parse_error_category(line[len("error: ") :])
440-
continue
441-
442-
diag_error = parse_diag_error(line.strip())
443-
if diag_error:
444-
curr.append((diag_error, curr_category))
445-
except KnownException as e:
446-
print(f"Error while parsing: {e}")
447-
if curr:
448-
print("skipping to next file")
449-
curr = []
450-
curr_category = None
451-
curr_run_line = None
452-
lines_since_run = []
453-
skip_to_next_file = True
454-
except Exception as e:
456+
curr_category = None
457+
curr_run_line = None
458+
lines_since_run = []
459+
skip_to_next_file = True
460+
except Exception as e:
461+
for line in lines_since_run:
462+
print(line, end="")
463+
print("====================")
464+
print(e)
465+
sys.exit(1)
466+
if curr:
467+
update_test_files(curr, prefix)
468+
print("done!")
469+
else:
455470
for line in lines_since_run:
456471
print(line, end="")
457472
print("====================")
458-
print(e)
459-
sys.exit(1)
460-
if curr:
461-
update_test_files(curr)
462-
print("done!")
463-
else:
464-
for line in lines_since_run:
465-
print(line, end="")
466-
print("====================")
467-
print("no mismatching diagnostics found")
473+
print("no mismatching diagnostics found")
474+
475+
def main():
476+
parser = argparse.ArgumentParser(description=__doc__)
477+
parser.add_argument("--prefix", default="expected", help="The prefix passed to -verify")
478+
args = parser.parse_args()
479+
check_expectations(sys.stdin.readlines(), args.prefix)
480+
481+
if __name__ == "__main__":
482+
main()

0 commit comments

Comments
 (0)