summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp449
1 files changed, 414 insertions, 35 deletions
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 3f6ce1513f0..8cf332f8a95 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -7,6 +7,9 @@
#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/Demangle/MicrosoftDemangle.h"
@@ -150,8 +153,8 @@ TranslateCallingConvention(llvm::codeview::CallingConvention conv) {
}
static llvm::Optional<CVTagRecord>
-GetNestedTagRecord(const NestedTypeRecord &Record, const CVTagRecord &parent,
- TpiStream &tpi) {
+GetNestedTagDefinition(const NestedTypeRecord &Record,
+ const CVTagRecord &parent, TpiStream &tpi) {
// An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
// is also used to indicate the primary definition of a nested class. That is
// to say, if you have:
@@ -218,7 +221,7 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
llvm::ms_demangle::IdentifierNode *idn =
ttn->QualifiedName->getUnqualifiedIdentifier();
- std::string uname = idn->toString();
+ std::string uname = idn->toString(llvm::ms_demangle::OF_NoTagSpecifier);
llvm::ms_demangle::NodeArrayNode *name_components =
ttn->QualifiedName->Components;
@@ -261,15 +264,55 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
return {context, uname};
}
+static bool IsUniqueNameEnumTag(llvm::StringRef unique_name) {
+ if (unique_name.size() < 4)
+ return false;
+ return unique_name[3] == 'W';
+}
+
+static std::string GetParentUniqueName(llvm::StringRef unique_name) {
+ if (unique_name.size() < 4)
+ return unique_name;
+ size_t start = IsUniqueNameEnumTag(unique_name) ? 5 : 4;
+ size_t end = unique_name.find('@');
+ if (end == llvm::StringRef::npos)
+ return unique_name;
+ std::string result = unique_name.str();
+ return result.erase(start, end - start + 1);
+}
+
void PdbAstBuilder::BuildParentMap() {
LazyRandomTypeCollection &types = m_index.tpi().typeCollection();
+ llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
+ llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
+
+ struct RecordIndices {
+ TypeIndex forward;
+ TypeIndex full;
+ };
+
+ llvm::StringMap<RecordIndices> record_indices;
+
for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
CVType type = types.getType(*ti);
if (!IsTagRecord(type))
continue;
CVTagRecord tag = CVTagRecord::create(type);
+
+ RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
+ if (tag.asTag().isForwardRef())
+ indices.forward = *ti;
+ else
+ indices.full = *ti;
+
+ if (indices.full != TypeIndex::None() &&
+ indices.forward != TypeIndex::None()) {
+ forward_to_full[indices.forward] = indices.full;
+ full_to_forward[indices.full] = indices.forward;
+ }
+
// We're looking for LF_NESTTYPE records in the field list, so ignore
// forward references (no field list), and anything without a nested class
// (since there won't be any LF_NESTTYPE records).
@@ -285,27 +328,26 @@ void PdbAstBuilder::BuildParentMap() {
PdbIndex &index;
llvm::DenseMap<TypeIndex, TypeIndex> &parents;
+
+ unsigned unnamed_type_index = 1;
TypeIndex parent;
const CVTagRecord &parent_cvt;
llvm::Error visitKnownMember(CVMemberRecord &CVR,
NestedTypeRecord &Record) override {
+ std::string unnamed_type_name;
+ if (Record.Name.empty()) {
+ unnamed_type_name =
+ llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
+ Record.Name = unnamed_type_name;
+ ++unnamed_type_index;
+ }
llvm::Optional<CVTagRecord> tag =
- GetNestedTagRecord(Record, parent_cvt, index.tpi());
+ GetNestedTagDefinition(Record, parent_cvt, index.tpi());
if (!tag)
return llvm::ErrorSuccess();
parents[Record.Type] = parent;
- if (!tag->asTag().isForwardRef())
- return llvm::ErrorSuccess();
-
- llvm::Expected<TypeIndex> full_decl =
- index.tpi().findFullDeclForForwardRef(Record.Type);
- if (!full_decl) {
- llvm::consumeError(full_decl.takeError());
- return llvm::ErrorSuccess();
- }
- parents[*full_decl] = parent;
return llvm::ErrorSuccess();
}
};
@@ -316,11 +358,102 @@ void PdbAstBuilder::BuildParentMap() {
if (error)
llvm::consumeError(std::move(error));
}
+
+ // Now that we know the forward -> full mapping of all type indices, we can
+ // re-write all the indices. At the end of this process, we want a mapping
+ // consisting of fwd -> full and full -> full for all child -> parent indices.
+ // We can re-write the values in place, but for the keys, we must save them
+ // off so that we don't modify the map in place while also iterating it.
+ std::vector<TypeIndex> full_keys;
+ std::vector<TypeIndex> fwd_keys;
+ for (auto &entry : m_parent_types) {
+ TypeIndex key, value;
+ std::tie(key, value) = entry;
+
+ auto iter = forward_to_full.find(value);
+ if (iter != forward_to_full.end())
+ entry.second = iter->second;
+
+ iter = forward_to_full.find(key);
+ if (iter != forward_to_full.end())
+ fwd_keys.push_back(key);
+ else
+ full_keys.push_back(key);
+ }
+ for (TypeIndex fwd : fwd_keys) {
+ TypeIndex full = forward_to_full[fwd];
+ m_parent_types[full] = m_parent_types[fwd];
+ }
+ for (TypeIndex full : full_keys) {
+ TypeIndex fwd = full_to_forward[full];
+ m_parent_types[fwd] = m_parent_types[full];
+ }
+
+ // Now that
+}
+
+static bool isLocalVariableType(SymbolKind K) {
+ switch (K) {
+ case S_REGISTER:
+ case S_REGREL32:
+ case S_LOCAL:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static std::string
+RenderScopeList(llvm::ArrayRef<llvm::ms_demangle::Node *> nodes) {
+ lldbassert(!nodes.empty());
+
+ std::string result = nodes.front()->toString();
+ nodes = nodes.drop_front();
+ while (!nodes.empty()) {
+ result += "::";
+ result += nodes.front()->toString(llvm::ms_demangle::OF_NoTagSpecifier);
+ nodes = nodes.drop_front();
+ }
+ return result;
+}
+
+static llvm::Optional<PublicSym32> FindPublicSym(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,
+ [&](const ulittle32_t &x, const SegmentOffset &y) {
+ CVSymbol s1 = syms.readRecord(x);
+ lldbassert(s1.kind() == S_PUB32);
+ PublicSym32 p1;
+ llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(s1, p1));
+ if (p1.Segment < y.segment)
+ 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;
}
clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {
CVSymbol cvs = m_index.ReadSymbolRecord(id);
+ if (isLocalVariableType(cvs.kind())) {
+ clang::DeclContext *scope = GetParentDeclContext(id);
+ clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope);
+ PdbCompilandSymId scope_id(id.modi, m_decl_to_status[scope_decl].uid);
+ return GetOrCreateVariableDecl(scope_id, id);
+ }
+
switch (cvs.kind()) {
case S_GPROC32:
case S_LPROC32:
@@ -333,14 +466,6 @@ clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {
return nullptr;
case S_BLOCK32:
return GetOrCreateBlockDecl(id);
- case S_REGISTER:
- case S_REGREL32:
- case S_LOCAL: {
- clang::DeclContext *scope = GetParentDeclContext(id);
- clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope);
- PdbCompilandSymId scope_id(id.modi, m_decl_to_status[scope_decl].uid);
- return GetOrCreateLocalVariableDecl(scope_id, id);
- }
default:
return nullptr;
}
@@ -371,6 +496,11 @@ clang::Decl *PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) {
}
clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) {
+ if (uid.kind() == PdbSymUidKind::CompilandSym) {
+ if (uid.asCompilandSym().offset == 0)
+ return &GetTranslationUnitDecl();
+ }
+
clang::Decl *decl = GetOrCreateDeclForUid(uid);
if (!decl)
return nullptr;
@@ -385,14 +515,60 @@ clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
case PdbSymUidKind::CompilandSym: {
llvm::Optional<PdbCompilandSymId> scope =
FindSymbolScope(m_index, uid.asCompilandSym());
- if (!scope)
+ if (scope)
+ return GetOrCreateDeclContextForUid(*scope);
+
+ CVSymbol sym = m_index.ReadSymbolRecord(uid.asCompilandSym());
+ if (!SymbolHasAddress(sym))
return &GetTranslationUnitDecl();
- return GetOrCreateDeclContextForUid(*scope);
+ SegmentOffset addr = GetSegmentAndOffset(sym);
+ llvm::Optional<PublicSym32> pub =
+ FindPublicSym(addr, m_index.symrecords(), m_index.publics());
+ if (!pub)
+ return &GetTranslationUnitDecl();
+
+ llvm::ms_demangle::Demangler demangler;
+ StringView name{pub->Name.begin(), pub->Name.size()};
+ llvm::ms_demangle::SymbolNode *node = demangler.parse(name);
+ if (!node)
+ return &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());
+ 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.
+ clang::DeclContext *context = &GetTranslationUnitDecl();
+ while (!name_components.empty()) {
+ std::string ns = name_components.front()->toString();
+ context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context);
+ name_components = name_components.drop_front();
+ }
+ return context;
}
- case PdbSymUidKind::Type:
+ case PdbSymUidKind::Type: {
// It could be a namespace, class, or global. We don't support nested
// functions yet. Anyway, we just need to consult the parent type map.
- break;
+ PdbTypeSymId type_id = uid.asTypeSym();
+ auto iter = m_parent_types.find(type_id.index);
+ if (iter == m_parent_types.end())
+ return &GetTranslationUnitDecl();
+ return GetOrCreateDeclContextForUid(PdbTypeSymId(iter->second));
+ }
case PdbSymUidKind::FieldListMember:
// In this case the parent DeclContext is the one for the class that this
// member is inside of.
@@ -531,10 +707,9 @@ PdbAstBuilder::CreateModifierType(const ModifierRecord &modifier) {
clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,
const TagRecord &record) {
- clang::DeclContext *decl_context = nullptr;
+ clang::DeclContext *context = nullptr;
std::string uname;
- std::tie(decl_context, uname) = CreateDeclInfoForType(record, id.index);
-
+ std::tie(context, uname) = CreateDeclInfoForType(record, id.index);
clang::TagTypeKind ttk = TranslateUdtKind(record);
lldb::AccessType access =
(ttk == clang::TTK_Class) ? lldb::eAccessPrivate : lldb::eAccessPublic;
@@ -544,7 +719,7 @@ clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,
metadata.SetIsDynamicCXXType(false);
CompilerType ct =
- m_clang.CreateRecordType(decl_context, access, uname.c_str(), ttk,
+ m_clang.CreateRecordType(context, access, uname.c_str(), ttk,
lldb::eLanguageTypeC_plus_plus, &metadata);
lldbassert(ct.IsValid());
@@ -583,6 +758,12 @@ PdbAstBuilder::GetOrCreateBlockDecl(PdbCompilandSymId block_id) {
clang::BlockDecl *block_decl = m_clang.CreateBlockDeclaration(scope);
m_uid_to_decl.insert({toOpaqueUid(block_id), block_decl});
+
+ DeclStatus status;
+ status.resolved = true;
+ status.uid = toOpaqueUid(block_id);
+ m_decl_to_status.insert({block_decl, status});
+
return block_decl;
}
@@ -595,12 +776,16 @@ clang::VarDecl *PdbAstBuilder::CreateVariableDecl(PdbSymUid uid, CVSymbol sym,
&scope, var_info.name.str().c_str(), qt);
m_uid_to_decl[toOpaqueUid(uid)] = var_decl;
+ DeclStatus status;
+ status.resolved = true;
+ status.uid = toOpaqueUid(uid);
+ m_decl_to_status.insert({var_decl, status});
return var_decl;
}
clang::VarDecl *
-PdbAstBuilder::GetOrCreateLocalVariableDecl(PdbCompilandSymId scope_id,
- PdbCompilandSymId var_id) {
+PdbAstBuilder::GetOrCreateVariableDecl(PdbCompilandSymId scope_id,
+ PdbCompilandSymId var_id) {
if (clang::Decl *decl = TryGetDecl(var_id))
return llvm::dyn_cast<clang::VarDecl>(decl);
@@ -610,8 +795,7 @@ PdbAstBuilder::GetOrCreateLocalVariableDecl(PdbCompilandSymId scope_id,
return CreateVariableDecl(PdbSymUid(var_id), sym, *scope);
}
-clang::VarDecl *
-PdbAstBuilder::GetOrCreateGlobalVariableDecl(PdbGlobalSymId var_id) {
+clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) {
if (clang::Decl *decl = TryGetDecl(var_id))
return llvm::dyn_cast<clang::VarDecl>(decl);
@@ -706,6 +890,12 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
return llvm::dyn_cast<clang::FunctionDecl>(decl);
clang::DeclContext *parent = GetParentDeclContext(PdbSymUid(func_id));
+ std::string context_name;
+ if (clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(parent)) {
+ context_name = ns->getQualifiedNameAsString();
+ } else if (clang::TagDecl *tag = llvm::dyn_cast<clang::TagDecl>(parent)) {
+ context_name = tag->getQualifiedNameAsString();
+ }
CVSymbol cvs = m_index.ReadSymbolRecord(func_id);
ProcSym proc(static_cast<SymbolRecordKind>(cvs.kind()));
@@ -713,6 +903,8 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
PdbTypeSymId type_id(proc.FunctionType);
clang::QualType qt = GetOrCreateType(type_id);
+ if (qt.isNull())
+ return nullptr;
clang::StorageClass storage = clang::SC_None;
if (proc.Kind == SymbolRecordKind::ProcSym)
@@ -723,11 +915,19 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
CompilerType func_ct = ToCompilerType(qt);
+ llvm::StringRef proc_name = proc.Name;
+ proc_name.consume_front(context_name);
+ proc_name.consume_front("::");
+
clang::FunctionDecl *function_decl = m_clang.CreateFunctionDeclaration(
- parent, proc.Name.str().c_str(), func_ct, storage, false);
+ parent, proc_name.str().c_str(), func_ct, storage, false);
lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);
m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;
+ DeclStatus status;
+ status.resolved = true;
+ status.uid = toOpaqueUid(func_id);
+ m_decl_to_status.insert({function_decl, status});
CreateFunctionParameters(func_id, *function_decl, func_type->getNumParams());
@@ -866,6 +1066,180 @@ PdbAstBuilder::CreateProcedureType(const ProcedureRecord &proc) {
func_sig_ast_type.GetOpaqueQualType());
}
+static bool isTagDecl(clang::DeclContext &context) {
+ return !!llvm::dyn_cast<clang::TagDecl>(&context);
+}
+
+static bool isFunctionDecl(clang::DeclContext &context) {
+ return !!llvm::dyn_cast<clang::FunctionDecl>(&context);
+}
+
+static bool isBlockDecl(clang::DeclContext &context) {
+ return !!llvm::dyn_cast<clang::BlockDecl>(&context);
+}
+
+void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf(
+ llvm::Optional<llvm::StringRef> parent) {
+ TypeIndex ti{m_index.tpi().TypeIndexBegin()};
+ for (const CVType &cvt : m_index.tpi().typeArray()) {
+ PdbTypeSymId tid{ti};
+ ++ti;
+
+ if (!IsTagRecord(cvt))
+ continue;
+
+ CVTagRecord tag = CVTagRecord::create(cvt);
+
+ if (!parent.hasValue()) {
+ clang::QualType qt = GetOrCreateType(tid);
+ CompleteType(qt);
+ continue;
+ }
+
+ // Call CreateDeclInfoForType unconditionally so that the namespace info
+ // gets created. But only call CreateRecordType if the namespace name
+ // matches.
+ clang::DeclContext *context = nullptr;
+ std::string uname;
+ std::tie(context, uname) = CreateDeclInfoForType(tag.asTag(), tid.index);
+ if (!context->isNamespace())
+ continue;
+
+ clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(context);
+ std::string actual_ns = ns->getQualifiedNameAsString();
+ if (llvm::StringRef(actual_ns).startswith(*parent)) {
+ clang::QualType qt = GetOrCreateType(tid);
+ CompleteType(qt);
+ continue;
+ }
+ }
+
+ uint32_t module_count = m_index.dbi().modules().getModuleCount();
+ for (uint16_t modi = 0; modi < module_count; ++modi) {
+ CompilandIndexItem &cii = m_index.compilands().GetOrCreateCompiland(modi);
+ const CVSymbolArray &symbols = cii.m_debug_stream.getSymbolArray();
+ auto iter = symbols.begin();
+ while (iter != symbols.end()) {
+ PdbCompilandSymId sym_id{modi, iter.offset()};
+
+ switch (iter->kind()) {
+ case S_GPROC32:
+ case S_LPROC32:
+ GetOrCreateFunctionDecl(sym_id);
+ iter = symbols.at(getScopeEndOffset(*iter));
+ break;
+ case S_GDATA32:
+ case S_GTHREAD32:
+ case S_LDATA32:
+ case S_LTHREAD32:
+ GetOrCreateVariableDecl(PdbCompilandSymId(modi, 0), sym_id);
+ ++iter;
+ break;
+ default:
+ ++iter;
+ continue;
+ }
+ }
+ }
+}
+
+static CVSymbolArray skipFunctionParameters(clang::Decl &decl,
+ const CVSymbolArray &symbols) {
+ clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>(&decl);
+ if (!func_decl)
+ return symbols;
+ unsigned int params = func_decl->getNumParams();
+ if (params == 0)
+ return symbols;
+
+ CVSymbolArray result = symbols;
+
+ while (!result.empty()) {
+ if (params == 0)
+ return result;
+
+ CVSymbol sym = *result.begin();
+ result.drop_front();
+
+ if (!isLocalVariableType(sym.kind()))
+ continue;
+
+ --params;
+ }
+ return result;
+}
+
+void PdbAstBuilder::ParseBlockChildren(PdbCompilandSymId block_id) {
+ CVSymbol sym = m_index.ReadSymbolRecord(block_id);
+ lldbassert(sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32 ||
+ sym.kind() == S_BLOCK32);
+ CompilandIndexItem &cii =
+ m_index.compilands().GetOrCreateCompiland(block_id.modi);
+ CVSymbolArray symbols =
+ cii.m_debug_stream.getSymbolArrayForScope(block_id.offset);
+
+ // Function parameters should already have been created when the function was
+ // parsed.
+ if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32)
+ symbols =
+ skipFunctionParameters(*m_uid_to_decl[toOpaqueUid(block_id)], symbols);
+
+ auto begin = symbols.begin();
+ while (begin != symbols.end()) {
+ PdbCompilandSymId child_sym_id(block_id.modi, begin.offset());
+ GetOrCreateSymbolForId(child_sym_id);
+ if (begin->kind() == S_BLOCK32) {
+ ParseBlockChildren(child_sym_id);
+ begin = symbols.at(getScopeEndOffset(*begin));
+ }
+ ++begin;
+ }
+}
+
+void PdbAstBuilder::ParseDeclsForSimpleContext(clang::DeclContext &context) {
+
+ clang::Decl *decl = clang::Decl::castFromDeclContext(&context);
+ lldbassert(decl);
+
+ auto iter = m_decl_to_status.find(decl);
+ lldbassert(iter != m_decl_to_status.end());
+
+ if (auto *tag = llvm::dyn_cast<clang::TagDecl>(&context)) {
+ CompleteTagDecl(*tag);
+ return;
+ }
+
+ if (isFunctionDecl(context) || isBlockDecl(context)) {
+ PdbCompilandSymId block_id = PdbSymUid(iter->second.uid).asCompilandSym();
+ ParseBlockChildren(block_id);
+ }
+}
+
+void PdbAstBuilder::ParseDeclsForContext(clang::DeclContext &context) {
+ // Namespaces aren't explicitly represented in the debug info, and the only
+ // way to parse them is to parse all type info, demangling every single type
+ // and trying to reconstruct the DeclContext hierarchy this way. Since this
+ // is an expensive operation, we have to special case it so that we do other
+ // work (such as parsing the items that appear within the namespaces) at the
+ // same time.
+ if (context.isTranslationUnit()) {
+ ParseAllNamespacesPlusChildrenOf(llvm::None);
+ return;
+ }
+
+ if (context.isNamespace()) {
+ clang::NamespaceDecl &ns = *llvm::dyn_cast<clang::NamespaceDecl>(&context);
+ std::string qname = ns.getQualifiedNameAsString();
+ ParseAllNamespacesPlusChildrenOf(llvm::StringRef{qname});
+ return;
+ }
+
+ if (isTagDecl(context) || isFunctionDecl(context) || isBlockDecl(context)) {
+ ParseDeclsForSimpleContext(context);
+ return;
+ }
+}
+
CompilerDecl PdbAstBuilder::ToCompilerDecl(clang::Decl &decl) {
return {&m_clang, &decl};
}
@@ -879,4 +1253,9 @@ PdbAstBuilder::ToCompilerDeclContext(clang::DeclContext &context) {
return {&m_clang, &context};
}
+clang::DeclContext *
+PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) {
+ return static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());
+}
+
void PdbAstBuilder::Dump(Stream &stream) { m_clang.Dump(stream); }
OpenPOWER on IntegriCloud