diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 239280c652556..4fcc640d90716 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,33 @@ 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 const &diag) { + switch (diag->GetCompilerID()) { + // FIXME: should we also be checking + // clang::diag::err_no_member_template? + case clang::diag::err_no_template: + case clang::diag::err_non_template_in_template_id: + return true; + default: + return false; + } + })) + return; + + diagnostic_manager.AddDiagnostic( + "Naming template instantiation not yet supported. Template functions " + "can be invoked via their mangled name. For example, using " + "`_Z3fooIiEvi(123)` for `foo(123)`", + 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..74aceed1d637e 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -215,6 +215,9 @@ 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..e8287108f7583 --- /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(5)", + error=True, + substrs=[ + "does not name a template but is followed by template arguments", + "note: Naming template instantiation not yet supported.", + "Template functions can be invoked via their mangled name.", + ], + ) + + self.expect( + "expression some_template_func(5) + some_template_func(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::smethod()", + error=True, + substrs=[ + "no template named 'Foo'", + "note: Naming template instantiation not yet supported.", + "Template functions can be invoked via their mangled name.", + ], + ) 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..914d9b59484de --- /dev/null +++ b/lldb/test/API/lang/cpp/template-diagnostic-hint/main.cpp @@ -0,0 +1,14 @@ +template static K some_template_func(int x) { + return (K)x; +} + +template struct Foo { + template T method(K k) { return (T)k; } + static T smethod() { return (T)10; } +}; + +int main() { + Foo f; + return some_template_func(5) + Foo::smethod() + + f.method(10); +}