Skip to content

Commit 565bdb5

Browse files
authored
[lldb] Add SB API to access static constexpr member values (#89730)
The main change is the addition of a new SBTypeStaticField class, representing a static member of a class. It can be retrieved created through SBType::GetStaticFieldWithName. It contains several methods (GetName, GetMangledName, etc.) whose meaning is hopefully obvious. The most interesting method is lldb::SBValue GetConstantValue(lldb::SBTarget) which returns a the value of the field -- if it is a compile time constant. The reason for that is that only constants have their values represented in the clang AST. For non-constants, we need to go back to the module containing that constant, and ask retrieve the associated ValueObjectVariable. That's easy enough if the we are still in the type system of the module (because then the type system will contain the pointer to the module symbol file), but it's hard when the type has been copied into another AST (e.g. during expression evaluation). To do that we would need to walk the ast import chain backwards to find the source TypeSystem, and I haven't found a nice way to do that. Another possibility would be to use the mangled name of the variable to perform a lookup (in all modules). That is sort of what happens when evaluating the variable in an expression (which does work), but I did not want to commit to that implementation as it's not necessary for my use case (and if anyone wants to, he can use the GetMangledName function and perform the lookup manually). The patch adds a couple of new TypeSystem functions to surface the information needed to implement this functionality.
1 parent d86cc73 commit 565bdb5

File tree

13 files changed

+251
-0
lines changed

13 files changed

+251
-0
lines changed

lldb/include/lldb/API/SBTarget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ class LLDB_API SBTarget {
954954
friend class SBSection;
955955
friend class SBSourceManager;
956956
friend class SBSymbol;
957+
friend class SBTypeStaticField;
957958
friend class SBValue;
958959
friend class SBVariablesOptions;
959960

lldb/include/lldb/API/SBType.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,35 @@ class SBTypeMemberFunction {
107107
lldb::TypeMemberFunctionImplSP m_opaque_sp;
108108
};
109109

110+
class LLDB_API SBTypeStaticField {
111+
public:
112+
SBTypeStaticField();
113+
114+
SBTypeStaticField(const lldb::SBTypeStaticField &rhs);
115+
lldb::SBTypeStaticField &operator=(const lldb::SBTypeStaticField &rhs);
116+
117+
~SBTypeStaticField();
118+
119+
explicit operator bool() const;
120+
121+
bool IsValid() const;
122+
123+
const char *GetName();
124+
125+
const char *GetMangledName();
126+
127+
lldb::SBType GetType();
128+
129+
lldb::SBValue GetConstantValue(lldb::SBTarget target);
130+
131+
protected:
132+
friend class SBType;
133+
134+
explicit SBTypeStaticField(lldb_private::CompilerDecl decl);
135+
136+
std::unique_ptr<lldb_private::CompilerDecl> m_opaque_up;
137+
};
138+
110139
class SBType {
111140
public:
112141
SBType();
@@ -182,6 +211,8 @@ class SBType {
182211

183212
lldb::SBTypeMember GetVirtualBaseClassAtIndex(uint32_t idx);
184213

214+
lldb::SBTypeStaticField GetStaticFieldWithName(const char *name);
215+
185216
lldb::SBTypeEnumMemberList GetEnumMembers();
186217

187218
uint32_t GetNumberOfTemplateArguments();
@@ -242,6 +273,7 @@ class SBType {
242273
friend class SBTypeNameSpecifier;
243274
friend class SBTypeMember;
244275
friend class SBTypeMemberFunction;
276+
friend class SBTypeStaticField;
245277
friend class SBTypeList;
246278
friend class SBValue;
247279
friend class SBWatchpoint;

lldb/include/lldb/API/SBValue.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ class LLDB_API SBValue {
426426
friend class SBModule;
427427
friend class SBTarget;
428428
friend class SBThread;
429+
friend class SBTypeStaticField;
429430
friend class SBTypeSummary;
430431
friend class SBValueList;
431432

lldb/include/lldb/Symbol/CompilerDecl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ class CompilerDecl {
7373

7474
CompilerDeclContext GetDeclContext() const;
7575

76+
// If this decl has a type, return it.
77+
CompilerType GetType() const;
78+
7679
// If this decl represents a function, return the return type
7780
CompilerType GetFunctionReturnType() const;
7881

@@ -91,6 +94,10 @@ class CompilerDecl {
9194
/// the subsequent entry, so the topmost entry is the global namespace.
9295
std::vector<lldb_private::CompilerContext> GetCompilerContext() const;
9396

97+
// If decl represents a constant value, return it. Otherwise, return an
98+
// invalid/empty Scalar.
99+
Scalar GetConstantValue() const;
100+
94101
private:
95102
TypeSystem *m_type_system = nullptr;
96103
void *m_opaque_decl = nullptr;

lldb/include/lldb/Symbol/CompilerType.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,8 @@ class CompilerType {
416416
CompilerType GetVirtualBaseClassAtIndex(size_t idx,
417417
uint32_t *bit_offset_ptr) const;
418418

419+
CompilerDecl GetStaticFieldWithName(llvm::StringRef name) const;
420+
419421
uint32_t GetIndexOfFieldWithName(const char *name,
420422
CompilerType *field_compiler_type = nullptr,
421423
uint64_t *bit_offset_ptr = nullptr,

lldb/include/lldb/Symbol/TypeSystem.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "lldb/Symbol/CompilerDecl.h"
2828
#include "lldb/Symbol/CompilerDeclContext.h"
2929
#include "lldb/Symbol/Type.h"
30+
#include "lldb/Utility/Scalar.h"
31+
#include "lldb/lldb-forward.h"
3032
#include "lldb/lldb-private.h"
3133
#include "lldb/lldb-types.h"
3234

@@ -110,6 +112,8 @@ class TypeSystem : public PluginInterface,
110112
virtual std::vector<lldb_private::CompilerContext>
111113
DeclGetCompilerContext(void *opaque_decl);
112114

115+
virtual Scalar DeclGetConstantValue(void *opaque_decl) { return Scalar(); }
116+
113117
virtual CompilerType GetTypeForDecl(void *opaque_decl) = 0;
114118

115119
// CompilerDeclContext functions
@@ -339,6 +343,11 @@ class TypeSystem : public PluginInterface,
339343
GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
340344
uint32_t *bit_offset_ptr) = 0;
341345

346+
virtual CompilerDecl GetStaticFieldWithName(lldb::opaque_compiler_type_t type,
347+
llvm::StringRef name) {
348+
return CompilerDecl();
349+
}
350+
342351
virtual CompilerType GetChildCompilerTypeAtIndex(
343352
lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
344353
bool transparent_pointers, bool omit_empty_base_classes,

lldb/source/API/SBType.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,21 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/API/SBType.h"
10+
#include "Utils.h"
1011
#include "lldb/API/SBDefines.h"
1112
#include "lldb/API/SBModule.h"
1213
#include "lldb/API/SBStream.h"
1314
#include "lldb/API/SBTypeEnumMember.h"
1415
#include "lldb/Core/Mangled.h"
16+
#include "lldb/Core/ValueObjectConstResult.h"
17+
#include "lldb/Symbol/CompilerDecl.h"
1518
#include "lldb/Symbol/CompilerType.h"
1619
#include "lldb/Symbol/Type.h"
1720
#include "lldb/Symbol/TypeSystem.h"
1821
#include "lldb/Utility/ConstString.h"
22+
#include "lldb/Utility/DataExtractor.h"
1923
#include "lldb/Utility/Instrumentation.h"
24+
#include "lldb/Utility/Scalar.h"
2025
#include "lldb/Utility/Stream.h"
2126

2227
#include "llvm/ADT/APSInt.h"
@@ -325,6 +330,79 @@ lldb::SBTypeMemberFunction SBType::GetMemberFunctionAtIndex(uint32_t idx) {
325330
return sb_func_type;
326331
}
327332

333+
SBTypeStaticField::SBTypeStaticField() { LLDB_INSTRUMENT_VA(this); }
334+
335+
SBTypeStaticField::SBTypeStaticField(lldb_private::CompilerDecl decl)
336+
: m_opaque_up(decl ? std::make_unique<CompilerDecl>(decl) : nullptr) {}
337+
338+
SBTypeStaticField::SBTypeStaticField(const SBTypeStaticField &rhs) {
339+
LLDB_INSTRUMENT_VA(this, rhs);
340+
341+
m_opaque_up = clone(rhs.m_opaque_up);
342+
}
343+
344+
SBTypeStaticField &SBTypeStaticField::operator=(const SBTypeStaticField &rhs) {
345+
LLDB_INSTRUMENT_VA(this, rhs);
346+
347+
m_opaque_up = clone(rhs.m_opaque_up);
348+
return *this;
349+
}
350+
351+
SBTypeStaticField::~SBTypeStaticField() { LLDB_INSTRUMENT_VA(this); }
352+
353+
SBTypeStaticField::operator bool() const {
354+
LLDB_INSTRUMENT_VA(this);
355+
356+
return IsValid();
357+
}
358+
359+
bool SBTypeStaticField::IsValid() const {
360+
LLDB_INSTRUMENT_VA(this);
361+
362+
return m_opaque_up != nullptr;
363+
}
364+
365+
const char *SBTypeStaticField::GetName() {
366+
LLDB_INSTRUMENT_VA(this);
367+
368+
if (!IsValid())
369+
return "";
370+
return m_opaque_up->GetName().GetCString();
371+
}
372+
373+
const char *SBTypeStaticField::GetMangledName() {
374+
LLDB_INSTRUMENT_VA(this);
375+
376+
if (!IsValid())
377+
return "";
378+
return m_opaque_up->GetMangledName().GetCString();
379+
}
380+
381+
SBType SBTypeStaticField::GetType() {
382+
LLDB_INSTRUMENT_VA(this);
383+
384+
if (!IsValid())
385+
return SBType();
386+
return SBType(m_opaque_up->GetType());
387+
}
388+
389+
SBValue SBTypeStaticField::GetConstantValue(lldb::SBTarget target) {
390+
LLDB_INSTRUMENT_VA(this, target);
391+
392+
if (!IsValid())
393+
return SBValue();
394+
395+
Scalar value = m_opaque_up->GetConstantValue();
396+
if (!value.IsValid())
397+
return SBValue();
398+
DataExtractor data;
399+
value.GetData(data);
400+
auto value_obj_sp = ValueObjectConstResult::Create(
401+
target.GetSP().get(), m_opaque_up->GetType(), m_opaque_up->GetName(),
402+
data);
403+
return SBValue(std::move(value_obj_sp));
404+
}
405+
328406
lldb::SBType SBType::GetUnqualifiedType() {
329407
LLDB_INSTRUMENT_VA(this);
330408

@@ -438,6 +516,16 @@ SBTypeMember SBType::GetVirtualBaseClassAtIndex(uint32_t idx) {
438516
return sb_type_member;
439517
}
440518

519+
SBTypeStaticField SBType::GetStaticFieldWithName(const char *name) {
520+
LLDB_INSTRUMENT_VA(this, name);
521+
522+
if (!IsValid() || !name)
523+
return SBTypeStaticField();
524+
525+
return SBTypeStaticField(m_opaque_sp->GetCompilerType(/*prefer_dynamic=*/true)
526+
.GetStaticFieldWithName(name));
527+
}
528+
441529
SBTypeEnumMemberList SBType::GetEnumMembers() {
442530
LLDB_INSTRUMENT_VA(this);
443531

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "TypeSystemClang.h"
1010

1111
#include "clang/AST/DeclBase.h"
12+
#include "clang/AST/ExprCXX.h"
1213
#include "llvm/Support/Casting.h"
1314
#include "llvm/Support/FormatAdapters.h"
1415
#include "llvm/Support/FormatVariadic.h"
@@ -1148,6 +1149,8 @@ CompilerType TypeSystemClang::GetTypeForDecl(clang::NamedDecl *decl) {
11481149
return GetTypeForDecl(interface_decl);
11491150
if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl))
11501151
return GetTypeForDecl(tag_decl);
1152+
if (clang::ValueDecl *value_decl = llvm::dyn_cast<clang::ValueDecl>(decl))
1153+
return GetTypeForDecl(value_decl);
11511154
return CompilerType();
11521155
}
11531156

@@ -1159,6 +1162,10 @@ CompilerType TypeSystemClang::GetTypeForDecl(ObjCInterfaceDecl *decl) {
11591162
return GetType(getASTContext().getObjCInterfaceType(decl));
11601163
}
11611164

1165+
CompilerType TypeSystemClang::GetTypeForDecl(clang::ValueDecl *value_decl) {
1166+
return GetType(value_decl->getType());
1167+
}
1168+
11621169
#pragma mark Structure, Unions, Classes
11631170

11641171
void TypeSystemClang::SetOwningModule(clang::Decl *decl,
@@ -5906,6 +5913,36 @@ CompilerType TypeSystemClang::GetVirtualBaseClassAtIndex(
59065913
return CompilerType();
59075914
}
59085915

5916+
CompilerDecl
5917+
TypeSystemClang::GetStaticFieldWithName(lldb::opaque_compiler_type_t type,
5918+
llvm::StringRef name) {
5919+
clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
5920+
switch (qual_type->getTypeClass()) {
5921+
case clang::Type::Record: {
5922+
if (!GetCompleteType(type))
5923+
return CompilerDecl();
5924+
5925+
const clang::RecordType *record_type =
5926+
llvm::cast<clang::RecordType>(qual_type.getTypePtr());
5927+
const clang::RecordDecl *record_decl = record_type->getDecl();
5928+
5929+
clang::DeclarationName decl_name(&getASTContext().Idents.get(name));
5930+
for (NamedDecl *decl : record_decl->lookup(decl_name)) {
5931+
auto *var_decl = dyn_cast<clang::VarDecl>(decl);
5932+
if (!var_decl || var_decl->getStorageClass() != clang::SC_Static)
5933+
continue;
5934+
5935+
return CompilerDecl(this, var_decl);
5936+
}
5937+
break;
5938+
}
5939+
5940+
default:
5941+
break;
5942+
}
5943+
return CompilerDecl();
5944+
}
5945+
59095946
// If a pointer to a pointee type (the clang_type arg) says that it has no
59105947
// children, then we either need to trust it, or override it and return a
59115948
// different result. For example, an "int *" has one child that is an integer,
@@ -9087,6 +9124,21 @@ CompilerType TypeSystemClang::DeclGetFunctionArgumentType(void *opaque_decl,
90879124
return CompilerType();
90889125
}
90899126

9127+
Scalar TypeSystemClang::DeclGetConstantValue(void *opaque_decl) {
9128+
clang::Decl *decl = static_cast<clang::Decl *>(opaque_decl);
9129+
clang::VarDecl *var_decl = llvm::dyn_cast<clang::VarDecl>(decl);
9130+
if (!var_decl)
9131+
return Scalar();
9132+
clang::Expr *init_expr = var_decl->getInit();
9133+
if (!init_expr)
9134+
return Scalar();
9135+
std::optional<llvm::APSInt> value =
9136+
init_expr->getIntegerConstantExpr(getASTContext());
9137+
if (!value)
9138+
return Scalar();
9139+
return Scalar(*value);
9140+
}
9141+
90909142
// CompilerDeclContext functions
90919143

90929144
std::vector<CompilerDecl> TypeSystemClang::DeclContextFindDeclByName(

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "clang/AST/ASTContext.h"
2424
#include "clang/AST/ASTFwd.h"
25+
#include "clang/AST/Decl.h"
2526
#include "clang/AST/TemplateBase.h"
2627
#include "clang/AST/Type.h"
2728
#include "clang/Basic/TargetInfo.h"
@@ -251,6 +252,8 @@ class TypeSystemClang : public TypeSystem {
251252

252253
CompilerType GetTypeForDecl(clang::ObjCInterfaceDecl *objc_decl);
253254

255+
CompilerType GetTypeForDecl(clang::ValueDecl *value_decl);
256+
254257
template <typename RecordDeclType>
255258
CompilerType
256259
GetTypeForIdentifier(llvm::StringRef type_name,
@@ -559,6 +562,8 @@ class TypeSystemClang : public TypeSystem {
559562
std::vector<lldb_private::CompilerContext>
560563
DeclGetCompilerContext(void *opaque_decl) override;
561564

565+
Scalar DeclGetConstantValue(void *opaque_decl) override;
566+
562567
CompilerType GetTypeForDecl(void *opaque_decl) override;
563568

564569
// CompilerDeclContext override functions
@@ -868,6 +873,9 @@ class TypeSystemClang : public TypeSystem {
868873
size_t idx,
869874
uint32_t *bit_offset_ptr) override;
870875

876+
CompilerDecl GetStaticFieldWithName(lldb::opaque_compiler_type_t type,
877+
llvm::StringRef name) override;
878+
871879
static uint32_t GetNumPointeeChildren(clang::QualType type);
872880

873881
CompilerType GetChildCompilerTypeAtIndex(

lldb/source/Symbol/CompilerDecl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "lldb/Symbol/CompilerDecl.h"
1010
#include "lldb/Symbol/CompilerDeclContext.h"
1111
#include "lldb/Symbol/TypeSystem.h"
12+
#include "lldb/Utility/Scalar.h"
1213

1314
using namespace lldb_private;
1415

@@ -24,6 +25,10 @@ CompilerDeclContext CompilerDecl::GetDeclContext() const {
2425
return m_type_system->DeclGetDeclContext(m_opaque_decl);
2526
}
2627

28+
CompilerType CompilerDecl::GetType() const {
29+
return m_type_system->GetTypeForDecl(m_opaque_decl);
30+
}
31+
2732
CompilerType CompilerDecl::GetFunctionReturnType() const {
2833
return m_type_system->DeclGetFunctionReturnType(m_opaque_decl);
2934
}
@@ -52,3 +57,7 @@ std::vector<lldb_private::CompilerContext>
5257
CompilerDecl::GetCompilerContext() const {
5358
return m_type_system->DeclGetCompilerContext(m_opaque_decl);
5459
}
60+
61+
Scalar CompilerDecl::GetConstantValue() const {
62+
return m_type_system->DeclGetConstantValue(m_opaque_decl);
63+
}

0 commit comments

Comments
 (0)