Skip to content

Commit b99945f

Browse files
committed
[utils] handle diagnostics from unparsed files
Don't try to add expected lines in files that aren't parsed for them - it will just lead to duplicated expected lines if run over and over. Because we don't know whether the right choice is to add -verify-additional-file or -verify-ignore-unrelated, we do nothing.
1 parent 0af8eb5 commit b99945f

File tree

2 files changed

+101
-24
lines changed

2 files changed

+101
-24
lines changed

test/Utils/update-verify-tests/expansion.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
// RUN: %target-swift-frontend-verify -load-plugin-library %t/%target-library-name(UnstringifyMacroDefinition) -typecheck %t/nested.swift
4040
// RUN: %diff %t/nested.swift %t/nested.swift.expected
4141

42+
// RUN: not %target-swift-frontend-verify -I %t -plugin-path %swift-plugin-dir -typecheck %t/unparsed.swift 2>%t/output.txt -Rmacro-expansions
43+
// RUN: not %update-verify-tests < %t/output.txt | %FileCheck --check-prefix CHECK-UNPARSED %s
44+
4245
//--- single.swift
4346
@attached(peer, names: overloaded)
4447
macro unstringifyPeer(_ s: String) =
@@ -238,3 +241,22 @@ func bar(_ y: Int) {
238241
// }}
239242
func bar() {}
240243

244+
//--- unparsed.h
245+
// CHECK-UNPARSED: no files updated: found diagnostics in unparsed files TMP_DIR/unparsed.h
246+
void foo(int len, int *p) __attribute__((swift_attr("@_SwiftifyImport(.countedBy(pointer: .param(2), count: \"len\"))")));
247+
248+
//--- module.modulemap
249+
module UnparsedClang {
250+
header "unparsed.h"
251+
export *
252+
}
253+
254+
//--- unparsed.swift
255+
import UnparsedClang
256+
257+
func bar() {
258+
let a: CInt = 1
259+
var b: CInt = 13
260+
foo(a, &b)
261+
}
262+

utils/update_verify_tests/core.py

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@ def relative_target(self):
118118

119119
def col(self):
120120
# expected-expansion requires column. Otherwise only retain column info if it's already there.
121-
if self._col and (self.category == "expansion" or self.is_from_source_file):
121+
if self._col and (
122+
self.category == "expansion" or self.is_from_source_file
123+
):
122124
return self._col
123125
return None
124126

@@ -296,7 +298,11 @@ def infer_line_context(target, line_n):
296298
)
297299
reverse = (
298300
True
299-
if [other for other in target.targeting_diags if other.relative_target() < 0]
301+
if [
302+
other
303+
for other in target.targeting_diags
304+
if other.relative_target() < 0
305+
]
300306
else False
301307
)
302308

@@ -446,7 +452,10 @@ def error_refers_to_diag(diag_error, diag, target_line_n):
446452
return (
447453
target_line_n == diag.absolute_target()
448454
and diag_error.category == diag.category
449-
and (diag.category == "expansion" or diag_error.content == diag.diag_content)
455+
and (
456+
diag.category == "expansion"
457+
or diag_error.content == diag.diag_content
458+
)
450459
)
451460

452461

@@ -468,7 +477,9 @@ def find_other_targeting(lines, orig_lines, is_nested, diag_error):
468477
return other_diags
469478

470479

471-
def update_lines(diag_errors, lines, orig_lines, prefix, filename, nested_context):
480+
def update_lines(
481+
diag_errors, lines, orig_lines, prefix, filename, nested_context
482+
):
472483
for diag_error in diag_errors:
473484
if not isinstance(diag_error, NotFoundDiag):
474485
continue
@@ -511,10 +522,13 @@ def update_lines(diag_errors, lines, orig_lines, prefix, filename, nested_contex
511522
if isinstance(diag_error, NestedDiag):
512523
if not diag.closer:
513524
whitespace = (
514-
diag.whitespace_strings[0] if diag.whitespace_strings else " "
525+
diag.whitespace_strings[0]
526+
if diag.whitespace_strings
527+
else " "
515528
)
516529
diag.closer = Line(
517-
get_indent(diag.line.content) + "//" + whitespace + "}}\n", None
530+
get_indent(diag.line.content) + "//" + whitespace + "}}\n",
531+
None,
518532
)
519533
update_lines(
520534
[diag_error.nested],
@@ -533,12 +547,14 @@ def update_test_file(filename, diag_errors, prefix, updated_test_files):
533547
else:
534548
updated_test_files.add(filename)
535549
with open(filename, "r") as f:
536-
lines = [Line(line, i + 1) for i, line in enumerate(f.readlines() + [""])]
550+
lines = [
551+
Line(line, i + 1) for i, line in enumerate(f.readlines() + [""])
552+
]
537553
orig_lines = list(lines)
538554

539555
expansion_context = []
540556
for line in lines:
541-
dprint(f"parsing line {line}")
557+
dprint(f"parsing line {line.render()}")
542558
diag = parse_diag(line, filename, prefix)
543559
if diag:
544560
dprint(f" parsed diag {diag.render()}")
@@ -563,7 +579,7 @@ def update_test_file(filename, diag_errors, prefix, updated_test_files):
563579
f.write(line.render())
564580

565581

566-
def update_test_files(errors, prefix):
582+
def update_test_files(errors, prefix, unparsed_files):
567583
errors_by_file = {}
568584
for error in errors:
569585
filename = error.file
@@ -572,6 +588,8 @@ def update_test_files(errors, prefix):
572588
errors_by_file[filename].append(error)
573589
updated_test_files = set()
574590
for filename, diag_errors in errors_by_file.items():
591+
if filename in unparsed_files:
592+
continue
575593
try:
576594
update_test_file(filename, diag_errors, prefix, updated_test_files)
577595
except KnownException as e:
@@ -580,7 +598,12 @@ def update_test_files(errors, prefix):
580598
None,
581599
)
582600
updated_files = list(updated_test_files)
583-
assert updated_files
601+
assert updated_files or unparsed_files
602+
if not updated_files:
603+
return (
604+
f"no files updated: found diagnostics in unparsed files {', '.join(unparsed_files)}",
605+
None,
606+
)
584607
return (None, updated_files)
585608

586609

@@ -590,7 +613,9 @@ def update_test_files(errors, prefix):
590613
// expected-error@+1{{asdf}}
591614
~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
592615
"""
593-
diag_error_re = re.compile(r"(\S+):(\d+):(\d+): error: expected (\S+) not produced")
616+
diag_error_re = re.compile(
617+
r"(\S+):(\d+):(\d+): error: expected (\S+) not produced"
618+
)
594619

595620

596621
"""
@@ -611,7 +636,9 @@ def update_test_files(errors, prefix):
611636
^~~~
612637
cannot find 'bar' in scope
613638
"""
614-
diag_error_re3 = re.compile(r"(\S+):(\d+):(\d+): error: incorrect message found")
639+
diag_error_re3 = re.compile(
640+
r"(\S+):(\d+):(\d+): error: incorrect message found"
641+
)
615642

616643

617644
"""
@@ -621,15 +648,29 @@ def update_test_files(errors, prefix):
621648
^~~~~~~
622649
error
623650
"""
624-
diag_error_re4 = re.compile(r"(\S+):(\d+):(\d+): error: expected (\S+), not (\S+)")
651+
diag_error_re4 = re.compile(
652+
r"(\S+):(\d+):(\d+): error: expected (\S+), not (\S+)"
653+
)
625654

626655
"""
627656
ex:
628657
test.swift:12:14: note: in expansion from here
629658
func foo() {}
630659
^
631660
"""
632-
diag_expansion_note_re = re.compile(r"(\S+):(\d+):(\d+): note: in expansion from here")
661+
diag_expansion_note_re = re.compile(
662+
r"(\S+):(\d+):(\d+): note: in expansion from here"
663+
)
664+
665+
"""
666+
ex:
667+
test.h:8:52: note: file 'test.h' is not parsed for 'expected' statements. Use '-verify-additional-file test.h' to enable, or '-verify-ignore-unrelated' to ignore diagnostics in this file
668+
void foo(int len, int * __counted_by(len) p);
669+
^
670+
"""
671+
diag_not_parsed_note_re = re.compile(
672+
r"(\S+):(\d+):(\d+): note: file '(\S+)' is not parsed for 'expected' statements"
673+
)
633674

634675

635676
class NotFoundDiag:
@@ -682,20 +723,31 @@ def check_expectations(tool_output, prefix):
682723
Called by the stand-alone update-verify-tests.py as well as litplugin.py.
683724
"""
684725
top_level = []
726+
unparsed_files = set()
685727
try:
686728
i = 0
687729
while i < len(tool_output):
688730
line = tool_output[i].strip()
689731
extra_lines = []
690732

691733
curr = []
734+
dprint(f"line: {line.strip()}")
692735
if not "error:" in line:
693-
dprint(f"ignored line: {line.strip()}")
694-
if m := diag_expansion_note_re.match(line.strip()):
695-
raise KnownException(f"unexpected 'nested' note found without preceding diagnostic: '{line.strip()}'")
736+
if "note:" in line:
737+
if m := diag_not_parsed_note_re.match(line.strip()):
738+
dprint(f"unparsed file: {m.group(4)}")
739+
unparsed_files.add(m.group(4))
740+
extra_lines = tool_output[i + 1 : i + 3]
741+
dprint(f"extra lines: {extra_lines}")
742+
else:
743+
raise KnownException(
744+
f"unhandled note found (line {i+1}): '{line.strip()}'"
745+
)
746+
else:
747+
dprint(f"ignored line: {line.strip()}")
696748
elif m := diag_error_re.match(line):
697749
dprint(f"diag not found: {line.strip()}")
698-
extra_lines = tool_output[i+1:i+3]
750+
extra_lines = tool_output[i + 1 : i + 3]
699751
dprint(f"extra lines: {extra_lines}")
700752
diag = parse_diag(
701753
Line(extra_lines[0], int(m.group(2))), m.group(1), prefix
@@ -712,7 +764,7 @@ def check_expectations(tool_output, prefix):
712764
)
713765
elif m := diag_error_re2.match(line):
714766
dprint(f"unexpected diag: {line.strip()}")
715-
extra_lines = tool_output[i+1:i+3]
767+
extra_lines = tool_output[i + 1 : i + 3]
716768
dprint(f"extra lines: {extra_lines}")
717769
curr.append(
718770
ExtraDiag(
@@ -730,7 +782,7 @@ def check_expectations(tool_output, prefix):
730782
# if only one diagnostic is emitted on that line, and the content of that diagnostic is actually 'bar'.
731783
elif m := diag_error_re3.match(line):
732784
dprint(f"wrong diag message: {line.strip()}")
733-
extra_lines = tool_output[i+1:i+4]
785+
extra_lines = tool_output[i + 1 : i + 4]
734786
dprint(f"extra lines: {extra_lines}")
735787
diag = parse_diag(
736788
Line(extra_lines[0], int(m.group(2))), m.group(1), prefix
@@ -757,7 +809,7 @@ def check_expectations(tool_output, prefix):
757809
)
758810
elif m := diag_error_re4.match(line):
759811
dprint(f"wrong diag kind: {line.strip()}")
760-
extra_lines = tool_output[i+1:i+4]
812+
extra_lines = tool_output[i + 1 : i + 4]
761813
dprint(f"extra lines: {extra_lines}")
762814
diag = parse_diag(
763815
Line(extra_lines[0], int(m.group(2))), m.group(1), prefix
@@ -793,7 +845,7 @@ def check_expectations(tool_output, prefix):
793845
and i < len(tool_output)
794846
and (m := diag_expansion_note_re.match(tool_output[i].strip()))
795847
):
796-
nested_note_lines = tool_output[i:i+3]
848+
nested_note_lines = tool_output[i : i + 3]
797849
dprint(f"nested note lines: {nested_note_lines}")
798850
curr = [
799851
NestedDiag(m.group(1), int(m.group(2)), int(m.group(3)), e)
@@ -803,8 +855,11 @@ def check_expectations(tool_output, prefix):
803855
top_level.extend(curr)
804856

805857
except KnownException as e:
806-
return (f"Error in update-verify-tests while parsing tool output: {e}", None)
858+
return (
859+
f"Error in update-verify-tests while parsing tool output: {e}",
860+
None,
861+
)
807862
if top_level:
808-
return update_test_files(top_level, prefix)
863+
return update_test_files(top_level, prefix, unparsed_files)
809864
else:
810865
return ("no mismatching diagnostics found", None)

0 commit comments

Comments
 (0)