diff --git a/clang/test/utils/update_cc_test_checks/Inputs/resolve-tmp-conflict.cpp b/clang/test/utils/update_cc_test_checks/Inputs/resolve-tmp-conflict.cpp new file mode 100644 --- /dev/null +++ b/clang/test/utils/update_cc_test_checks/Inputs/resolve-tmp-conflict.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s + +void foo(int a) { + int &tmp0 = a; + int &&tmp1 = 1; + tmp1 = a; + return; +} diff --git a/clang/test/utils/update_cc_test_checks/Inputs/resolve-tmp-conflict.cpp.expected b/clang/test/utils/update_cc_test_checks/Inputs/resolve-tmp-conflict.cpp.expected new file mode 100644 --- /dev/null +++ b/clang/test/utils/update_cc_test_checks/Inputs/resolve-tmp-conflict.cpp.expected @@ -0,0 +1,25 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --prefix-filecheck-ir-name _ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s + +// CHECK-LABEL: define {{[^@]+}}@_Z3fooi +// CHECK-SAME: (i32 [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[_TMP0:%.*]] = alloca i32*, align 8 +// CHECK-NEXT: [[_TMP1:%.*]] = alloca i32*, align 8 +// CHECK-NEXT: [[REF_TMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4 +// CHECK-NEXT: store i32* [[A_ADDR]], i32** [[_TMP0]], align 8 +// CHECK-NEXT: store i32 1, i32* [[REF_TMP]], align 4 +// CHECK-NEXT: store i32* [[REF_TMP]], i32** [[_TMP1]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32*, i32** [[_TMP1]], align 8 +// CHECK-NEXT: store i32 [[TMP0]], i32* [[TMP1]], align 4 +// CHECK-NEXT: ret void +// +void foo(int a) { + int &tmp0 = a; + int &&tmp1 = 1; + tmp1 = a; + return; +} diff --git a/clang/test/utils/update_cc_test_checks/resolve-tmp-conflict.test b/clang/test/utils/update_cc_test_checks/resolve-tmp-conflict.test new file mode 100644 --- /dev/null +++ b/clang/test/utils/update_cc_test_checks/resolve-tmp-conflict.test @@ -0,0 +1,8 @@ +## Test that CHECK lines generated avoid naming conflicts with FileCheck IR variables + +# RUN: cp %S/Inputs/resolve-tmp-conflict.cpp %t.cpp && %update_cc_test_checks --function-signature --prefix-filecheck-ir-name _ %t.cpp +# RUN: diff -u %S/Inputs/resolve-tmp-conflict.cpp.expected %t.cpp + +## Check that re-running update_cc_test_checks doesn't change the output +# RUN: %update_cc_test_checks %t.cpp +# RUN: diff -u %S/Inputs/resolve-tmp-conflict.cpp.expected %t.cpp 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 @@ -16,6 +16,7 @@ _verbose = False +_prefix_filecheck_ir_name = '' def parse_commandline_args(parser): parser.add_argument('--include-generated-funcs', action='store_true', @@ -32,6 +33,8 @@ help='Deactivate CHECK line generation from this point forward') parser.add_argument('--replace-function-regex', nargs='+', default=[], help='List of regular expressions to replace matching function names') + parser.add_argument('--prefix-filecheck-ir-name', default='', + help='Add a prefix to FileCheck IR value names to avoid conflicts with scripted names') args = parser.parse_args() global _verbose _verbose = args.verbose @@ -53,6 +56,9 @@ self.argparse_callback = argparse_callback self.path = test self.args = args + if args.prefix_filecheck_ir_name: + global _prefix_filecheck_ir_name + _prefix_filecheck_ir_name = args.prefix_filecheck_ir_name self.argv = argv self.input_lines = input_lines self.run_lines = find_run_lines(test, self.input_lines) @@ -512,11 +518,21 @@ def is_global_scope_ir_value_match(match): return nameless_values[get_idx_from_ir_value_match(match)].global_ir_prefix is not None +# Return true if var clashes with the scripted FileCheck check_prefix. +def may_clash_with_default_check_prefix_name(check_prefix, var): + return check_prefix and re.match(r'^' + check_prefix + r'[0-9]+?$', var, re.IGNORECASE) + # Create a FileCheck variable name based on an IR name. def get_value_name(var, check_prefix): var = var.replace('!', '') + # This is a nameless value, prepend check_prefix. if var.isdigit(): var = check_prefix + var + else: + # This is a named value that clashes with the check_prefix, prepend with _prefix_filecheck_ir_name, + # if it has been defined. + if may_clash_with_default_check_prefix_name(check_prefix, var) and _prefix_filecheck_ir_name: + var = _prefix_filecheck_ir_name + var var = var.replace('.', '_') var = var.replace('-', '_') return var.upper() @@ -546,8 +562,9 @@ pre, check = get_ir_prefix_from_ir_value_match(match) var = get_name_from_ir_value_match(match) for nameless_value in nameless_values: - if nameless_value.check_prefix and re.match(r'^' + nameless_value.check_prefix + r'[0-9]+?$', var, re.IGNORECASE): - warn("Change IR value name '%s' to prevent possible conflict with scripted FileCheck name." % (var,)) + if may_clash_with_default_check_prefix_name(nameless_value.check_prefix, var): + warn("Change IR value name '%s' or use -prefix-ir-filecheck-name to prevent possible conflict" + " with scripted FileCheck name." % (var,)) key = (var, get_check_key_from_ir_value_match(match)) is_local_def = is_local_def_ir_value_match(match) if is_local_def and key in vars_seen: