[clang] [libcxxabi] [lldb] [llvm] [DRAFT] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
Michael Buch via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 3 23:50:24 PDT 2025
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/149827
>From a61eb43dd47463a817e2899ec81bab23d5bdc9bc Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 4 Aug 2025 07:49:19 +0100
Subject: [PATCH 1/3] Clang
---
clang/include/clang/Basic/Attr.td | 17 ++++-------------
clang/lib/AST/Mangle.cpp | 26 ++++++++++++++++++++++----
clang/lib/Sema/SemaDecl.cpp | 13 +++++--------
clang/unittests/AST/DeclTest.cpp | 4 ++--
4 files changed, 33 insertions(+), 27 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
- // Label specifies the mangled name for the decl.
- StringArgument<"Label">,
-
- // IsLiteralLabel specifies whether the label is literal (i.e. suppresses
- // the global C symbol prefix) or not. If not, the mangle-suppression prefix
- // ('\01') is omitted from the decl name at the LLVM IR level.
- //
- // Non-literal labels are used by some external AST sources like LLDB.
- BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() == Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..940a04112df40 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,20 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func";
+
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ Out << g_lldb_func_call_label_prefix << ":";
+
+ if (llvm::isa<clang::CXXConstructorDecl>(GD.getDecl()))
+ Out << "C" << GD.getCtorType();
+ else if (llvm::isa<clang::CXXDestructorDecl>(GD.getDecl()))
+ Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size() + 1);
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
@@ -161,10 +175,10 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
// If we have an asm name, then we use it as the mangling.
- // If the label isn't literal, or if this is an alias for an LLVM intrinsic,
- // do not add a "\01" prefix.
- if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+ // If is an alias for an LLVM intrinsic, do not add a "\01" prefix.
+ if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
+
return;
}
@@ -185,7 +199,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
- Out << ALA->getLabel();
+ if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+ else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
- NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
- /*IsLiteralLabel=*/true,
- SE->getStrTokenLoc(0)));
+ NewVD->addAttr(AsmLabelAttr::Create(Context, Label, SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -10345,9 +10343,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (Expr *E = D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
- NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(),
- /*IsLiteralLabel=*/true,
- SE->getStrTokenLoc(0)));
+ NewFD->addAttr(
+ AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -20598,8 +20595,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
LookupOrdinaryName);
AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
AttributeCommonInfo::Form::Pragma());
- AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
- Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info);
+ AsmLabelAttr *Attr =
+ AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), Info);
// If a declaration that:
// 1) declares a function or a variable
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index ed635da683aab..c19ecab646c2a 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -90,8 +90,8 @@ TEST(Decl, AsmLabelAttr) {
NamedDecl *DeclG = *(++DeclS->method_begin());
// Attach asm labels to the decls: one literal, and one not.
- DeclF->addAttr(AsmLabelAttr::Create(Ctx, "foo", /*LiteralLabel=*/true));
- DeclG->addAttr(AsmLabelAttr::Create(Ctx, "goo", /*LiteralLabel=*/false));
+ DeclF->addAttr(AsmLabelAttr::Create(Ctx, "foo", /*IsLLDBFuncLabel=*/false));
+ DeclG->addAttr(AsmLabelAttr::Create(Ctx, "goo", /*IsLLDBFuncLabel=*/true));
// Mangle the decl names.
std::string MangleF, MangleG;
>From 859670495da0778dc2da0b2b68430ad3b896404e Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 4 Aug 2025 07:49:40 +0100
Subject: [PATCH 2/3] Demangler
---
libcxxabi/src/demangle/ItaniumDemangle.h | 2 ++
llvm/include/llvm/Demangle/Demangle.h | 3 +++
llvm/include/llvm/Demangle/ItaniumDemangle.h | 2 ++
llvm/lib/Demangle/ItaniumDemangle.cpp | 10 +++++++---
4 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 6f27da7b9cadf..7b3983bc89367 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -1766,6 +1766,8 @@ class CtorDtorName final : public Node {
template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
+ int getVariant() const { return Variant; }
+
void printLeft(OutputBuffer &OB) const override {
if (IsDtor)
OB += "~";
diff --git a/llvm/include/llvm/Demangle/Demangle.h b/llvm/include/llvm/Demangle/Demangle.h
index d9b08b2d856dc..6af8fad9ceb86 100644
--- a/llvm/include/llvm/Demangle/Demangle.h
+++ b/llvm/include/llvm/Demangle/Demangle.h
@@ -127,6 +127,9 @@ struct ItaniumPartialDemangler {
/// If this symbol describes a constructor or destructor.
DEMANGLE_ABI bool isCtorOrDtor() const;
+ /// If this symbol describes a constructor or destructor.
+ std::optional<int> getCtorOrDtorVariant() const;
+
/// If this symbol describes a function.
DEMANGLE_ABI bool isFunction() const;
diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index 62d427c3966bb..c0db02f8e7fef 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -1766,6 +1766,8 @@ class CtorDtorName final : public Node {
template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
+ int getVariant() const { return Variant; }
+
void printLeft(OutputBuffer &OB) const override {
if (IsDtor)
OB += "~";
diff --git a/llvm/lib/Demangle/ItaniumDemangle.cpp b/llvm/lib/Demangle/ItaniumDemangle.cpp
index 1009cc91ca12a..a5d7a5576fccf 100644
--- a/llvm/lib/Demangle/ItaniumDemangle.cpp
+++ b/llvm/lib/Demangle/ItaniumDemangle.cpp
@@ -560,13 +560,17 @@ bool ItaniumPartialDemangler::hasFunctionQualifiers() const {
}
bool ItaniumPartialDemangler::isCtorOrDtor() const {
+ return getCtorOrDtorVariant().has_value();
+}
+
+std::optional<int> ItaniumPartialDemangler::getCtorOrDtorVariant() const {
const Node *N = static_cast<const Node *>(RootNode);
while (N) {
switch (N->getKind()) {
default:
- return false;
+ return std::nullopt;
case Node::KCtorDtorName:
- return true;
+ return static_cast<const CtorDtorName *>(N)->getVariant();
case Node::KAbiTagAttr:
N = static_cast<const AbiTagAttr *>(N)->Base;
@@ -588,7 +592,7 @@ bool ItaniumPartialDemangler::isCtorOrDtor() const {
break;
}
}
- return false;
+ return std::nullopt;
}
bool ItaniumPartialDemangler::isFunction() const {
>From 9261a5ecb4cf873fce74c2f5ade35fbc99e19eb2 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 4 Aug 2025 07:49:47 +0100
Subject: [PATCH 3/3] LLDB
---
lldb/include/lldb/Expression/Expression.h | 8 +-
lldb/source/Expression/Expression.cpp | 29 +++---
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 34 ++++++-
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 95 +++++++++++++++++--
.../TypeSystem/Clang/TypeSystemClang.cpp | 8 +-
.../TypeSystem/Clang/TypeSystemClang.h | 2 +
lldb/unittests/Expression/ExpressionTest.cpp | 37 +++++---
lldb/unittests/Symbol/TestTypeSystemClang.cpp | 14 +--
8 files changed, 178 insertions(+), 49 deletions(-)
diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h
index 20067f469895b..847226167d584 100644
--- a/lldb/include/lldb/Expression/Expression.h
+++ b/lldb/include/lldb/Expression/Expression.h
@@ -103,11 +103,15 @@ class Expression {
///
/// The format being:
///
-/// <prefix>:<module uid>:<symbol uid>:<name>
+/// <prefix>:<discriminator>:<module uid>:<symbol uid>:<name>
///
/// The label string needs to stay valid for the entire lifetime
/// of this object.
struct FunctionCallLabel {
+ /// Arbitrary string which language plugins can interpret for their
+ /// own needs.
+ llvm::StringRef discriminator;
+
/// Unique identifier of the lldb_private::Module
/// which contains the symbol identified by \c symbol_id.
lldb::user_id_t module_id;
@@ -133,7 +137,7 @@ struct FunctionCallLabel {
///
/// The representation roundtrips through \c fromString:
/// \code{.cpp}
- /// llvm::StringRef encoded = "$__lldb_func:0x0:0x0:_Z3foov";
+ /// llvm::StringRef encoded = "$__lldb_func:blah:0x0:0x0:_Z3foov";
/// FunctionCallLabel label = *fromString(label);
///
/// assert (label.toString() == encoded);
diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp
index 796851ff15ca3..16ecb1d7deef8 100644
--- a/lldb/source/Expression/Expression.cpp
+++ b/lldb/source/Expression/Expression.cpp
@@ -34,10 +34,10 @@ Expression::Expression(ExecutionContextScope &exe_scope)
llvm::Expected<FunctionCallLabel>
lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
- llvm::SmallVector<llvm::StringRef, 4> components;
- label.split(components, ":", /*MaxSplit=*/3);
+ llvm::SmallVector<llvm::StringRef, 5> components;
+ label.split(components, ":", /*MaxSplit=*/4);
- if (components.size() != 4)
+ if (components.size() != 5)
return llvm::createStringError("malformed function call label.");
if (components[0] != FunctionCallLabelPrefix)
@@ -45,8 +45,10 @@ lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
"expected function call label prefix '{0}' but found '{1}' instead.",
FunctionCallLabelPrefix, components[0]));
- llvm::StringRef module_label = components[1];
- llvm::StringRef die_label = components[2];
+ llvm::StringRef discriminator = components[1];
+ llvm::StringRef module_label = components[2];
+ llvm::StringRef die_label = components[3];
+ llvm::StringRef lookup_name = components[4];
lldb::user_id_t module_id = 0;
if (!llvm::to_integer(module_label, module_id))
@@ -58,20 +60,23 @@ lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
return llvm::createStringError(
llvm::formatv("failed to parse symbol ID from '{0}'.", die_label));
- return FunctionCallLabel{/*.module_id=*/module_id,
+ return FunctionCallLabel{/*.discriminator=*/discriminator,
+ /*.module_id=*/module_id,
/*.symbol_id=*/die_id,
- /*.lookup_name=*/components[3]};
+ /*.lookup_name=*/lookup_name};
}
std::string lldb_private::FunctionCallLabel::toString() const {
- return llvm::formatv("{0}:{1:x}:{2:x}:{3}", FunctionCallLabelPrefix,
- module_id, symbol_id, lookup_name)
+ return llvm::formatv("{0}:{1}:{2:x}:{3:x}:{4}", FunctionCallLabelPrefix,
+ discriminator, module_id, symbol_id, lookup_name)
.str();
}
void llvm::format_provider<FunctionCallLabel>::format(
const FunctionCallLabel &label, raw_ostream &OS, StringRef Style) {
- OS << llvm::formatv("FunctionCallLabel{ module_id: {0:x}, symbol_id: {1:x}, "
- "lookup_name: {2} }",
- label.module_id, label.symbol_id, label.lookup_name);
+ OS << llvm::formatv("FunctionCallLabel{ discriminator: {0}, module_id: "
+ "{1:x}, symbol_id: {2:x}, "
+ "lookup_name: {3} }",
+ label.discriminator, label.module_id, label.symbol_id,
+ label.lookup_name);
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 781c1c6c5745d..d079d09e1049a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -250,8 +250,36 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram,
return cv_quals;
}
+static const char *GetMangledOrStructorName(const DWARFDIE &die) {
+ const char *name = die.GetMangledName(/*substitute_name_allowed*/ false);
+ if (name)
+ return name;
+
+ name = die.GetName();
+ if (!name)
+ return nullptr;
+
+ DWARFDIE parent = die.GetParent();
+ if (!parent.IsStructUnionOrClass())
+ return nullptr;
+
+ const char *parent_name = parent.GetName();
+ if (!parent_name)
+ return nullptr;
+
+ // Constructor.
+ if (::strcmp(parent_name, name) == 0)
+ return name;
+
+ // Destructor.
+ if (name[0] == '~' && ::strcmp(parent_name, name + 1))
+ return name;
+
+ return nullptr;
+}
+
static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
- char const *name = die.GetMangledName(/*substitute_name_allowed*/ false);
+ char const *name = GetMangledOrStructorName(die);
if (!name)
return {};
@@ -285,7 +313,9 @@ static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
if (die_id == LLDB_INVALID_UID)
return {};
- return FunctionCallLabel{/*module_id=*/module_id,
+ // Note, discriminator is added by Clang during mangling.
+ return FunctionCallLabel{/*discriminator=*/{},
+ /*module_id=*/module_id,
/*symbol_id=*/die_id,
/*.lookup_name=*/name}
.toString();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 42a66ce75d6d6..c40d0a2600ae8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -7,7 +7,9 @@
//===----------------------------------------------------------------------===//
#include "SymbolFileDWARF.h"
+#include "clang/Basic/ABI.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/Support/Casting.h"
@@ -78,6 +80,7 @@
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
@@ -2482,6 +2485,56 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
return false;
}
+static uint8_t ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+ return 1;
+ case clang::CXXCtorType::Ctor_Base:
+ return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+ llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static uint8_t ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+ return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+ return 1;
+ case clang::CXXDtorType::Dtor_Base:
+ return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+ llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional<uint8_t>
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+ return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+ return std::nullopt;
+
+ if (is_ctor) {
+ if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+ return ClangToItaniumCtorKind(
+ static_cast<clang::CXXCtorType>(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Deleting)
+ return std::nullopt;
+
+ return ClangToItaniumDtorKind(static_cast<clang::CXXDtorType>(structor_kind));
+}
+
llvm::Expected<SymbolContext>
SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
@@ -2494,21 +2547,49 @@ SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) {
// Label was created using a declaration DIE. Need to fetch the definition
// to resolve the function call.
if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) {
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
Module::LookupInfo info(ConstString(label.lookup_name),
- lldb::eFunctionNameTypeFull,
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
lldb::eLanguageTypeUnknown);
m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
return IterationAction::Continue;
- // We don't check whether the specification DIE for this function
- // corresponds to the declaration DIE because the declaration might be in
- // a type-unit but the definition in the compile-unit (and it's
- // specifcation would point to the declaration in the compile-unit). We
- // rely on the mangled name within the module to be enough to find us the
- // unique definition.
+ // TODO: this specification check doesn't work if declaration DIE was in a
+ // type-unit (we should only encode DIEs from .debug_info).
+ auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+ if (!spec)
+ return IterationAction::Continue;
+
+ if (spec != die)
+ return IterationAction::Continue;
+
+ // We're not picking a specific structor variant DIE, so we're done here.
+ if (label.discriminator.empty()) {
+ die = entry;
+ return IterationAction::Continue;
+ }
+
+ const char *mangled =
+ entry.GetMangledName(/*substitute_name_allowed=*/false);
+ if (!mangled)
+ return IterationAction::Continue;
+
+ llvm::ItaniumPartialDemangler D;
+ if (D.partialDemangle(mangled))
+ return IterationAction::Continue;
+
+ // TODO: account for constructor alias (only an issue on Linux)
+ if (D.getCtorOrDtorVariant() !=
+ GetItaniumCtorDtorVariant(label.discriminator).value_or(-1))
+ return IterationAction::Continue;
+
die = entry;
+
return IterationAction::Stop;
});
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 8dd6aa08ba2aa..77ed1a0ad3e39 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -10,6 +10,7 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Basic/ABI.h"
#include "clang/Frontend/ASTConsumers.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/FormatAdapters.h"
@@ -2183,8 +2184,7 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
// This is done separately for member functions in
// AddMethodToCXXRecordType.
if (!asm_label.empty())
- func_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(ast, asm_label,
- /*literal=*/true));
+ func_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(ast, asm_label));
SetOwningModule(func_decl, owning_module);
decl_ctx->addDecl(func_decl);
@@ -7823,8 +7823,8 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext()));
if (!asm_label.empty())
- cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
- getASTContext(), asm_label, /*literal=*/true));
+ cxx_method_decl->addAttr(
+ clang::AsmLabelAttr::CreateImplicit(getASTContext(), asm_label));
// Parameters on member function declarations in DWARF generally don't
// have names, so we omit them when creating the ParmVarDecls.
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 70d613d47f93a..09f3a11eaf7bc 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -18,6 +18,7 @@
#include <set>
#include <string>
#include <utility>
+#include <variant>
#include <vector>
#include "clang/AST/ASTContext.h"
@@ -26,6 +27,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/ABI.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/lldb/unittests/Expression/ExpressionTest.cpp b/lldb/unittests/Expression/ExpressionTest.cpp
index 12f6dd515fd11..ceb567c28ab99 100644
--- a/lldb/unittests/Expression/ExpressionTest.cpp
+++ b/lldb/unittests/Expression/ExpressionTest.cpp
@@ -23,15 +23,15 @@ struct LabelTestCase {
static LabelTestCase g_label_test_cases[] = {
// Failure modes
- {"bar:0x0:0x0:_Z3foov",
+ {"bar:blah:0x0:0x0:_Z3foov",
{},
{"expected function call label prefix '$__lldb_func' but found 'bar' "
"instead."}},
- {"$__lldb_func :0x0:0x0:_Z3foov",
+ {"$__lldb_func :blah:0x0:0x0:_Z3foov",
{},
{"expected function call label prefix '$__lldb_func' but found "
"'$__lldb_func ' instead."}},
- {"$__lldb_funcc:0x0:0x0:_Z3foov",
+ {"$__lldb_funcc:blah:0x0:0x0:_Z3foov",
{},
{"expected function call label prefix '$__lldb_func' but found "
"'$__lldb_funcc' instead."}},
@@ -39,47 +39,52 @@ static LabelTestCase g_label_test_cases[] = {
{"foo", {}, {"malformed function call label."}},
{"$__lldb_func", {}, {"malformed function call label."}},
{"$__lldb_func:", {}, {"malformed function call label."}},
- {"$__lldb_func:0x0:0x0", {}, {"malformed function call label."}},
- {"$__lldb_func:abc:0x0:_Z3foov",
+ {"$__lldb_func:blah", {}, {"malformed function call label."}},
+ {"$__lldb_func:blah:0x0", {}, {"malformed function call label."}},
+ {"$__lldb_func:111:0x0:0x0", {}, {"malformed function call label."}},
+ {"$__lldb_func:111:abc:0x0:_Z3foov",
{},
{"failed to parse module ID from 'abc'."}},
- {"$__lldb_func:-1:0x0:_Z3foov",
+ {"$__lldb_func:111:-1:0x0:_Z3foov",
{},
{"failed to parse module ID from '-1'."}},
- {"$__lldb_func:0x0invalid:0x0:_Z3foov",
+ {"$__lldb_func:111:0x0invalid:0x0:_Z3foov",
{},
{"failed to parse module ID from '0x0invalid'."}},
- {"$__lldb_func:0x0 :0x0:_Z3foov",
+ {"$__lldb_func:111:0x0 :0x0:_Z3foov",
{},
{"failed to parse module ID from '0x0 '."}},
- {"$__lldb_func:0x0:abc:_Z3foov",
+ {"$__lldb_func:blah:0x0:abc:_Z3foov",
{},
{"failed to parse symbol ID from 'abc'."}},
- {"$__lldb_func:0x5:-1:_Z3foov",
+ {"$__lldb_func:blah:0x5:-1:_Z3foov",
{},
{"failed to parse symbol ID from '-1'."}},
- {"$__lldb_func:0x5:0x0invalid:_Z3foov",
+ {"$__lldb_func:blah:0x5:0x0invalid:_Z3foov",
{},
{"failed to parse symbol ID from '0x0invalid'."}},
- {"$__lldb_func:0x5:0x0 :_Z3foov",
+ {"$__lldb_func:blah:0x5:0x0 :_Z3foov",
{},
{"failed to parse symbol ID from '0x0 '."}},
- {"$__lldb_func:0x0:0x0:_Z3foov",
+ {"$__lldb_func:blah:0x0:0x0:_Z3foov",
{
+ /*.discriminator=*/"blah",
/*.module_id=*/0x0,
/*.symbol_id=*/0x0,
/*.lookup_name=*/"_Z3foov",
},
{}},
- {"$__lldb_func:0x0:0x0:abc:def:::a",
+ {"$__lldb_func::0x0:0x0:abc:def:::a",
{
+ /*.discriminator=*/"",
/*.module_id=*/0x0,
/*.symbol_id=*/0x0,
/*.lookup_name=*/"abc:def:::a",
},
{}},
- {"$__lldb_func:0xd2:0xf0:$__lldb_func",
+ {"$__lldb_func:0x45:0xd2:0xf0:$__lldb_func",
{
+ /*.discriminator=*/"0x45",
/*.module_id=*/0xd2,
/*.symbol_id=*/0xf0,
/*.lookup_name=*/"$__lldb_func",
@@ -106,6 +111,7 @@ TEST_P(ExpressionTestFixture, FunctionCallLabel) {
EXPECT_EQ(decoded_or_err->toString(), encoded);
EXPECT_EQ(label_str, encoded);
+ EXPECT_EQ(decoded_or_err->discriminator, label.discriminator);
EXPECT_EQ(decoded_or_err->module_id, label.module_id);
EXPECT_EQ(decoded_or_err->symbol_id, label.symbol_id);
EXPECT_EQ(decoded_or_err->lookup_name, label.lookup_name);
@@ -113,6 +119,7 @@ TEST_P(ExpressionTestFixture, FunctionCallLabel) {
auto roundtrip_or_err = FunctionCallLabel::fromString(label_str);
EXPECT_THAT_EXPECTED(roundtrip_or_err, llvm::Succeeded());
+ EXPECT_EQ(roundtrip_or_err->discriminator, label.discriminator);
EXPECT_EQ(roundtrip_or_err->module_id, label.module_id);
EXPECT_EQ(roundtrip_or_err->symbol_id, label.symbol_id);
EXPECT_EQ(roundtrip_or_err->lookup_name, label.lookup_name);
diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp
index b993b82612497..f673cceae00dd 100644
--- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp
+++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp
@@ -1150,12 +1150,12 @@ TEST_F(TestTypeSystemClang, AsmLabel_CtorDtor) {
is_explicit, is_attr_used, is_artificial);
auto *ctor = m_ast->AddMethodToCXXRecordType(
- t.GetOpaqueQualType(), "S", /*asm_label=*/"$__lldb_func:0x0:0x0:S",
+ t.GetOpaqueQualType(), "S", /*asm_label=*/"$__lldb_func::0x0:0x0:S",
function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static,
is_inline, is_explicit, is_attr_used, is_artificial);
auto *dtor = m_ast->AddMethodToCXXRecordType(
- t.GetOpaqueQualType(), "~S", /*asm_label=*/"$__lldb_func:0x0:0x0:~S",
+ t.GetOpaqueQualType(), "~S", /*asm_label=*/"$__lldb_func::0x0:0x0:~S",
function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static,
is_inline, is_explicit, is_attr_used, is_artificial);
@@ -1181,11 +1181,11 @@ TEST_F(TestTypeSystemClang, AsmLabel_CtorDtor) {
EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape(
m_ast->DeclGetMangledName(ctor).GetStringRef())
.data(),
- "$__lldb_func:0x0:0x0:S");
+ "$__lldb_func:C0:0x0:0x0:S");
EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape(
m_ast->DeclGetMangledName(dtor).GetStringRef())
.data(),
- "$__lldb_func:0x0:0x0:~S");
+ "$__lldb_func:D1:0x0:0x0:~S");
}
struct AsmLabelTestCase {
@@ -1215,10 +1215,10 @@ class TestTypeSystemClangAsmLabel
};
static AsmLabelTestCase g_asm_label_test_cases[] = {
- {/*mangled=*/"$__lldb_func:0x0:0x0:_Z3foov",
+ {/*mangled=*/"$__lldb_func::0x0:0x0:_Z3foov",
/*expected=*/"_Z3foov"},
- {/*mangled=*/"$__lldb_func:0x0:0x0:foo",
- /*expected=*/"$__lldb_func:0x0:0x0:foo"},
+ {/*mangled=*/"$__lldb_func::0x0:0x0:foo",
+ /*expected=*/"$__lldb_func::0x0:0x0:foo"},
{/*mangled=*/"foo",
/*expected=*/"foo"},
{/*mangled=*/"_Z3foov",
More information about the llvm-commits
mailing list