[clang] [llvm] improve update_cc_test_checks.py for template (PR #102505)

Yaxun Liu via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 29 18:29:27 PDT 2026


https://github.com/yxsamliu updated https://github.com/llvm/llvm-project/pull/102505

>From 51c8dc82f6eb4e77f9d2216ee4263ab08083b958 Mon Sep 17 00:00:00 2001
From: "Yaxun (Sam) Liu" <yaxun.liu at amd.com>
Date: Tue, 29 Sep 2026 21:27:12 -0400
Subject: [PATCH] [utils] Generate checks for function template instantiations

Clang's JSON AST nests instantiated functions under FunctionTemplateDecl.
Visit the mangled declarations to generate checks at the template definition.

Add a script test with two instantiations and an unused template. Check the
generated IR and verify that a second run leaves the output unchanged.
---
 .../function-template-instantiation.cpp       |  7 +++++
 ...nction-template-instantiation.cpp.expected | 26 +++++++++++++++++++
 .../function-template-instantiation.test      |  8 ++++++
 llvm/utils/update_cc_test_checks.py           |  6 +++++
 4 files changed, 47 insertions(+)
 create mode 100644 clang/test/utils/update_cc_test_checks/Inputs/function-template-instantiation.cpp
 create mode 100644 clang/test/utils/update_cc_test_checks/Inputs/function-template-instantiation.cpp.expected
 create mode 100644 clang/test/utils/update_cc_test_checks/function-template-instantiation.test

diff --git a/clang/test/utils/update_cc_test_checks/Inputs/function-template-instantiation.cpp b/clang/test/utils/update_cc_test_checks/Inputs/function-template-instantiation.cpp
new file mode 100644
index 00000000000000..24415112cc94ad
--- /dev/null
+++ b/clang/test/utils/update_cc_test_checks/Inputs/function-template-instantiation.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+template <typename T> T twice(T x) { return x + x; }
+template int twice<int>(int);
+template long twice<long>(long);
+
+template <typename T> T unused(T x) { return x; }
diff --git a/clang/test/utils/update_cc_test_checks/Inputs/function-template-instantiation.cpp.expected b/clang/test/utils/update_cc_test_checks/Inputs/function-template-instantiation.cpp.expected
new file mode 100644
index 00000000000000..efca1a14ac5fd6
--- /dev/null
+++ b/clang/test/utils/update_cc_test_checks/Inputs/function-template-instantiation.cpp.expected
@@ -0,0 +1,26 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: @_Z5twiceIiET_S0_(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X:%.*]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    ret i32 [[ADD]]
+//
+// CHECK-LABEL: @_Z5twiceIlET_S0_(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    store i64 [[X:%.*]], ptr [[X_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr [[X_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load i64, ptr [[X_ADDR]], align 8
+// CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    ret i64 [[ADD]]
+//
+template <typename T> T twice(T x) { return x + x; }
+template int twice<int>(int);
+template long twice<long>(long);
+
+template <typename T> T unused(T x) { return x; }
diff --git a/clang/test/utils/update_cc_test_checks/function-template-instantiation.test b/clang/test/utils/update_cc_test_checks/function-template-instantiation.test
new file mode 100644
index 00000000000000..a05a04102c311d
--- /dev/null
+++ b/clang/test/utils/update_cc_test_checks/function-template-instantiation.test
@@ -0,0 +1,8 @@
+## Test CHECK generation for instantiated function templates.
+
+# RUN: cp %S/Inputs/function-template-instantiation.cpp %t.cpp && %update_cc_test_checks %t.cpp
+# RUN: diff -u %S/Inputs/function-template-instantiation.cpp.expected %t.cpp
+# RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %t.cpp | FileCheck %t.cpp
+## Re-running the script must not change the generated checks.
+# RUN: %update_cc_test_checks %t.cpp
+# RUN: diff -u %S/Inputs/function-template-instantiation.cpp.expected %t.cpp
diff --git a/llvm/utils/update_cc_test_checks.py b/llvm/utils/update_cc_test_checks.py
index 97b446d5659734..16ab4741065054 100755
--- a/llvm/utils/update_cc_test_checks.py
+++ b/llvm/utils/update_cc_test_checks.py
@@ -64,6 +64,12 @@ def get_line2func_list(args, clang_args, globals_name_prefix):
     # TODO: Should we add checks for global variables being emitted?
     def parse_clang_ast_json(node, loc, search):
         node_kind = node["kind"]
+        if node_kind == "FunctionTemplateDecl":
+            # The template pattern has no mangled name; its instantiations do.
+            for inner in node.get("inner", []):
+                if inner.get("kind") == "FunctionDecl" and inner.get("mangledName"):
+                    parse_clang_ast_json(inner, node["loc"], search)
+            return
         # Recurse for the following nodes that can contain nested function decls:
         if node_kind in (
             "NamespaceDecl",



More information about the cfe-commits mailing list