diff --git a/clang/test/utils/update_cc_test_checks/Inputs/check-globals.c b/clang/test/utils/update_cc_test_checks/Inputs/check-globals.c new file mode 100644 --- /dev/null +++ b/clang/test/utils/update_cc_test_checks/Inputs/check-globals.c @@ -0,0 +1,10 @@ +// First, make sure --check-globals doesn't crash on a non-FileChecked command. +// RUN: true +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s | FileCheck %s + +void foo() { + static int i, j; +} +void bar() { + static int i, j; +} diff --git a/clang/test/utils/update_cc_test_checks/Inputs/lit.cfg.example b/clang/test/utils/update_cc_test_checks/Inputs/lit.cfg.example new file mode 100644 --- /dev/null +++ b/clang/test/utils/update_cc_test_checks/Inputs/lit.cfg.example @@ -0,0 +1,9 @@ +import lit +lit_config.load_config( + config, os.path.join(lit_config.params.get('clang_obj_root'), + "test/lit.site.cfg.py")) +config.name = 'update_cc_test_checks.py example' +config.suffixes = ['.c', '.cpp'] +config.test_format = lit.formats.ShTest(execute_external=False) +config.test_source_root = os.path.dirname(__file__) +config.test_exec_root = os.path.dirname(__file__) diff --git a/clang/test/utils/update_cc_test_checks/check-globals.test b/clang/test/utils/update_cc_test_checks/check-globals.test new file mode 100644 --- /dev/null +++ b/clang/test/utils/update_cc_test_checks/check-globals.test @@ -0,0 +1,83 @@ +RUN: rm -rf %t && mkdir %t + +# Check --check-globals in normal mode and in --include-generated-funcs mode. + +RUN: cp %S/Inputs/check-globals.c %t/norm.c +RUN: %update_cc_test_checks %t/norm.c --check-globals +RUN: FileCheck %s --input-file=%t/norm.c --match-full-lines -strict-whitespace \ +RUN: -check-prefixes=BOTH,NRM + +RUN: cp %S/Inputs/check-globals.c %t/igf.c +RUN: %update_cc_test_checks %t/igf.c --check-globals --include-generated-funcs +RUN: FileCheck %s --input-file=%t/igf.c --match-full-lines -strict-whitespace \ +RUN: -check-prefixes=BOTH,IGF + +# Check that repeating doesn't change it, such as duplicating '//.' occurrences. + +RUN: cp %t/norm.c %t/norm-again.c +RUN: %update_cc_test_checks %t/norm-again.c --check-globals +RUN: diff -u %t/norm.c %t/norm-again.c +RUN: rm %t/norm-again.c + +RUN: cp %t/igf.c %t/igf-again.c +RUN: %update_cc_test_checks %t/igf-again.c --check-globals \ +RUN: --include-generated-funcs +RUN: diff -u %t/igf.c %t/igf-again.c +RUN: rm %t/igf-again.c + +# Check that the generated directives actually work correctly. For example, +# they're not in the wrong order. + +RUN: cp %S/Inputs/lit.cfg.example %t/lit.cfg +# Show lit failures while avoiding confusing FileCheck input dump nesting. +RUN: %lit %t +# Lit was successful. Sanity-check the results. +RUN: %lit %t 2>&1 | FileCheck -check-prefix=LIT-RUN %s + +END. + + BOTH-NOT:{{.}} + NRM:// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals + IGF:// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --include-generated-funcs + BOTH-NEXT:// {{.*}} + BOTH-NEXT:// RUN: true + BOTH-NEXT:// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s | FileCheck %s +BOTH-EMPTY: + IGF-NEXT:void foo() { + IGF-NEXT: static int i, j; + IGF-NEXT:} + IGF-NEXT:void bar() { + IGF-NEXT: static int i, j; + IGF-NEXT:} + BOTH-NEXT://. + BOTH-NEXT:// CHECK: @foo.i = internal global i32 0, align 4 + BOTH-NEXT:// CHECK: @foo.j = internal global i32 0, align 4 + BOTH-NEXT:// CHECK: @bar.i = internal global i32 0, align 4 + BOTH-NEXT:// CHECK: @bar.j = internal global i32 0, align 4 + BOTH-NEXT://. + BOTH-NEXT:// CHECK-LABEL: @foo( + BOTH-NEXT:// CHECK-NEXT: entry: + BOTH-NEXT:// CHECK-NEXT: ret void + BOTH-NEXT:// + NRM-NEXT:void foo() { + NRM-NEXT: static int i, j; + NRM-NEXT:} + IGF-NEXT:// + BOTH-NEXT:// CHECK-LABEL: @bar( + BOTH-NEXT:// CHECK-NEXT: entry: + BOTH-NEXT:// CHECK-NEXT: ret void + BOTH-NEXT:// + NRM-NEXT:void bar() { + NRM-NEXT: static int i, j; + NRM-NEXT:} + BOTH-NEXT://. + BOTH-NEXT:// CHECK: attributes {{.*}} + BOTH-NEXT://. + BOTH-NEXT:// CHECK: !0 = {{.*}} + BOTH-NEXT:// CHECK: !1 = {{.*}} + BOTH-NEXT://. + BOTH-NOT:{{.}} + +LIT-RUN: Testing: 2 tests +LIT-RUN: PASS: {{.*}} igf.c +LIT-RUN: PASS: {{.*}} norm.c diff --git a/clang/test/utils/update_cc_test_checks/lit.local.cfg b/clang/test/utils/update_cc_test_checks/lit.local.cfg --- a/clang/test/utils/update_cc_test_checks/lit.local.cfg +++ b/clang/test/utils/update_cc_test_checks/lit.local.cfg @@ -19,9 +19,13 @@ script_path = os.path.join(config.llvm_src_root, 'utils', 'update_cc_test_checks.py') assert os.path.isfile(script_path) +lit = shell_quote(os.path.join(config.llvm_src_root, 'utils', 'lit', 'lit.py')) +python = shell_quote(config.python_executable) config.substitutions.append( ('%update_cc_test_checks', "%s %s %s" % ( - shell_quote(config.python_executable), shell_quote(script_path), - extra_args))) + python, shell_quote(script_path), extra_args))) config.substitutions.append( ('%clang_tools_dir', shell_quote(config.clang_tools_dir))) +config.substitutions.append( + ('%lit', "%s %s -Dclang_obj_root=%s -j1 -vv" % ( + python, lit, shell_quote(config.clang_obj_root)))) diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -780,6 +780,8 @@ for p in prefix_list: global_vars_seen = {} checkprefixes = p[0] + if checkprefixes is None: + continue for checkprefix in checkprefixes: if checkprefix in global_vars_seen_dict: global_vars_seen.update(global_vars_seen_dict[checkprefix]) diff --git a/llvm/utils/update_cc_test_checks.py b/llvm/utils/update_cc_test_checks.py --- a/llvm/utils/update_cc_test_checks.py +++ b/llvm/utils/update_cc_test_checks.py @@ -147,6 +147,8 @@ help='Keep function signature information around for the check line') parser.add_argument('--check-attributes', action='store_true', help='Check "Function Attributes" for functions') + parser.add_argument('--check-globals', action='store_true', + help='Check global entries (global variables, metadata, attribute sets, ...) for functions') parser.add_argument('tests', nargs='+') args = common.parse_commandline_args(parser) infer_dependent_args(args) @@ -301,6 +303,7 @@ global_vars_seen_dict = {} prefix_set = set([prefix for p in filecheck_run_list for prefix in p[0]]) output_lines = [] + has_checked_pre_function_globals = False include_generated_funcs = common.find_arg_in_test(ti, lambda args: ti.args.include_generated_funcs, @@ -333,6 +336,10 @@ prefixes, func_dict, func) + if ti.args.check_globals: + common.add_global_checks(builder.global_var_dict(), '//', run_list, + output_lines, global_vars_seen_dict, True, + True) common.add_checks_at_end(output_lines, filecheck_run_list, builder.func_order(), '//', lambda my_output_lines, prefixes, func: check_generator(my_output_lines, @@ -347,6 +354,9 @@ m = common.CHECK_RE.match(line) if m and m.group(1) in prefix_set: continue # Don't append the existing CHECK lines + # Skip special separator comments added by commmon.add_global_checks. + if line.strip() == '//' + common.SEPARATOR: + continue if idx in line2spell_and_mangled_list: added = set() for spell, mangled in line2spell_and_mangled_list[idx]: @@ -364,6 +374,11 @@ # line as part of common.add_ir_checks() output_lines.pop() last_line = output_lines[-1].strip() + if ti.args.check_globals and not has_checked_pre_function_globals: + common.add_global_checks(builder.global_var_dict(), '//', + run_list, output_lines, + global_vars_seen_dict, True, True) + has_checked_pre_function_globals = True if added: output_lines.append('//') added.add(mangled) @@ -375,6 +390,9 @@ if include_line: output_lines.append(line.rstrip('\n')) + if ti.args.check_globals: + common.add_global_checks(builder.global_var_dict(), '//', run_list, + output_lines, global_vars_seen_dict, True, False) common.debug('Writing %d lines to %s...' % (len(output_lines), ti.path)) with open(ti.path, 'wb') as f: f.writelines(['{}\n'.format(l).encode('utf-8') for l in output_lines])