[Lldb-commits] [lldb] 1d84916 - [lldb][NativePDB] Remove uses of cantFail in AST builder (#200452)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Jun 8 08:24:39 PDT 2026
Author: Nerixyz
Date: 2026-06-08T17:24:34+02:00
New Revision: 1d84916abda575472652611ae4cedafc50433b3c
URL: https://github.com/llvm/llvm-project/commit/1d84916abda575472652611ae4cedafc50433b3c
DIFF: https://github.com/llvm/llvm-project/commit/1d84916abda575472652611ae4cedafc50433b3c.diff
LOG: [lldb][NativePDB] Remove uses of cantFail in AST builder (#200452)
As a continuation of #187158, this removes uses of `llvm::cantFail` and
replaces them with logs and early returns.
The motivation for this is the PDB of the
[ExprLanguageNote.test](https://github.com/llvm/llvm-project/blob/c241374079f12aabe5d1db5133cb5d924a3cc1d6/lldb/test/Shell/Expr/TestExprLanguageNote.test).
It's incrementally linked (if the built clang uses link.exe by default).
After some amount of checkouts + rebuilds, the PDB gets (semantically)
corrupted such that some type indices point to incorrect records. While
this is a bug in the MSVC linker, we shouldn't crash if we get these
inputs.
Added:
Modified:
lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp
lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h
Removed:
################################################################################
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
index 83b937f92eeec..e1cdfca57e79e 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
@@ -1,6 +1,7 @@
#include "PdbAstBuilderClang.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/RecordName.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
@@ -61,8 +62,15 @@ struct CreateMethodDecl : public TypeVisitorCallbacks {
assert(method_list_type.kind() == LF_METHODLIST);
MethodOverloadListRecord method_list;
- llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
- method_list_type, method_list));
+ llvm::Error err = TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
+ method_list_type, method_list);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as MethodOverloadList: {0}",
+ method_list_idx);
+ // Continue even if we couldn't deserialize.
+ return llvm::Error::success();
+ }
for (const OneMethodRecord &method : method_list.Methods) {
if (method.getType().getIndex() == func_type_index.getIndex())
@@ -471,8 +479,14 @@ PdbAstBuilderClang::GetParentClangDeclContext(PdbSymUid uid) {
case SymbolKind::S_PROCREF:
case SymbolKind::S_LPROCREF: {
ProcRefSym ref{global.kind()};
- llvm::cantFail(
- SymbolDeserializer::deserializeAs<ProcRefSym>(global, ref));
+ llvm::Error err =
+ SymbolDeserializer::deserializeAs<ProcRefSym>(global, ref);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as ProcRef: {0}",
+ uid.asGlobalSym());
+ return nullptr;
+ }
PdbCompilandSymId cu_sym_id{ref.modi(), ref.SymOffset};
return GetParentClangDeclContext(cu_sym_id);
}
@@ -809,16 +823,21 @@ CompilerType PdbAstBuilderClang::GetOrCreateTypedefType(PdbGlobalSymId id) {
PdbIndex &index = pdb->GetIndex();
CVSymbol sym = index.ReadSymbolRecord(id);
lldbassert(sym.kind() == S_UDT);
- UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+ llvm::Expected<UDTSym> udt = SymbolDeserializer::deserializeAs<UDTSym>(sym);
+ if (!udt) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), udt.takeError(),
+ "Failed to deserialize {1} as UDT: {0}", id);
+ return CompilerType();
+ }
clang::DeclContext *scope = GetParentClangDeclContext(id);
- PdbTypeSymId real_type_id{udt.Type, false};
+ PdbTypeSymId real_type_id{udt->Type, false};
clang::QualType qt = GetOrCreateClangType(real_type_id);
if (qt.isNull() || !scope)
return CompilerType();
- std::string uname = std::string(DropNameScope(udt.Name));
+ std::string uname = std::string(DropNameScope(udt->Name));
CompilerType ct = ToCompilerType(qt).CreateTypedef(
uname.c_str(), ToCompilerDeclContext(scope), 0);
@@ -845,15 +864,25 @@ clang::QualType PdbAstBuilderClang::CreateType(PdbTypeSymId type) {
if (cvt.kind() == LF_MODIFIER) {
ModifierRecord modifier;
- llvm::cantFail(
- TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
+ llvm::Error err =
+ TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as Modifier: {0}", type.index);
+ return {};
+ }
return CreateModifierType(modifier);
}
if (cvt.kind() == LF_POINTER) {
PointerRecord pointer;
- llvm::cantFail(
- TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
+ llvm::Error err =
+ TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as Pointer: {0}", type.index);
+ return {};
+ }
return CreatePointerType(pointer);
}
@@ -868,21 +897,37 @@ clang::QualType PdbAstBuilderClang::CreateType(PdbTypeSymId type) {
if (cvt.kind() == LF_ARRAY) {
ArrayRecord ar;
- llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
+ llvm::Error err = TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as Array: {0}", type.index);
+ return {};
+ }
return CreateArrayType(ar);
}
if (cvt.kind() == LF_PROCEDURE) {
ProcedureRecord pr;
- llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
+ llvm::Error err = TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as Procedure: {0}", type.index);
+ return {};
+ }
return CreateFunctionType(pr.ArgumentList, pr.ReturnType, pr.CallConv,
/*type_quals=*/0);
}
if (cvt.kind() == LF_MFUNCTION) {
MemberFunctionRecord mfr;
- llvm::cantFail(
- TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr));
+ llvm::Error err =
+ TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as MemberFunction: {0}",
+ type.index);
+ return {};
+ }
unsigned int type_quals = 0;
if (!mfr.ThisType.isNoneType()) {
clang::QualType this_type = GetOrCreateClangType(mfr.getThisType());
@@ -971,8 +1016,14 @@ clang::FunctionDecl *PdbAstBuilderClang::CreateFunctionDecl(
CVType cvt = index.tpi().getType(func_ti);
MemberFunctionRecord func_record(static_cast<TypeRecordKind>(cvt.kind()));
- llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(
- cvt, func_record));
+ llvm::Error err =
+ TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, func_record);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as MemberFunction: {0}",
+ func_ti);
+ return nullptr;
+ }
TypeIndex class_index = func_record.getClassType();
CVType parent_cvt = index.tpi().getType(class_index);
@@ -1030,7 +1081,14 @@ clang::FunctionDecl *PdbAstBuilderClang::GetOrCreateInlinedFunctionDecl(
CompilandIndexItem *cii = index.compilands().GetCompiland(inlinesite_id.modi);
CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(inlinesite_id.offset);
InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));
- cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site));
+ llvm::Error err =
+ SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as InlineSite: {0}",
+ inlinesite_id);
+ return nullptr;
+ }
// Inlinee is the id index to the function id record that is inlined.
PdbTypeSymId func_id(inline_site.Inlinee, true);
@@ -1077,8 +1135,14 @@ PdbAstBuilderClang::CreateFunctionDeclFromId(PdbTypeSymId func_tid,
switch (func_cvt->kind()) {
case LF_MFUNC_ID: {
MemberFuncIdRecord mfr;
- cantFail(
- TypeDeserializer::deserializeAs<MemberFuncIdRecord>(*func_cvt, mfr));
+ llvm::Error err =
+ TypeDeserializer::deserializeAs<MemberFuncIdRecord>(*func_cvt, mfr);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} (IPI) as MemberFuncId: {0}",
+ func_tid.index);
+ return nullptr;
+ }
func_name = mfr.getName();
func_ti = mfr.getFunctionType();
PdbTypeSymId class_type_id(mfr.ClassType, false);
@@ -1087,7 +1151,14 @@ PdbAstBuilderClang::CreateFunctionDeclFromId(PdbTypeSymId func_tid,
}
case LF_FUNC_ID: {
FuncIdRecord fir;
- cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(*func_cvt, fir));
+ llvm::Error err =
+ TypeDeserializer::deserializeAs<FuncIdRecord>(*func_cvt, fir);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} (IPI) as FuncId: {0}",
+ func_tid.index);
+ return nullptr;
+ }
func_name = fir.getName();
func_ti = fir.getFunctionType();
parent = FromCompilerDeclContext(GetTranslationUnitDecl());
@@ -1095,8 +1166,13 @@ PdbAstBuilderClang::CreateFunctionDeclFromId(PdbTypeSymId func_tid,
CVType parent_cvt = index.ipi().getType(fir.ParentScope);
if (parent_cvt.kind() == LF_STRING_ID) {
StringIdRecord sir;
- cantFail(
- TypeDeserializer::deserializeAs<StringIdRecord>(parent_cvt, sir));
+ err = TypeDeserializer::deserializeAs<StringIdRecord>(parent_cvt, sir);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} (IPI) as StringId: {0}",
+ fir.ParentScope);
+ return nullptr;
+ }
parent = GetOrCreateNamespaceDecl(sir.String.data(), *parent);
}
}
@@ -1135,7 +1211,12 @@ PdbAstBuilderClang::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
PdbIndex &index = pdb->GetIndex();
CVSymbol cvs = index.ReadSymbolRecord(func_id);
ProcSym proc(static_cast<SymbolRecordKind>(cvs.kind()));
- llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(cvs, proc));
+ llvm::Error err = SymbolDeserializer::deserializeAs<ProcSym>(cvs, proc);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as Proc: {0}", func_id);
+ return nullptr;
+ }
PdbTypeSymId type_id(proc.FunctionType);
clang::QualType qt = GetOrCreateClangType(type_id);
@@ -1215,6 +1296,7 @@ void PdbAstBuilderClang::CreateFunctionParameters(
std::vector<clang::ParmVarDecl *> params;
for (uint32_t i = 0; i < param_count && begin != end;) {
uint32_t record_offset = begin.offset();
+ PdbCompilandSymId sym_id(func_id.modi, record_offset);
CVSymbol sym = *begin++;
TypeIndex param_type;
@@ -1222,29 +1304,52 @@ void PdbAstBuilderClang::CreateFunctionParameters(
switch (sym.kind()) {
case S_REGREL32: {
RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
- cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
+ llvm::Error err =
+ SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as RegRelative: {0}", sym_id);
+ return;
+ }
param_type = reg.Type;
param_name = reg.Name;
break;
}
case S_REGREL32_INDIR: {
RegRelativeIndirSym reg(SymbolRecordKind::RegRelativeIndirSym);
- cantFail(
- SymbolDeserializer::deserializeAs<RegRelativeIndirSym>(sym, reg));
+ llvm::Error err =
+ SymbolDeserializer::deserializeAs<RegRelativeIndirSym>(sym, reg);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as RegRelativeIndir: {0}",
+ sym_id);
+ return;
+ }
param_type = reg.Type;
param_name = reg.Name;
break;
}
case S_REGISTER: {
RegisterSym reg(SymbolRecordKind::RegisterSym);
- cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
+ llvm::Error err =
+ SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as Register: {0}", sym_id);
+ return;
+ }
param_type = reg.Index;
param_name = reg.Name;
break;
}
case S_LOCAL: {
LocalSym local(SymbolRecordKind::LocalSym);
- cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+ llvm::Error err = SymbolDeserializer::deserializeAs<LocalSym>(sym, local);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as Local: {0}", sym_id);
+ return;
+ }
if ((local.Flags & LocalSymFlags::IsParameter) == LocalSymFlags::None)
continue;
param_type = local.Type;
@@ -1332,8 +1437,13 @@ clang::QualType PdbAstBuilderClang::CreateFunctionType(
TpiStream &stream = index.tpi();
CVType args_cvt = stream.getType(args_type_idx);
ArgListRecord args;
- llvm::cantFail(
- TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args));
+ llvm::Error err =
+ TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args);
+ if (err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+ "Failed to deserialize {1} as ArgList: {0}", args_type_idx);
+ return {};
+ }
llvm::ArrayRef<TypeIndex> arg_indices = llvm::ArrayRef(args.ArgIndices);
bool is_variadic = IsCVarArgsFunction(arg_indices);
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp
index 67397d707110b..ec170383c05ae 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp
@@ -158,3 +158,18 @@ PdbFieldListMemberId PdbSymUid::asFieldListMember() const {
result.offset = repr.offset;
return result;
}
+
+void llvm::format_provider<lldb_private::npdb::PdbCompilandSymId>::format(
+ const lldb_private::npdb::PdbCompilandSymId &V, raw_ostream &Stream,
+ StringRef Style) {
+ Stream << "Sym(modi=" << V.modi << ", offset=" << V.offset << ')';
+}
+
+void llvm::format_provider<lldb_private::npdb::PdbGlobalSymId>::format(
+ const lldb_private::npdb::PdbGlobalSymId &V, raw_ostream &Stream,
+ StringRef Style) {
+ Stream << "GlobalSym(";
+ if (V.is_public)
+ Stream << "public, ";
+ Stream << V.offset << ')';
+}
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h
index 3accd38d710e1..59d7f842d1380 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h
@@ -17,12 +17,9 @@
#ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBSYMUID_H
#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBSYMUID_H
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include "llvm/Support/Compiler.h"
-
-#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/lldb-types.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/FormatAdapters.h"
namespace lldb_private {
namespace npdb {
@@ -122,4 +119,18 @@ struct SymbolAndUid {
} // namespace npdb
} // namespace lldb_private
+namespace llvm {
+
+template <> struct format_provider<lldb_private::npdb::PdbCompilandSymId> {
+ static void format(const lldb_private::npdb::PdbCompilandSymId &V,
+ raw_ostream &Stream, StringRef Style);
+};
+
+template <> struct format_provider<lldb_private::npdb::PdbGlobalSymId> {
+ static void format(const lldb_private::npdb::PdbGlobalSymId &V,
+ raw_ostream &Stream, StringRef Style);
+};
+
+} // namespace llvm
+
#endif
More information about the lldb-commits
mailing list