https://github.com/Michael137 created 
https://github.com/llvm/llvm-project/pull/179916

Before:
```
(lldb) expression some_template_func<int, long>(5)
                  ˄
                  ╰─ error: 'some_template_func' does not name a template but 
is followed by template arguments
note: Ran expression as 'C++14'.
note: note: non-template declaration found by name lookup
```

After:
```
(lldb) expression some_template_func<int, long>(5)
                  ˄
                  ╰─ error: 'some_template_func' does not name a template but 
is followed by template arguments
note: Ran expression as 'C++14'.
note: note: non-template declaration found by name lookup
note: Naming template instantiation not yet supported. If calling a template 
function, try doing so using its mangled name. E.g., expression _Z3fooIiEvi(5)
```

There isn't a great way to get to the actual function being named (and its 
mangled name) since we're just dealing with raw text. So I just print an 
example mangled name.

This doesn't work for all template instantiations. E.g.,:
```
(lldb) p f.method<long>(10)
           ˄          ˄
           │          ╰─ error: expected '(' for function-style cast or type 
construction
           ╰─ error: no member named 'method' in 'Foo<int>'
note: Ran expression as 'C++14'.
```
This is a consequence of how we construct the AST for template methods. Once we 
fix that, this hint will get emitted there too.

Note this will also trigger in cases where no function is being called (hence I 
used the defensive phrase "If calling a template function").

rdar://135725807

>From f722dee7c6fb0fe48ba80000eea3e71d090c4508 Mon Sep 17 00:00:00 2001
From: Michael Buch <[email protected]>
Date: Thu, 5 Feb 2026 10:15:52 +0000
Subject: [PATCH] [lldb][ClangUserExpression] Emit workaround hint when trying
 to call function templates
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Before:
```
(lldb) expression some_template_func<int, long>(5)
                  ˄
                  ╰─ error: 'some_template_func' does not name a template but 
is followed by template arguments
note: Ran expression as 'C++14'.
note: note: non-template declaration found by name lookup
```

After:
```
(lldb) expression some_template_func<int, long>(5)
                  ˄
                  ╰─ error: 'some_template_func' does not name a template but 
is followed by template arguments
note: Ran expression as 'C++14'.
note: note: non-template declaration found by name lookup
note: Naming template instantiation not yet supported. If calling a template 
function, try doing so using its mangled name. E.g., expression _Z3fooIiEvi(5)
```

There isn't a great way to get to the actual function being named (and
its mangled name) since we're just dealing with raw text. So I just
print an example mangled name.

This doesn't work for all template instantiations. E.g.,:
```
(lldb) p f.method<long>(10)
           ˄          ˄
           │          ╰─ error: expected '(' for function-style cast or type 
construction
           ╰─ error: no member named 'method' in 'Foo<int>'
note: Ran expression as 'C++14'.
```
This is a consequence of how we construct the AST for template methods. Once we 
fix that, this hint will get emitted there too.

Note this will also trigger in cases where no function is being called (hence I 
used the defensive phrase "If calling a template function").

rdar://135725807
---
 .../Clang/ClangUserExpression.cpp             | 23 +++++++++
 .../Clang/ClangUserExpression.h               |  2 +
 .../cpp/template-diagnostic-hint/Makefile     |  3 ++
 .../TestTemplateDiagnosticHint.py             | 48 +++++++++++++++++++
 .../cpp/template-diagnostic-hint/main.cpp     | 15 ++++++
 5 files changed, 91 insertions(+)
 create mode 100644 lldb/test/API/lang/cpp/template-diagnostic-hint/Makefile
 create mode 100644 
lldb/test/API/lang/cpp/template-diagnostic-hint/TestTemplateDiagnosticHint.py
 create mode 100644 lldb/test/API/lang/cpp/template-diagnostic-hint/main.cpp

diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp 
b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 239280c652556..fbd622d3dc7e9 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -56,6 +56,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 
+#include "clang/Basic/DiagnosticSema.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -988,9 +989,31 @@ void ClangUserExpression::FixupCVRParseErrorDiagnostics(
       !m_fixed_text.empty() ? m_fixed_text.c_str() : m_expr_text.c_str());
 }
 
+void ClangUserExpression::FixupTemplateLookupDiagnostics(DiagnosticManager 
&diagnostic_manager) const {
+  if (llvm::none_of(
+      diagnostic_manager.Diagnostics(),
+      [](std::unique_ptr<Diagnostic> const &diag) {
+        switch (diag->GetCompilerID()) {
+        case clang::diag::err_non_template_in_template_id:
+        case clang::diag::err_no_template:
+        case clang::diag::err_no_member_template:
+          return true;
+        default:
+          return false;
+        }
+      }))
+    return;
+
+  diagnostic_manager.AddDiagnostic(
+      "Naming template instantiation not yet supported. If calling a template 
function, "
+      "try doing so using its mangled name. E.g., expression _Z3fooIiEvi(5)",
+      lldb::eSeverityInfo, eDiagnosticOriginLLDB);
+}
+
 void ClangUserExpression::FixupParseErrorDiagnostics(
     DiagnosticManager &diagnostic_manager) const {
   FixupCVRParseErrorDiagnostics(diagnostic_manager);
+  FixupTemplateLookupDiagnostics(diagnostic_manager);
 }
 
 char ClangUserExpression::ClangUserExpressionHelper::ID;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h 
b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
index fd24893b1ecdd..979d3bd8a710e 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -215,6 +215,8 @@ class ClangUserExpression : public LLVMUserExpression {
   void
   FixupCVRParseErrorDiagnostics(DiagnosticManager &diagnostic_manager) const;
 
+  void FixupTemplateLookupDiagnostics(DiagnosticManager &diagnostic_manager) 
const;
+
   /// Defines how the current expression should be wrapped.
   ClangExpressionSourceCode::WrapKind GetWrapKind() const;
   bool SetupPersistentState(DiagnosticManager &diagnostic_manager,
diff --git a/lldb/test/API/lang/cpp/template-diagnostic-hint/Makefile 
b/lldb/test/API/lang/cpp/template-diagnostic-hint/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/lang/cpp/template-diagnostic-hint/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git 
a/lldb/test/API/lang/cpp/template-diagnostic-hint/TestTemplateDiagnosticHint.py 
b/lldb/test/API/lang/cpp/template-diagnostic-hint/TestTemplateDiagnosticHint.py
new file mode 100644
index 0000000000000..dbe7b7a68d540
--- /dev/null
+++ 
b/lldb/test/API/lang/cpp/template-diagnostic-hint/TestTemplateDiagnosticHint.py
@@ -0,0 +1,48 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestCase(TestBase):
+    def test(self):
+        self.build()
+        (_, process, _, _) = lldbutil.run_to_source_breakpoint(
+            self, "main", lldb.SBFileSpec("main.cpp")
+        )
+
+        self.expect(
+            "expression some_template_func<int, long>(5)",
+            error=True,
+            substrs=[
+                "does not name a template but is followed by template 
arguments",
+                "note: Naming template instantiation not yet supported.",
+                "If calling a template function, try doing so using its 
mangled name. E.g., expression _Z3fooIiEvi(5)",
+            ],
+        )
+
+        self.expect(
+            "expression some_template_func<int, long>(5) + 
some_template_func<int, long>(5)",
+            error=True,
+            substrs=[
+                "does not name a template but is followed by template 
arguments",
+                "does not name a template but is followed by template 
arguments",
+            ],
+        )
+
+        self.assertEqual(
+            self.res.GetError().count(
+                "note: Naming template instantiation not yet supported"
+            ),
+            1,
+        )
+
+        self.expect(
+            "expression Foo<int>::smethod()",
+            error=True,
+            substrs=[
+                "no template named 'Foo'",
+                "note: Naming template instantiation not yet supported.",
+                "If calling a template function, try doing so using its 
mangled name. E.g., expression _Z3fooIiEvi(5)",
+            ],
+        )
diff --git a/lldb/test/API/lang/cpp/template-diagnostic-hint/main.cpp 
b/lldb/test/API/lang/cpp/template-diagnostic-hint/main.cpp
new file mode 100644
index 0000000000000..00e4a25d199fe
--- /dev/null
+++ b/lldb/test/API/lang/cpp/template-diagnostic-hint/main.cpp
@@ -0,0 +1,15 @@
+template <typename T, typename K> static K some_template_func(int x) {
+  return (K)x;
+}
+
+template <typename T> struct Foo {
+  template<typename K>
+  T method(K k) { return (T)k; }
+  static T smethod() { return (T)10; }
+};
+
+int main() {
+  Foo<int> f;
+  return some_template_func<int, long>(5) +
+         Foo<int>::smethod() + f.method<long>(10);
+}

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to