Author: aleksandr.urakov
Date: Tue Nov  6 00:02:55 2018
New Revision: 346213

URL: http://llvm.org/viewvc/llvm-project?rev=346213&view=rev
Log:
[PDB] Introduce `MSVCUndecoratedNameParser`

This patch introduces the simple MSVCUndecoratedNameParser. It is needed for
parsing names of PDB symbols corresponding to template instantiations. For
example, for the name `operator<<A>'::`2'::B::operator> we can't just split the
name with :: (as it is implemented for now) to retrieve its scopes. This parser
processes such names in a more correct way.

Differential Revision: https://reviews.llvm.org/D52461

Added:
    lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp
    lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h
Modified:
    lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp
    lldb/trunk/lit/SymbolFile/PDB/ast-restore.test
    lldb/trunk/source/Plugins/Language/CPlusPlus/CMakeLists.txt
    lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
    lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
    lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h
    lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
    lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
    lldb/trunk/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp

Modified: lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp?rev=346213&r1=346212&r2=346213&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp (original)
+++ lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp Tue Nov  6 00:02:55 
2018
@@ -36,7 +36,15 @@ private:
 };
 int Class::ClassStatic = 7;
 
-void foo() { Class::StaticFunc(Class(Enum_0)); }
+template<typename T>
+struct Template {
+  template<Enum E>
+  void TemplateFunc() {
+    T::StaticFunc(T(E));
+  }
+};
+
+void foo() { Template<Class>().TemplateFunc<Enum_0>(); }
 
 } // namespace N1
 } // namespace N0

Modified: lldb/trunk/lit/SymbolFile/PDB/ast-restore.test
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/ast-restore.test?rev=346213&r1=346212&r2=346213&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/ast-restore.test (original)
+++ lldb/trunk/lit/SymbolFile/PDB/ast-restore.test Tue Nov  6 00:02:55 2018
@@ -6,6 +6,7 @@ RUN: lldb-test symbols -dump-ast %t.exe
 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:     }
 INNER: }
 
+TEMPLATE: Module: {{.*}}
+TEMPLATE: struct Template<N0::N1::Class> {
+TEMPLATE:     inline void TemplateFunc<1>();
+TEMPLATE: };
+
 FOO: Module: {{.*}}
 FOO: namespace N0 {
 FOO:     namespace N1 {

Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/CMakeLists.txt
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/CMakeLists.txt?rev=346213&r1=346212&r2=346213&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/CMakeLists.txt Tue Nov  6 
00:02:55 2018
@@ -18,6 +18,7 @@ add_lldb_library(lldbPluginCPlusPlusLang
   LibStdcpp.cpp
   LibStdcppTuple.cpp
   LibStdcppUniquePointer.cpp
+  MSVCUndecoratedNameParser.cpp
 
   LINK_LIBS
     lldbCore

Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp?rev=346213&r1=346212&r2=346213&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
(original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp Tue Nov  
6 00:02:55 2018
@@ -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::IsCPPMangledName
 
 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;

Added: 
lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp?rev=346213&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp 
(added)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp 
Tue Nov  6 00:02:55 2018
@@ -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 <stack>
+
+MSVCUndecoratedNameParser::MSVCUndecoratedNameParser(llvm::StringRef name) {
+  std::size_t last_base_start = 0;
+
+  std::stack<std::size_t> 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<MSVCUndecoratedNameSpecifier> 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<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+  if (specs.empty())
+    return "";
+
+  return specs[specs.size() - 1].GetBaseName();
+}

Added: lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h?rev=346213&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h 
(added)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h 
Tue Nov  6 00:02:55 2018
@@ -0,0 +1,51 @@
+//===-- 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 <vector>
+
+#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);
+
+  llvm::ArrayRef<MSVCUndecoratedNameSpecifier> 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<MSVCUndecoratedNameSpecifier> m_specifiers;
+};
+
+#endif

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp?rev=346213&r1=346212&r2=346213&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp Tue Nov  6 
00:02:55 2018
@@ -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;
@@ -330,7 +332,7 @@ GetDeclFromContextByName(const clang::AS
   return result[0];
 }
 
-static bool IsAnonymousNamespaceName(const std::string &name) {
+static bool IsAnonymousNamespaceName(llvm::StringRef name) {
   return name == "`anonymous namespace'" || name == "`anonymous-namespace'";
 }
 
@@ -387,7 +389,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTyp
       return nullptr;
 
     // Ignore unnamed-tag UDTs.
-    auto name = PDBNameDropScope(udt->getName());
+    std::string name = MSVCUndecoratedNameParser::DropScope(udt->getName());
     if (name.empty())
       return nullptr;
 
@@ -465,7 +467,8 @@ lldb::TypeSP PDBASTParser::CreateLLDBTyp
     auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&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();
 
@@ -537,7 +540,8 @@ lldb::TypeSP PDBASTParser::CreateLLDBTyp
     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
@@ -583,7 +587,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTyp
         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<PDBSymbolTypeFunctionSig>(&type)) {
       func_sig = const_cast<PDBSymbolTypeFunctionSig *>(pdb_func_sig);
@@ -796,7 +800,8 @@ bool PDBASTParser::CompleteTypeFromPDB(
 
 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;
 
@@ -812,14 +817,50 @@ PDBASTParser::GetDeclForSymbol(const llv
     const IPDBRawSymbol &raw = symbol.getRawSymbol();
 
     auto class_parent_id = raw.getClassParentId();
-    if (session.getSymbolById(class_parent_id)) {
+    if (std::unique_ptr<PDBSymbol> 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<PDBSymbolFunc>(&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<ConcreteSymbolEnumerator<PDBSymbolFunc>>
+                  methods_enum =
+                      class_parent->findAllChildren<PDBSymbolFunc>()) {
+            while (std::unique_ptr<PDBSymbolFunc> method =
+                       methods_enum->getNext()) {
+              if (method->getRelativeVirtualAddress() == rva) {
+                decl = m_uid_to_decl.lookup(method->getSymIndexId());
+                if (decl)
+                  break;
+              }
+            }
+          }
+        }
 
-      return m_uid_to_decl.lookup(symbol.getSymIndexId());
+        // 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);
+      }
+
+      if (decl)
+        m_uid_to_decl[sym_id] = decl;
+
+      return decl;
     }
   }
 
@@ -841,7 +882,7 @@ PDBASTParser::GetDeclForSymbol(const llv
     if (auto parent_decl = 
llvm::dyn_cast_or_null<clang::TagDecl>(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 =
@@ -856,7 +897,7 @@ PDBASTParser::GetDeclForSymbol(const llv
           ClangUtil::GetQualType(type->GetLayoutCompilerType()));
     }
 
-    m_uid_to_decl[data->getSymIndexId()] = decl;
+    m_uid_to_decl[sym_id] = decl;
 
     return decl;
   }
@@ -867,9 +908,9 @@ PDBASTParser::GetDeclForSymbol(const llv
     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;
 
@@ -880,17 +921,17 @@ PDBASTParser::GetDeclForSymbol(const llv
         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);
   }
   }
 }
@@ -937,19 +978,15 @@ clang::DeclContext *PDBASTParser::GetDec
   // 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<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+  if (specs.empty())
+    return m_ast.GetTranslationUnitDecl();
 
   auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
   if (!symbol_file)
@@ -959,32 +996,43 @@ clang::DeclContext *PDBASTParser::GetDec
   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;
   clang::DeclContext *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);
+  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<IPDBEnumSymbols> children_enum = global->findChildren(
+            PDB_SymType::None, specs[i].GetFullName(), NS_CaseSensitive)) {
+      while (IPDBEnumChildren<PDBSymbol>::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);
+      m_parent_to_namespaces[curr_context].insert(namespace_decl);
 
-    curr_context = namespace_decl;
-    from = to + 2;
+      curr_context = namespace_decl;
+    }
   }
 
   return curr_context;
@@ -1035,24 +1083,11 @@ PDBASTParser::FindNamespaceDecl(const cl
   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:
@@ -1257,36 +1292,43 @@ void PDBASTParser::AddRecordBases(
 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());
-
-    auto method_type = symbol_file.ResolveTypeUID(method->getSymIndexId());
-    // MSVC specific __vecDelDtor.
-    if (!method_type)
-      continue;
-
-    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);
-    }
+  while (std::unique_ptr<PDBSymbolFunc> method = methods_enum.getNext())
+    if (clang::CXXMethodDecl *decl =
+            AddRecordMethod(symbol_file, record_type, *method))
+      m_uid_to_decl[method->getSymIndexId()] = decl;
+}
 
-    // 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;
+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());
+
+  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());
 }

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h?rev=346213&r1=346212&r2=346213&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h Tue Nov  6 00:02:55 
2018
@@ -65,8 +65,6 @@ public:
     return m_ast_importer;
   }
 
-  static std::string PDBNameDropScope(const std::string &name);
-
 private:
   typedef llvm::DenseMap<clang::CXXRecordDecl *, lldb::user_id_t>
       CXXRecordDeclToUidMap;
@@ -100,6 +98,10 @@ private:
   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;

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp?rev=346213&r1=346212&r2=346213&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp Tue Nov  6 
00:02:55 2018
@@ -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 <regex>
 
@@ -1068,7 +1070,7 @@ uint32_t SymbolFilePDB::FindGlobalVariab
     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();
@@ -1175,22 +1177,11 @@ void SymbolFilePDB::CacheFunctionNames()
         // 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 {
@@ -1203,11 +1194,12 @@ void SymbolFilePDB::CacheFunctionNames()
       } 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);
@@ -1353,10 +1345,8 @@ uint32_t SymbolFilePDB::FindTypes(
   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();
 }
@@ -1425,7 +1415,7 @@ void SymbolFilePDB::FindTypesByRegex(
 }
 
 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)
@@ -1443,8 +1433,8 @@ void SymbolFilePDB::FindTypesByName(
     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()) {

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h?rev=346213&r1=346212&r2=346213&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h Tue Nov  6 
00:02:55 2018
@@ -192,7 +192,7 @@ private:
       const llvm::pdb::PDBSymbolCompiland &pdb_compiland,
       llvm::DenseMap<uint32_t, uint32_t> &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);
 

Modified: lldb/trunk/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp?rev=346213&r1=346212&r2=346213&view=diff
==============================================================================
--- lldb/trunk/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp (original)
+++ lldb/trunk/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp Tue Nov  
6 00:02:55 2018
@@ -138,7 +138,14 @@ TEST(CPlusPlusLanguage, ExtractContextAn
       {"std::vector<Class, std::allocator<Class>>"
        "::_M_emplace_back_aux<Class const&>",
        "std::vector<Class, std::allocator<Class>>",
-       "_M_emplace_back_aux<Class const&>"}};
+       "_M_emplace_back_aux<Class const&>"},
+      {"`anonymous namespace'::foo", "`anonymous namespace'", "foo"},
+      {"`operator<<A>'::`2'::B<0>::operator>",
+       "`operator<<A>'::`2'::B<0>",
+       "operator>"},
+      {"`anonymous namespace'::S::<<::__l2::Foo",
+       "`anonymous namespace'::S::<<::__l2",
+       "Foo"}};
 
   llvm::StringRef context, basename;
   for (const auto &test : test_cases) {


_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to