zequanwu updated this revision to Diff 457752.
zequanwu added a comment.
Herald added a subscriber: JDevlieghere.

Fix comment in test case.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133243/new/

https://reviews.llvm.org/D133243

Files:
  lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
  lldb/test/Shell/SymbolFile/NativePDB/icf.cpp

Index: lldb/test/Shell/SymbolFile/NativePDB/icf.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/NativePDB/icf.cpp
@@ -0,0 +1,54 @@
+// clang-format off
+// REQUIRES: lld, x86
+
+// Test lldb finds the correct parent context decl for functions and class methods when icf happens.
+// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -GS- -fno-addrsig -c /Fo%t.obj -- %s
+// RUN: lld-link -opt:icf -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols --dump-ast %t.exe | FileCheck %s
+
+struct A {
+  int f1(int x) {
+    return x * 2;
+  }
+};
+struct B {
+  int f2(int x) {
+    return x * 2;
+  }
+};
+namespace N1 {
+int f3(void*, int x) {
+  return  x * 2;
+}
+} // namespace N1
+
+namespace N2 {
+namespace N3 {
+  int f4(void*, int x) {
+    return  x * 2;
+  }
+} // namespace N3  
+} // namespace N2
+
+int main() {
+  A a;
+  B b;
+  return a.f1(1) + b.f2(1) + N1::f3(nullptr, 1) + N2::N3::f4(nullptr, 1);
+}
+
+
+// CHECK:      namespace N1 {
+// CHECK-NEXT:     int f3(void *, int x);
+// CHECK-NEXT: }
+// CHECK-NEXT: namespace N2 {
+// CHECK-NEXT:     namespace N3 {
+// CHECK-NEXT:         int f4(void *, int x);
+// CHECK-NEXT:     }
+// CHECK-NEXT: }
+// CHECK-NEXT: int main();
+// CHECK-NEXT: struct A {
+// CHECK-NEXT:     int f1(int);
+// CHECK-NEXT: };
+// CHECK-NEXT: struct B {
+// CHECK-NEXT:     int f2(int);
+// CHECK-NEXT: };
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -470,9 +470,9 @@
   return result;
 }
 
-static llvm::Optional<PublicSym32> FindPublicSym(const SegmentOffset &addr,
-                                                 SymbolStream &syms,
-                                                 PublicsStream &publics) {
+static llvm::SmallVector<PublicSym32> FindPublicSyms(const SegmentOffset &addr,
+                                                     SymbolStream &syms,
+                                                     PublicsStream &publics) {
   llvm::FixedStreamArray<ulittle32_t> addr_map = publics.getAddressMap();
   auto iter = std::lower_bound(
       addr_map.begin(), addr_map.end(), addr,
@@ -485,15 +485,17 @@
           return true;
         return p1.Offset < y.offset;
       });
-  if (iter == addr_map.end())
-    return llvm::None;
-  CVSymbol sym = syms.readRecord(*iter);
-  lldbassert(sym.kind() == S_PUB32);
-  PublicSym32 p;
-  llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym, p));
-  if (p.Segment == addr.segment && p.Offset == addr.offset)
-    return p;
-  return llvm::None;
+  llvm::SmallVector<PublicSym32, 1> public_syms;
+  while (iter != addr_map.end()) {
+    CVSymbol sym = syms.readRecord(*iter);
+    lldbassert(sym.kind() == S_PUB32);
+    PublicSym32 p;
+    llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym, p));
+    if (p.Segment == addr.segment && p.Offset == addr.offset)
+      public_syms.push_back(p);
+    ++iter;
+  }
+  return public_syms;
 }
 
 clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {
@@ -608,48 +610,56 @@
 
 clang::DeclContext *
 PdbAstBuilder::GetParentDeclContextForSymbol(const CVSymbol &sym) {
-  if (!SymbolHasAddress(sym))
-    return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
+  llvm::StringRef full_name = getSymbolName(sym);
+  llvm::StringRef base_name = full_name.rsplit("::").second;
+  if (!SymbolHasAddress(sym) || base_name.empty())
+    return CreateDeclInfoForUndecoratedName(full_name).first;
   SegmentOffset addr = GetSegmentAndOffset(sym);
-  llvm::Optional<PublicSym32> pub =
-      FindPublicSym(addr, m_index.symrecords(), m_index.publics());
-  if (!pub)
-    return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
+  llvm::SmallVector<PublicSym32> public_syms =
+      FindPublicSyms(addr, m_index.symrecords(), m_index.publics());
+
+  for (const PublicSym32 &pub : public_syms) {
+    llvm::ms_demangle::Demangler demangler;
+    StringView name{pub.Name.begin(), pub.Name.size()};
+    llvm::ms_demangle::SymbolNode *node = demangler.parse(name);
+    if (!node)
+      continue;
+    llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{
+        node->Name->Components->Nodes, node->Name->Components->Count};
+    // Because ICF, we need to filter out the public symbols by base name.
+    if (name_components.empty() ||
+        base_name != name_components.back()->toString())
+      continue;
 
-  llvm::ms_demangle::Demangler demangler;
-  StringView name{pub->Name.begin(), pub->Name.size()};
-  llvm::ms_demangle::SymbolNode *node = demangler.parse(name);
-  if (!node)
-    return FromCompilerDeclContext(GetTranslationUnitDecl());
-  llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{
-      node->Name->Components->Nodes, node->Name->Components->Count - 1};
-
-  if (!name_components.empty()) {
-    // Render the current list of scope nodes as a fully qualified name, and
-    // look it up in the debug info as a type name.  If we find something,
-    // this is a type (which may itself be prefixed by a namespace).  If we
-    // don't, this is a list of namespaces.
-    std::string qname = RenderScopeList(name_components);
-    std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname);
-    while (!matches.empty()) {
-      clang::QualType qt = GetOrCreateType(matches.back());
-      if (qt.isNull())
-        continue;
-      clang::TagDecl *tag = qt->getAsTagDecl();
-      if (tag)
-        return clang::TagDecl::castToDeclContext(tag);
-      matches.pop_back();
+    name_components = name_components.drop_back();
+    if (!name_components.empty()) {
+      // Render the current list of scope nodes as a fully qualified name, and
+      // look it up in the debug info as a type name.  If we find something,
+      // this is a type (which may itself be prefixed by a namespace).  If we
+      // don't, this is a list of namespaces.
+      std::string qname = RenderScopeList(name_components);
+      std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname);
+      while (!matches.empty()) {
+        clang::QualType qt = GetOrCreateType(matches.back());
+        if (qt.isNull())
+          continue;
+        clang::TagDecl *tag = qt->getAsTagDecl();
+        if (tag)
+          return clang::TagDecl::castToDeclContext(tag);
+        matches.pop_back();
+      }
     }
-  }
 
-  // It's not a type.  It must be a series of namespaces.
-  auto context = FromCompilerDeclContext(GetTranslationUnitDecl());
-  while (!name_components.empty()) {
-    std::string ns = name_components.front()->toString();
-    context = GetOrCreateNamespaceDecl(ns.c_str(), *context);
-    name_components = name_components.drop_front();
+    // It's not a type.  It must be a series of namespaces.
+    auto *context = FromCompilerDeclContext(GetTranslationUnitDecl());
+    while (!name_components.empty()) {
+      std::string ns = name_components.front()->toString();
+      context = GetOrCreateNamespaceDecl(ns.c_str(), *context);
+      name_components = name_components.drop_front();
+    }
+    return context;
   }
-  return context;
+  return CreateDeclInfoForUndecoratedName(full_name).first;
 }
 
 clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to