16c1ac141SIvan Zhechev#!/usr/bin/env python3 26c1ac141SIvan Zhechev 36c1ac141SIvan Zhechev"""Compiles a source file and checks errors against those listed in the file. 46c1ac141SIvan Zhechev 56c1ac141SIvan ZhechevParameters: 66c1ac141SIvan Zhechev sys.argv[1]: a source file with contains the input and expected output 76c1ac141SIvan Zhechev sys.argv[2]: the Flang frontend driver 86c1ac141SIvan Zhechev sys.argv[3:]: Optional arguments to the Flang frontend driver""" 96c1ac141SIvan Zhechev 106c1ac141SIvan Zhechevimport sys 116c1ac141SIvan Zhechevimport re 126c1ac141SIvan Zhechevimport tempfile 136c1ac141SIvan Zhechevimport subprocess 146c1ac141SIvan Zhechevimport common as cm 156c1ac141SIvan Zhechev 166c1ac141SIvan Zhechevfrom difflib import unified_diff 176c1ac141SIvan Zhechev 186c1ac141SIvan Zhechevcm.check_args(sys.argv) 196c1ac141SIvan Zhechevsrcdir = cm.set_source(sys.argv[1]) 20*f98ee40fSTobias Hietawith open(srcdir, "r") as f: 216c1ac141SIvan Zhechev src = f.readlines() 226c1ac141SIvan Zhechevactual = "" 236c1ac141SIvan Zhechevexpect = "" 246c1ac141SIvan Zhechevdiffs = "" 256c1ac141SIvan Zhechevlog = "" 266c1ac141SIvan Zhechev 276c1ac141SIvan Zhechevflang_fc1 = cm.set_executable(sys.argv[2]) 286c1ac141SIvan Zhechevflang_fc1_args = sys.argv[3:] 296c1ac141SIvan Zhechevflang_fc1_options = "-fsyntax-only" 306c1ac141SIvan Zhechev 316c1ac141SIvan Zhechev# Compiles, and reads in the output from the compilation process 326c1ac141SIvan Zhechevcmd = [flang_fc1, *flang_fc1_args, flang_fc1_options, str(srcdir)] 336c1ac141SIvan Zhechevwith tempfile.TemporaryDirectory() as tmpdir: 346c1ac141SIvan Zhechev try: 35*f98ee40fSTobias Hieta proc = subprocess.run( 36*f98ee40fSTobias Hieta cmd, 37*f98ee40fSTobias Hieta stdout=subprocess.PIPE, 38*f98ee40fSTobias Hieta stderr=subprocess.PIPE, 39*f98ee40fSTobias Hieta check=True, 40*f98ee40fSTobias Hieta universal_newlines=True, 41*f98ee40fSTobias Hieta cwd=tmpdir, 42*f98ee40fSTobias Hieta ) 436c1ac141SIvan Zhechev except subprocess.CalledProcessError as e: 446c1ac141SIvan Zhechev log = e.stderr 456c1ac141SIvan Zhechev if e.returncode >= 128: 466c1ac141SIvan Zhechev print(f"{log}") 476c1ac141SIvan Zhechev sys.exit(1) 486c1ac141SIvan Zhechev 496c1ac141SIvan Zhechev# Cleans up the output from the compilation process to be easier to process 50*f98ee40fSTobias Hietafor line in log.split("\n"): 51502e7690SPeter Klausler m = re.search(r"[^:]*:(\d+:).*(?:error|warning|portability|because):(.*)", line) 526c1ac141SIvan Zhechev if m: 53502e7690SPeter Klausler if re.search(r"warning: .*fold.*host", line): 54502e7690SPeter Klausler continue # ignore host-dependent folding warnings 556c1ac141SIvan Zhechev actual += m.expand(r"\1\2\n") 566c1ac141SIvan Zhechev 57502e7690SPeter Klausler# Gets the expected errors and their line numbers 586c1ac141SIvan Zhecheverrors = [] 596c1ac141SIvan Zhechevfor i, line in enumerate(src, 1): 60502e7690SPeter Klausler m = re.search(r"(?:^\s*!\s*(?:ERROR|WARNING|PORTABILITY|BECAUSE): )(.*)", line) 616c1ac141SIvan Zhechev if m: 626c1ac141SIvan Zhechev errors.append(m.group(1)) 636c1ac141SIvan Zhechev continue 646c1ac141SIvan Zhechev if errors: 656c1ac141SIvan Zhechev for x in errors: 666c1ac141SIvan Zhechev expect += f"{i}: {x}\n" 676c1ac141SIvan Zhechev errors = [] 686c1ac141SIvan Zhechev 696c1ac141SIvan Zhechev# Compares the expected errors with the compiler errors 706c1ac141SIvan Zhechevfor line in unified_diff(actual.split("\n"), expect.split("\n"), n=0): 716c1ac141SIvan Zhechev line = re.sub(r"(^\-)(\d+:)", r"\nactual at \g<2>", line) 726c1ac141SIvan Zhechev line = re.sub(r"(^\+)(\d+:)", r"\nexpect at \g<2>", line) 736c1ac141SIvan Zhechev diffs += line 746c1ac141SIvan Zhechev 756c1ac141SIvan Zhechevif diffs != "": 766c1ac141SIvan Zhechev print(diffs) 776c1ac141SIvan Zhechev print() 786c1ac141SIvan Zhechev print("FAIL") 796c1ac141SIvan Zhechev sys.exit(1) 806c1ac141SIvan Zhechevelse: 816c1ac141SIvan Zhechev print() 826c1ac141SIvan Zhechev print("PASS") 83