Index: lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp =================================================================== --- lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp +++ lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp @@ -36,7 +36,15 @@ }; int Class::ClassStatic = 7; -void foo() { Class::StaticFunc(Class(Enum_0)); } +template +struct Template { + template + void TemplateFunc() { + T::StaticFunc(T(E)); + } +}; + +void foo() { Template().TemplateFunc(); } } // namespace N1 } // namespace N0 Index: lit/SymbolFile/PDB/ast-restore.test =================================================================== --- lit/SymbolFile/PDB/ast-restore.test +++ lit/SymbolFile/PDB/ast-restore.test @@ -6,6 +6,7 @@ RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=BASE %s RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=CLASS %s RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=INNER %s +RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=TEMPLATE %s RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=FOO %s RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=MAIN %s @@ -66,6 +67,11 @@ INNER: } INNER: } +TEMPLATE: Module: {{.*}} +TEMPLATE: struct Template { +TEMPLATE: inline void TemplateFunc<1>(); +TEMPLATE: }; + FOO: Module: {{.*}} FOO: namespace N0 { FOO: namespace N1 { Index: source/Plugins/Language/CPlusPlus/CMakeLists.txt =================================================================== --- source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -18,6 +18,7 @@ LibStdcpp.cpp LibStdcppTuple.cpp LibStdcppUniquePointer.cpp + MSVCUndecoratedNameParser.cpp LINK_LIBS lldbCore Index: source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp =================================================================== --- source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -41,6 +41,7 @@ #include "LibCxxAtomic.h" #include "LibCxxVariant.h" #include "LibStdcpp.h" +#include "MSVCUndecoratedNameParser.h" using namespace lldb; using namespace lldb_private; @@ -265,6 +266,10 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier( const char *name, llvm::StringRef &context, llvm::StringRef &identifier) { + if (MSVCUndecoratedNameParser::IsMSVCUndecoratedName(name)) + return MSVCUndecoratedNameParser::ExtractContextAndIdentifier(name, context, + identifier); + CPlusPlusNameParser parser(name); if (auto full_name = parser.ParseAsFullName()) { identifier = full_name.getValue().basename; Index: source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h =================================================================== --- /dev/null +++ source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h @@ -0,0 +1,57 @@ +//===-- MSVCUndecoratedNameParser.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_MSVCUndecoratedNameParser_h_ +#define liblldb_MSVCUndecoratedNameParser_h_ + +#include + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" + +class MSVCUndecoratedNameSpecifier { +public: + MSVCUndecoratedNameSpecifier(llvm::StringRef full_name, + llvm::StringRef base_name) + : m_full_name(full_name), m_base_name(base_name) {} + + llvm::StringRef GetFullName() const { return m_full_name; } + llvm::StringRef GetBaseName() const { return m_base_name; } + +private: + llvm::StringRef m_full_name; + llvm::StringRef m_base_name; +}; + +class MSVCUndecoratedNameParser { +public: + explicit MSVCUndecoratedNameParser(llvm::StringRef name); + + std::size_t GetSpecifiersCount() const { return m_specifiers.size(); } + + MSVCUndecoratedNameSpecifier GetSpecifierAtIndex(std::size_t index) const { + return m_specifiers[index]; + } + + llvm::ArrayRef GetSpecifiers() const { + return m_specifiers; + } + + static bool IsMSVCUndecoratedName(llvm::StringRef name); + static bool ExtractContextAndIdentifier(llvm::StringRef name, + llvm::StringRef &context, + llvm::StringRef &identifier); + + static llvm::StringRef DropScope(llvm::StringRef name); + +private: + std::vector m_specifiers; +}; + +#endif Index: source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp =================================================================== --- /dev/null +++ source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp @@ -0,0 +1,98 @@ +//===-- MSVCUndecoratedNameParser.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MSVCUndecoratedNameParser.h" + +#include + +MSVCUndecoratedNameParser::MSVCUndecoratedNameParser(llvm::StringRef name) { + std::size_t last_base_start = 0; + + std::stack stack; + unsigned int open_angle_brackets = 0; + for (size_t i = 0; i < name.size(); i++) { + switch (name[i]) { + case '<': + // Do not treat `operator<' and `operator<<' as templates + // (sometimes they represented as `<' and `<<' in the name). + if (i == last_base_start || + i == last_base_start + 1 && name[last_base_start] == '<') + break; + + stack.push(i); + open_angle_brackets++; + + break; + case '>': + if (!stack.empty() && name[stack.top()] == '<') { + open_angle_brackets--; + stack.pop(); + } + + break; + case '`': + stack.push(i); + + break; + case '\'': + while (!stack.empty()) { + std::size_t top = stack.top(); + if (name[top] == '<') + open_angle_brackets--; + + stack.pop(); + + if (name[top] == '`') + break; + } + + break; + case ':': + if (open_angle_brackets) + break; + if (i == 0 || name[i - 1] != ':') + break; + + m_specifiers.emplace_back(name.take_front(i - 1), + name.slice(last_base_start, i - 1)); + + last_base_start = i + 1; + default: + break; + } + } + + m_specifiers.emplace_back(name, name.drop_front(last_base_start)); +} + +bool MSVCUndecoratedNameParser::IsMSVCUndecoratedName(llvm::StringRef name) { + return name.find('`') != llvm::StringRef::npos; +} + +bool MSVCUndecoratedNameParser::ExtractContextAndIdentifier( + llvm::StringRef name, llvm::StringRef &context, + llvm::StringRef &identifier) { + MSVCUndecoratedNameParser parser(name); + llvm::ArrayRef specs = parser.GetSpecifiers(); + + std::size_t count = specs.size(); + identifier = count > 0 ? specs[count - 1].GetBaseName() : ""; + context = count > 1 ? specs[count - 2].GetFullName() : ""; + + return count; +} + +llvm::StringRef MSVCUndecoratedNameParser::DropScope(llvm::StringRef name) { + MSVCUndecoratedNameParser parser(name); + llvm::ArrayRef specs = parser.GetSpecifiers(); + if (specs.empty()) + return ""; + + return specs[specs.size() - 1].GetBaseName(); +} Index: source/Plugins/SymbolFile/PDB/PDBASTParser.h =================================================================== --- source/Plugins/SymbolFile/PDB/PDBASTParser.h +++ source/Plugins/SymbolFile/PDB/PDBASTParser.h @@ -65,8 +65,6 @@ return m_ast_importer; } - static std::string PDBNameDropScope(const std::string &name); - private: typedef llvm::DenseMap CXXRecordDeclToUidMap; @@ -100,6 +98,10 @@ void AddRecordMethods(lldb_private::SymbolFile &symbol_file, lldb_private::CompilerType &record_type, PDBFuncSymbolEnumerator &methods_enum); + clang::CXXMethodDecl * + AddRecordMethod(lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, + const llvm::pdb::PDBSymbolFunc &method) const; lldb_private::ClangASTContext &m_ast; lldb_private::ClangASTImporter m_ast_importer; Index: source/Plugins/SymbolFile/PDB/PDBASTParser.cpp =================================================================== --- source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -38,6 +38,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" + using namespace lldb; using namespace lldb_private; using namespace llvm::pdb; @@ -329,7 +331,7 @@ return result[0]; } -static bool IsAnonymousNamespaceName(const std::string &name) { +static bool IsAnonymousNamespaceName(llvm::StringRef name) { return name == "`anonymous namespace'" || name == "`anonymous-namespace'"; } @@ -386,7 +388,7 @@ return nullptr; // Ignore unnamed-tag UDTs. - auto name = PDBNameDropScope(udt->getName()); + std::string name = MSVCUndecoratedNameParser::DropScope(udt->getName()); if (name.empty()) return nullptr; @@ -464,7 +466,8 @@ auto enum_type = llvm::dyn_cast(&type); assert(enum_type); - std::string name = PDBNameDropScope(enum_type->getName()); + std::string name = + MSVCUndecoratedNameParser::DropScope(enum_type->getName()); auto decl_context = GetDeclContextContainingSymbol(type); uint64_t bytes = enum_type->getLength(); @@ -536,7 +539,8 @@ if (!target_type) return nullptr; - std::string name = PDBNameDropScope(type_def->getName()); + std::string name = + MSVCUndecoratedNameParser::DropScope(type_def->getName()); auto decl_ctx = GetDeclContextContainingSymbol(type); // Check if such a typedef already exists in the current context @@ -582,7 +586,7 @@ return nullptr; func_sig = sig.release(); // Function type is named. - name = PDBNameDropScope(pdb_func->getName()); + name = MSVCUndecoratedNameParser::DropScope(pdb_func->getName()); } else if (auto pdb_func_sig = llvm::dyn_cast(&type)) { func_sig = const_cast(pdb_func_sig); @@ -795,7 +799,8 @@ clang::Decl * PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { - auto it = m_uid_to_decl.find(symbol.getSymIndexId()); + uint32_t sym_id = symbol.getSymIndexId(); + auto it = m_uid_to_decl.find(sym_id); if (it != m_uid_to_decl.end()) return it->second; @@ -811,14 +816,50 @@ const IPDBRawSymbol &raw = symbol.getRawSymbol(); auto class_parent_id = raw.getClassParentId(); - if (session.getSymbolById(class_parent_id)) { + if (std::unique_ptr class_parent = + session.getSymbolById(class_parent_id)) { auto class_parent_type = symbol_file->ResolveTypeUID(class_parent_id); if (!class_parent_type) return nullptr; - class_parent_type->GetFullCompilerType(); + CompilerType class_parent_ct = class_parent_type->GetFullCompilerType(); + + // Look a declaration up in the cache after completing the class + clang::Decl *decl = m_uid_to_decl.lookup(sym_id); + if (decl) + return decl; + + // A declaration was not found in the cache. It means that the symbol + // has the class parent, but the class doesn't have the symbol in its + // children list. + if (auto func = llvm::dyn_cast_or_null(&symbol)) { + // Try to find a class child method with the same RVA and use its + // declaration if found. + if (uint32_t rva = func->getRelativeVirtualAddress()) { + if (std::unique_ptr> + methods_enum = + class_parent->findAllChildren()) { + while (std::unique_ptr method = + methods_enum->getNext()) { + if (method->getRelativeVirtualAddress() == rva) { + decl = m_uid_to_decl.lookup(method->getSymIndexId()); + if (decl) + break; + } + } + } + } + + // If no class methods with the same RVA were found, then create a new + // method. It is possible for template methods. + if (!decl) + decl = AddRecordMethod(*symbol_file, class_parent_ct, *func); + } - return m_uid_to_decl.lookup(symbol.getSymIndexId()); + if (decl) + m_uid_to_decl[sym_id] = decl; + + return decl; } } @@ -840,7 +881,7 @@ if (auto parent_decl = llvm::dyn_cast_or_null(decl_context)) m_ast.GetCompleteDecl(parent_decl); - auto name = PDBNameDropScope(data->getName()); + std::string name = MSVCUndecoratedNameParser::DropScope(data->getName()); // Check if the current context already contains the symbol with the name. clang::Decl *decl = @@ -855,7 +896,7 @@ ClangUtil::GetQualType(type->GetLayoutCompilerType())); } - m_uid_to_decl[data->getSymIndexId()] = decl; + m_uid_to_decl[sym_id] = decl; return decl; } @@ -866,9 +907,9 @@ auto decl_context = GetDeclContextContainingSymbol(symbol); assert(decl_context); - auto name = PDBNameDropScope(func->getName()); + std::string name = MSVCUndecoratedNameParser::DropScope(func->getName()); - auto type = symbol_file->ResolveTypeUID(func->getSymIndexId()); + Type *type = symbol_file->ResolveTypeUID(sym_id); if (!type) return nullptr; @@ -879,17 +920,17 @@ decl_context, name.c_str(), type->GetForwardCompilerType(), storage, func->hasInlineAttribute()); - m_uid_to_decl[func->getSymIndexId()] = decl; + m_uid_to_decl[sym_id] = decl; return decl; } default: { // It's not a variable and not a function, check if it's a type - auto type = symbol_file->ResolveTypeUID(symbol.getSymIndexId()); + Type *type = symbol_file->ResolveTypeUID(sym_id); if (!type) return nullptr; - return m_uid_to_decl.lookup(symbol.getSymIndexId()); + return m_uid_to_decl.lookup(sym_id); } } } @@ -936,19 +977,15 @@ // We can't find any class or function parent of the symbol. So analyze // the full symbol name. The symbol may be belonging to a namespace // or function (or even to a class if it's e.g. a static variable symbol). - // We do not use CPlusPlusNameParser because it fails on things like - // `anonymous namespace'. // TODO: Make clang to emit full names for variables in namespaces // (as MSVC does) - auto context = symbol.getRawSymbol().getName(); - auto context_size = context.rfind("::"); - if (context_size == std::string::npos) - context_size = 0; - context = context.substr(0, context_size); - - // Check if there is a symbol with the name of the context. + std::string name(symbol.getRawSymbol().getName()); + MSVCUndecoratedNameParser parser(name); + llvm::ArrayRef specs = parser.GetSpecifiers(); + if (specs.empty()) + return m_ast.GetTranslationUnitDecl(); auto symbol_file = static_cast(m_ast.GetSymbolFile()); if (!symbol_file) @@ -958,32 +995,43 @@ if (!global) return m_ast.GetTranslationUnitDecl(); - TypeMap types; - if (auto children_enum = - global->findChildren(PDB_SymType::None, context, NS_CaseSensitive)) - while (auto child = children_enum->getNext()) - if (auto child_context = GetDeclContextForSymbol(*child)) - return child_context; - - // Split context and retrieve nested namespaces + bool has_type_or_function_parent = false; auto curr_context = m_ast.GetTranslationUnitDecl(); - std::string::size_type from = 0; - while (from < context_size) { - auto to = context.find("::", from); - if (to == std::string::npos) - to = context_size; - - auto namespace_name = context.substr(from, to - from); - auto namespace_name_c_str = IsAnonymousNamespaceName(namespace_name) - ? nullptr - : namespace_name.c_str(); - auto namespace_decl = - m_ast.GetUniqueNamespaceDeclaration(namespace_name_c_str, curr_context); - - m_parent_to_namespaces[curr_context].insert(namespace_decl); - - curr_context = namespace_decl; - from = to + 2; + for (std::size_t i = 0; i < specs.size() - 1; i++) { + // Check if there is a function or a type with the current context's name. + if (std::unique_ptr children_enum = global->findChildren( + PDB_SymType::None, specs[i].GetFullName(), NS_CaseSensitive)) { + while (IPDBEnumChildren::ChildTypePtr child = + children_enum->getNext()) { + if (clang::DeclContext *child_context = + GetDeclContextForSymbol(*child)) { + // Note that `GetDeclContextForSymbol' retrieves + // a declaration context for functions and types only, + // so if we are here then `child_context' is guaranteed + // a function or a type declaration context. + has_type_or_function_parent = true; + curr_context = child_context; + } + } + } + + // If there were no functions or types above then retrieve a namespace with + // the current context's name. There can be no namespaces inside a function + // or a type. We check it to avoid fake namespaces such as `__l2': + // `N0::N1::CClass::PrivateFunc::__l2::InnerFuncStruct' + if (!has_type_or_function_parent) { + std::string namespace_name = specs[i].GetBaseName(); + const char *namespace_name_c_str = + IsAnonymousNamespaceName(namespace_name) ? nullptr + : namespace_name.data(); + clang::NamespaceDecl *namespace_decl = + m_ast.GetUniqueNamespaceDeclaration(namespace_name_c_str, + curr_context); + + m_parent_to_namespaces[curr_context].insert(namespace_decl); + + curr_context = namespace_decl; + } } return curr_context; @@ -1034,24 +1082,11 @@ return nullptr; } -std::string PDBASTParser::PDBNameDropScope(const std::string &name) { - // Not all PDB names can be parsed with CPlusPlusNameParser. - // E.g. it fails on names containing `anonymous namespace'. - // So we simply drop everything before '::' - - auto offset = name.rfind("::"); - if (offset == std::string::npos) - return name; - assert(offset + 2 <= name.size()); - - return name.substr(offset + 2); -} - bool PDBASTParser::AddEnumValue(CompilerType enum_type, const PDBSymbolData &enum_value) { Declaration decl; Variant v = enum_value.getValue(); - std::string name = PDBNameDropScope(enum_value.getName()); + std::string name = MSVCUndecoratedNameParser::DropScope(enum_value.getName()); int64_t raw_value; switch (v.Type) { case PDB_VariantType::Int8: @@ -1256,36 +1291,43 @@ void PDBASTParser::AddRecordMethods(lldb_private::SymbolFile &symbol_file, lldb_private::CompilerType &record_type, PDBFuncSymbolEnumerator &methods_enum) { - while (auto method = methods_enum.getNext()) { - auto name = PDBNameDropScope(method->getName().c_str()); + while (std::unique_ptr method = methods_enum.getNext()) + if (clang::CXXMethodDecl *decl = + AddRecordMethod(symbol_file, record_type, *method)) + m_uid_to_decl[method->getSymIndexId()] = decl; +} - auto method_type = symbol_file.ResolveTypeUID(method->getSymIndexId()); - // MSVC specific __vecDelDtor. - if (!method_type) - continue; +clang::CXXMethodDecl * +PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, + const llvm::pdb::PDBSymbolFunc &method) const { + std::string name = MSVCUndecoratedNameParser::DropScope(method.getName()); - auto method_comp_type = method_type->GetFullCompilerType(); - if (!method_comp_type.GetCompleteType()) { - symbol_file.GetObjectFile()->GetModule()->ReportError( - ":: Class '%s' has a method '%s' whose type cannot be completed.", - record_type.GetTypeName().GetCString(), - method_comp_type.GetTypeName().GetCString()); - if (ClangASTContext::StartTagDeclarationDefinition(method_comp_type)) - ClangASTContext::CompleteTagDeclarationDefinition(method_comp_type); - } - - // TODO: get mangled name for the method. - auto decl = m_ast.AddMethodToCXXRecordType( - record_type.GetOpaqueQualType(), name.c_str(), - /*mangled_name*/ nullptr, method_comp_type, - TranslateMemberAccess(method->getAccess()), method->isVirtual(), - method->isStatic(), method->hasInlineAttribute(), - /*is_explicit*/ false, // FIXME: Need this field in CodeView. - /*is_attr_used*/ false, - /*is_artificial*/ method->isCompilerGenerated()); - if (!decl) - continue; + Type *method_type = symbol_file.ResolveTypeUID(method.getSymIndexId()); + // MSVC specific __vecDelDtor. + if (!method_type) + return nullptr; - m_uid_to_decl[method->getSymIndexId()] = decl; + CompilerType method_comp_type = method_type->GetFullCompilerType(); + if (!method_comp_type.GetCompleteType()) { + symbol_file.GetObjectFile()->GetModule()->ReportError( + ":: Class '%s' has a method '%s' whose type cannot be completed.", + record_type.GetTypeName().GetCString(), + method_comp_type.GetTypeName().GetCString()); + if (ClangASTContext::StartTagDeclarationDefinition(method_comp_type)) + ClangASTContext::CompleteTagDeclarationDefinition(method_comp_type); } + + AccessType access = TranslateMemberAccess(method.getAccess()); + if (access == eAccessNone) + access = eAccessPublic; + + // TODO: get mangled name for the method. + return m_ast.AddMethodToCXXRecordType( + record_type.GetOpaqueQualType(), name.c_str(), + /*mangled_name*/ nullptr, method_comp_type, access, method.isVirtual(), + method.isStatic(), method.hasInlineAttribute(), + /*is_explicit*/ false, // FIXME: Need this field in CodeView. + /*is_attr_used*/ false, + /*is_artificial*/ method.isCompilerGenerated()); } Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.h =================================================================== --- source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -187,7 +187,7 @@ const llvm::pdb::PDBSymbolCompiland &pdb_compiland, llvm::DenseMap &index_map) const; - void FindTypesByName(const std::string &name, + void FindTypesByName(llvm::StringRef name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::TypeMap &types); Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp =================================================================== --- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -9,6 +9,9 @@ #include "SymbolFilePDB.h" +#include "PDBASTParser.h" +#include "PDBLocationToDWARFExpression.h" + #include "clang/Lex/Lexer.h" #include "lldb/Core/Module.h" @@ -46,9 +49,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" // For IsCPPMangledName +#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" #include "Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h" -#include "Plugins/SymbolFile/PDB/PDBASTParser.h" -#include "Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h" #include @@ -1063,7 +1065,7 @@ lldbassert(sc.module_sp.get()); if (!name.GetStringRef().equals( - PDBASTParser::PDBNameDropScope(pdb_data->getName()))) + MSVCUndecoratedNameParser::DropScope(pdb_data->getName()))) continue; sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get(); @@ -1170,22 +1172,11 @@ // Class. We won't bother to check if the parent is UDT or Enum here. m_func_method_names.Append(ConstString(name), uid); - ConstString cstr_name(name); - // To search a method name, like NS::Class:MemberFunc, LLDB searches // its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does // not have inforamtion of this, we extract base names and cache them // by our own effort. - llvm::StringRef basename; - CPlusPlusLanguage::MethodName cpp_method(cstr_name); - if (cpp_method.IsValid()) { - llvm::StringRef context; - basename = cpp_method.GetBasename(); - if (basename.empty()) - CPlusPlusLanguage::ExtractContextAndIdentifier(name.c_str(), - context, basename); - } - + llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name); if (!basename.empty()) m_func_base_names.Append(ConstString(basename), uid); else { @@ -1198,11 +1189,12 @@ } else { // Handle not-method symbols. - // The function name might contain namespace, or its lexical scope. It - // is not safe to get its base name by applying same scheme as we deal - // with the method names. - // FIXME: Remove namespace if function is static in a scope. - m_func_base_names.Append(ConstString(name), uid); + // The function name might contain namespace, or its lexical scope. + llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name); + if (!basename.empty()) + m_func_base_names.Append(ConstString(basename), uid); + else + m_func_base_names.Append(ConstString(name), uid); if (name == "main") { m_func_full_names.Append(ConstString(name), uid); @@ -1348,10 +1340,8 @@ searched_symbol_files.clear(); searched_symbol_files.insert(this); - std::string name_str = name.AsCString(); - // There is an assumption 'name' is not a regex - FindTypesByName(name_str, parent_decl_ctx, max_matches, types); + FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types); return types.GetSize(); } @@ -1412,7 +1402,7 @@ } void SymbolFilePDB::FindTypesByName( - const std::string &name, + llvm::StringRef name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::TypeMap &types) { if (!parent_decl_ctx) @@ -1430,8 +1420,8 @@ if (max_matches > 0 && matches >= max_matches) break; - if (PDBASTParser::PDBNameDropScope(result->getRawSymbol().getName()) != - name) + if (MSVCUndecoratedNameParser::DropScope( + result->getRawSymbol().getName()) != name) continue; switch (result->getSymTag()) { Index: unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp =================================================================== --- unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp +++ unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp @@ -138,7 +138,14 @@ {"std::vector>" "::_M_emplace_back_aux", "std::vector>", - "_M_emplace_back_aux"}}; + "_M_emplace_back_aux"}, + {"`anonymous namespace'::foo", "`anonymous namespace'", "foo"}, + {"`operator<'::`2'::B<0>::operator>", + "`operator<'::`2'::B<0>", + "operator>"}, + {"`anonymous namespace'::S::<<::__l2::Foo", + "`anonymous namespace'::S::<<::__l2", + "Foo"}}; llvm::StringRef context, basename; for (const auto &test : test_cases) {