llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Michael Buch (Michael137)

<details>
<summary>Changes</summary>

Before:
```
(lldb) expression some_template_func&lt;int, long&gt;(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&lt;int, long&gt;(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&lt;long&gt;(10)
           ˄          ˄
           │          ╰─ error: expected '(' for function-style cast or type 
construction
           ╰─ error: no member named 'method' in 'Foo&lt;int&gt;'
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

---
Full diff: https://github.com/llvm/llvm-project/pull/179916.diff


5 Files Affected:

- (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp 
(+23) 
- (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h 
(+2) 
- (added) lldb/test/API/lang/cpp/template-diagnostic-hint/Makefile (+3) 
- (added) 
lldb/test/API/lang/cpp/template-diagnostic-hint/TestTemplateDiagnosticHint.py 
(+48) 
- (added) lldb/test/API/lang/cpp/template-diagnostic-hint/main.cpp (+15) 


``````````diff
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);
+}

``````````

</details>


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

Reply via email to