Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -35,6 +35,8 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" +#include "llvm/Demangle/Demangle.h" + #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -1167,12 +1169,24 @@ } if (!function_decl) { + const char *name = attrs.name.GetCString(); + + // We currently generate function templates with template parameters in + // their name. In order to get closer to the AST that clang generates + // we want to strip these from the name when creating the AST. + if (attrs.mangled_name) { + llvm::ItaniumPartialDemangler D; + D.partialDemangle(attrs.mangled_name); + size_t Size = 1; + + name = D.getFunctionBaseName(nullptr, &Size); + } + // We just have a function that isn't part of a class function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, - attrs.name.GetCString(), clang_type, attrs.storage, - attrs.is_inline); + name, clang_type, attrs.storage, attrs.is_inline); if (has_template_params) { TypeSystemClang::TemplateParameterInfos template_param_infos; @@ -1180,14 +1194,14 @@ template_function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, - attrs.name.GetCString(), clang_type, attrs.storage, - attrs.is_inline); + name, clang_type, attrs.storage, attrs.is_inline); + clang::FunctionTemplateDecl *func_template_decl = - m_ast.CreateFunctionTemplateDecl( - containing_decl_ctx, template_function_decl, - attrs.name.GetCString(), template_param_infos); + m_ast.CreateFunctionTemplateDecl(containing_decl_ctx, + template_function_decl, name, + template_param_infos); m_ast.CreateFunctionTemplateSpecializationInfo( - function_decl, func_template_decl, template_param_infos); + template_function_decl, func_template_decl, template_param_infos); } lldbassert(function_decl); Index: lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py =================================================================== --- lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py +++ lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py @@ -13,14 +13,39 @@ def do_test_template_function(self, add_cast): self.build() - (_, _, thread, _) = lldbutil.run_to_name_breakpoint(self, "main") - frame = thread.GetSelectedFrame() - expr = "foo(42)" + (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + if add_cast: - expr = "(int)" + expr - expr_result = frame.EvaluateExpression(expr) - self.assertTrue(expr_result.IsValid()) - self.assertEqual(expr_result.GetValue(), "42") + self.expect_expr("(int) foo(42)", result_type="int", result_value="42") + else: + self.expect_expr("foo(42)", result_type="int", result_value="42") + + self.expect_expr("h(10)", result_type="int", result_value="10") + + self.expect_expr("f(A::C{})", result_type="int", result_value="4") + + self.expect_expr("g(A::C{})", result_type="int", result_value="4") + + self.expect_expr("var(1)", result_type="int", result_value="10") + + self.expect_expr("var(1,2)", result_type="int", result_value="10") + + self.expect_expr("b1 > b2", result_type="bool", result_value="true") + + self.expect_expr("b1 >> b2", result_type="bool", result_value="true") + + self.expect_expr("b1 << b2", result_type="bool", result_value="true") + + self.expect_expr("b1 == b2", result_type="bool", result_value="true") + + self.expect_expr("c1 > c2", result_type="bool", result_value="true") + + self.expect_expr("c1 >> c2", result_type="bool", result_value="true") + + self.expect_expr("c1 << c2", result_type="bool", result_value="true") + + self.expect_expr("c1 == c2", result_type="bool", result_value="true") @skipIfWindows def test_template_function_with_cast(self): Index: lldb/test/API/lang/cpp/template-function/main.cpp =================================================================== --- lldb/test/API/lang/cpp/template-function/main.cpp +++ lldb/test/API/lang/cpp/template-function/main.cpp @@ -3,6 +3,67 @@ return int(t1); } +// Some cases to cover ADL +namespace A { +struct C {}; + +template int f(T) { return 4; } + +template int g(T) { return 4; } +} // namespace A + +int f(int) { return 1; } + +template int h(T x) { return x; } + +int h(double d) { return 5; } + +template int var(Us... pargs) { return 10; } + +// Having the templated overloaded operators in a namespace effects the +// mangled name generated in the IR e.g. _ZltRK1BS1_ Vs _ZN1AltERKNS_1BES2_ +// One will be in the symbol table but the other won't. This results in a +// different code path that will result in CPlusPlusNameParser being used. +// This allows us to cover that code as well. +namespace A { +template bool operator<(const T &, const T &) { return true; } + +template bool operator>(const T &, const T &) { return true; } + +template bool operator<<(const T &, const T &) { return true; } + +template bool operator>>(const T &, const T &) { return true; } + +template bool operator==(const T &, const T &) { return true; } + +struct B {}; +} // namespace A + +struct C {}; + +// Make sure we cover more straight forward cases as well. +bool operator<(const C &, const C &) { return true; } +bool operator>(const C &, const C &) { return true; } +bool operator>>(const C &, const C &) { return true; } +bool operator<<(const C &, const C &) { return true; } +bool operator==(const C &, const C &) { return true; } + int main() { - return foo(42); + A::B b1; + A::B b2; + C c1; + C c2; + + bool result_b = b1 < b2 && b1 << b2 && b1 == b2 && b1 > b2 && b1 >> b2; + bool result_c = c1 < c2 && c1 << c2 && c1 == c2 && c1 > c2 && c1 >> c2; + + return foo(42) + result_b + result_c + + // ADL lookup case, + f(A::C{}) + + // ADL lookup but no overload + g(A::C{}) + + // overload with template + h(10) + h(1.) + + // variadic function + var(1) + var(1, 2); // break here }