1#!/usr/bin/env python3 2 3"""Compiles a source file and checks errors against those listed in the file. 4 5Parameters: 6 sys.argv[1]: a source file with contains the input and expected output 7 sys.argv[2]: the Flang frontend driver 8 sys.argv[3:]: Optional arguments to the Flang frontend driver""" 9 10import sys 11import re 12import tempfile 13import subprocess 14import common as cm 15 16from difflib import unified_diff 17 18cm.check_args(sys.argv) 19srcdir = cm.set_source(sys.argv[1]) 20with open(srcdir, "r") as f: 21 src = f.readlines() 22actual = "" 23expect = "" 24diffs = "" 25log = "" 26 27flang_fc1 = cm.set_executable(sys.argv[2]) 28flang_fc1_args = sys.argv[3:] 29flang_fc1_options = "-fsyntax-only" 30 31# Compiles, and reads in the output from the compilation process 32cmd = [flang_fc1, *flang_fc1_args, flang_fc1_options, str(srcdir)] 33with tempfile.TemporaryDirectory() as tmpdir: 34 try: 35 proc = subprocess.run( 36 cmd, 37 stdout=subprocess.PIPE, 38 stderr=subprocess.PIPE, 39 check=True, 40 universal_newlines=True, 41 cwd=tmpdir, 42 ) 43 except subprocess.CalledProcessError as e: 44 log = e.stderr 45 if e.returncode >= 128: 46 print(f"{log}") 47 sys.exit(1) 48 49# Cleans up the output from the compilation process to be easier to process 50for line in log.split("\n"): 51 m = re.search(r"[^:]*:(\d+:).*(?:error|warning|portability|because):(.*)", line) 52 if m: 53 if re.search(r"warning: .*fold.*host", line): 54 continue # ignore host-dependent folding warnings 55 actual += m.expand(r"\1\2\n") 56 57# Gets the expected errors and their line numbers 58errors = [] 59for i, line in enumerate(src, 1): 60 m = re.search(r"(?:^\s*!\s*(?:ERROR|WARNING|PORTABILITY|BECAUSE): )(.*)", line) 61 if m: 62 errors.append(m.group(1)) 63 continue 64 if errors: 65 for x in errors: 66 expect += f"{i}: {x}\n" 67 errors = [] 68 69# Compares the expected errors with the compiler errors 70for line in unified_diff(actual.split("\n"), expect.split("\n"), n=0): 71 line = re.sub(r"(^\-)(\d+:)", r"\nactual at \g<2>", line) 72 line = re.sub(r"(^\+)(\d+:)", r"\nexpect at \g<2>", line) 73 diffs += line 74 75if diffs != "": 76 print(diffs) 77 print() 78 print("FAIL") 79 sys.exit(1) 80else: 81 print() 82 print("PASS") 83