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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits