[Lldb-commits] [lldb] [lldb][NativePDB] Use decl context from a method's class (PR #199221)
via lldb-commits
lldb-commits at lists.llvm.org
Thu May 28 02:12:31 PDT 2026
================
@@ -360,6 +360,79 @@ PdbAstBuilderClang::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {
return {context, std::string(uname)};
}
+std::pair<clang::DeclContext *, std::string>
+PdbAstBuilderClang::CreateDeclInfoForCompilandSymbol(PdbCompilandSymId uid) {
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CVSymbol sym = index.ReadSymbolRecord(uid);
+
+ llvm::StringRef symbol_name = getSymbolName(sym);
+
+ std::optional<PdbTypeSymId> func_id = GetFunctionType(sym);
+ if (!func_id || !symbol_name.contains("::"))
+ return CreateDeclInfoForUndecoratedName(symbol_name);
+
+ // Try to get the context from class type of an LF_MFUNCTION.
+ // For some types, we might not find a class type.
+ auto get_member_fn_context = [&]() -> clang::DeclContext * {
+ TypeIndex id = func_id->index;
+
+ if (func_id->is_ipi) {
+ // Type from IPI, for example from S_INLINESITE
+ std::optional<CVType> func_id_type =
+ index.ipi().tryGetType(func_id->index);
+ if (!func_id_type || func_id_type->kind() != LF_MFUNC_ID)
+ return nullptr;
+
+ MemberFuncIdRecord record;
+ llvm::Error err = TypeDeserializer::deserializeAs<MemberFuncIdRecord>(
+ *func_id_type, record);
+ if (err) {
+ llvm::consumeError(std::move(err));
+ return nullptr;
+ }
+
+ id = record.FunctionType;
+ }
+
+ std::optional<CVType> func_type = index.tpi().tryGetType(id);
+ if (!func_type || func_type->kind() != LF_MFUNCTION)
+ return nullptr;
+
+ MemberFunctionRecord mfr(TypeRecordKind::MemberFunction);
+
+ llvm::Error err =
+ TypeDeserializer::deserializeAs<MemberFunctionRecord>(*func_type, mfr);
+ if (err || mfr.ClassType.isNoneType()) {
+ llvm::consumeError(std::move(err));
+ return nullptr;
+ }
+
+ clang::QualType qt = GetOrCreateClangType(mfr.ClassType);
+ if (qt.isNull())
+ return nullptr;
+ clang::TagDecl *tag = qt->getAsTagDecl();
+ if (!tag)
+ return nullptr;
+
+ return clang::TagDecl::castToDeclContext(tag);
+ };
+
+ clang::DeclContext *context = get_member_fn_context();
+ if (!context)
+ return CreateDeclInfoForUndecoratedName(symbol_name);
+
+ MSVCUndecoratedNameParser parser(symbol_name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specifiers =
+ parser.GetSpecifiers();
+ if (specifiers.size() < 2) {
+ assert(false && "Member function name with less than two scopes");
+ return CreateDeclInfoForUndecoratedName(symbol_name);
+ }
+ return {context, std::string(specifiers.back().GetFullName())};
----------------
Nerixyz wrote:
> I think `std::string(specifiers.back().GetFullName())` is the reason why we get the full name of the method of a lambda. Can we use the base_name instead to just get the base name of the method?
We didn't use this return value at here. Only `.first` was used. I removed that second value ([`22a6e5c` (this PR)](https://github.com/llvm/llvm-project/pull/199221/commits/22a6e5c2121932247fa60cba1688c69d4f2289a3)).
[`PdbAstBuilderClang::GetOrCreateFunctionDecl`](https://github.com/llvm/llvm-project/blob/0513c9cba2a02fb853b0af385c0b47503e6678ff/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp#L1057-L1065) is the reason we get the full name. It gets the context name from the decl context it retrieves. But there, we can be a bit smarter. If the function name doesn't start with the context, we can instead use the basename. I did that in [`26b0b74` (this PR)](https://github.com/llvm/llvm-project/pull/199221/commits/26b0b7406a15fcff210631e40d9871f0ddfe583b).
https://github.com/llvm/llvm-project/pull/199221
More information about the lldb-commits
mailing list