Skip to content

Commit d5b6e30

Browse files
committed
[LLDB][Clang] add AccessSpecDecl for methods and fields in RecordType
This allows access type be printed when running `lldb-test -dump-ast` and `lldb-test -dump-clang-ast`. Differential Revision: https://reviews.llvm.org/D115062
1 parent cff1a2e commit d5b6e30

File tree

3 files changed

+100
-9
lines changed

3 files changed

+100
-9
lines changed

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

+62-7
Original file line numberDiff line numberDiff line change
@@ -1345,7 +1345,30 @@ namespace {
13451345
bool IsValueParam(const clang::TemplateArgument &argument) {
13461346
return argument.getKind() == TemplateArgument::Integral;
13471347
}
1348+
1349+
void AddAccessSpecifierDecl(clang::CXXRecordDecl *cxx_record_decl,
1350+
ASTContext &ct,
1351+
clang::AccessSpecifier previous_access,
1352+
clang::AccessSpecifier access_specifier) {
1353+
if (!cxx_record_decl->isClass() && !cxx_record_decl->isStruct())
1354+
return;
1355+
if (previous_access != access_specifier) {
1356+
// For struct, don't add AS_public if it's the first AccessSpecDecl.
1357+
// For class, don't add AS_private if it's the first AccessSpecDecl.
1358+
if ((cxx_record_decl->isStruct() &&
1359+
previous_access == clang::AccessSpecifier::AS_none &&
1360+
access_specifier == clang::AccessSpecifier::AS_public) ||
1361+
(cxx_record_decl->isClass() &&
1362+
previous_access == clang::AccessSpecifier::AS_none &&
1363+
access_specifier == clang::AccessSpecifier::AS_private)) {
1364+
return;
1365+
}
1366+
cxx_record_decl->addDecl(
1367+
AccessSpecDecl::Create(ct, access_specifier, cxx_record_decl,
1368+
SourceLocation(), SourceLocation()));
1369+
}
13481370
}
1371+
} // namespace
13491372

13501373
static TemplateParameterList *CreateTemplateParameterList(
13511374
ASTContext &ast,
@@ -2552,6 +2575,22 @@ ClangASTMetadata *TypeSystemClang::GetMetadata(const clang::Type *object) {
25522575
return nullptr;
25532576
}
25542577

2578+
void TypeSystemClang::SetCXXRecordDeclAccess(const clang::CXXRecordDecl *object,
2579+
clang::AccessSpecifier access) {
2580+
if (access == clang::AccessSpecifier::AS_none)
2581+
m_cxx_record_decl_access.erase(object);
2582+
else
2583+
m_cxx_record_decl_access[object] = access;
2584+
}
2585+
2586+
clang::AccessSpecifier
2587+
TypeSystemClang::GetCXXRecordDeclAccess(const clang::CXXRecordDecl *object) {
2588+
auto It = m_cxx_record_decl_access.find(object);
2589+
if (It != m_cxx_record_decl_access.end())
2590+
return It->second;
2591+
return clang::AccessSpecifier::AS_none;
2592+
}
2593+
25552594
clang::DeclContext *
25562595
TypeSystemClang::GetDeclContextForType(const CompilerType &type) {
25572596
return GetDeclContextForType(ClangUtil::GetQualType(type));
@@ -7276,9 +7315,17 @@ clang::FieldDecl *TypeSystemClang::AddFieldToRecordType(
72767315
}
72777316

72787317
if (field) {
7279-
field->setAccess(
7280-
TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access));
7281-
7318+
clang::AccessSpecifier access_specifier =
7319+
TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access);
7320+
field->setAccess(access_specifier);
7321+
7322+
if (clang::CXXRecordDecl *cxx_record_decl =
7323+
llvm::dyn_cast<CXXRecordDecl>(record_decl)) {
7324+
AddAccessSpecifierDecl(cxx_record_decl, ast->getASTContext(),
7325+
ast->GetCXXRecordDeclAccess(cxx_record_decl),
7326+
access_specifier);
7327+
ast->SetCXXRecordDeclAccess(cxx_record_decl, access_specifier);
7328+
}
72827329
record_decl->addDecl(field);
72837330

72847331
VerifyDecl(field);
@@ -7657,6 +7704,11 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
76577704

76587705
cxx_method_decl->setParams(llvm::ArrayRef<clang::ParmVarDecl *>(params));
76597706

7707+
AddAccessSpecifierDecl(cxx_record_decl, getASTContext(),
7708+
GetCXXRecordDeclAccess(cxx_record_decl),
7709+
access_specifier);
7710+
SetCXXRecordDeclAccess(cxx_record_decl, access_specifier);
7711+
76607712
cxx_record_decl->addDecl(cxx_method_decl);
76617713

76627714
// Sometimes the debug info will mention a constructor (default/copy/move),
@@ -8190,6 +8242,11 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition(
81908242
if (qual_type.isNull())
81918243
return false;
81928244

8245+
TypeSystemClang *lldb_ast =
8246+
llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
8247+
if (lldb_ast == nullptr)
8248+
return false;
8249+
81938250
// Make sure we use the same methodology as
81948251
// TypeSystemClang::StartTagDeclarationDefinition() as to how we start/end
81958252
// the definition.
@@ -8220,6 +8277,8 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition(
82208277
cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
82218278
cxx_record_decl->setHasExternalLexicalStorage(false);
82228279
cxx_record_decl->setHasExternalVisibleStorage(false);
8280+
lldb_ast->SetCXXRecordDeclAccess(cxx_record_decl,
8281+
clang::AccessSpecifier::AS_none);
82238282
return true;
82248283
}
82258284
}
@@ -8233,10 +8292,6 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition(
82338292
if (enum_decl->isCompleteDefinition())
82348293
return true;
82358294

8236-
TypeSystemClang *lldb_ast =
8237-
llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
8238-
if (lldb_ast == nullptr)
8239-
return false;
82408295
clang::ASTContext &ast = lldb_ast->getASTContext();
82418296

82428297
/// TODO This really needs to be fixed.

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

+11
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ class TypeSystemClang : public TypeSystem {
196196
ClangASTMetadata *GetMetadata(const clang::Decl *object);
197197
ClangASTMetadata *GetMetadata(const clang::Type *object);
198198

199+
void SetCXXRecordDeclAccess(const clang::CXXRecordDecl *object,
200+
clang::AccessSpecifier access);
201+
clang::AccessSpecifier
202+
GetCXXRecordDeclAccess(const clang::CXXRecordDecl *object);
203+
199204
// Basic Types
200205
CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
201206
size_t bit_size) override;
@@ -1080,6 +1085,12 @@ class TypeSystemClang : public TypeSystem {
10801085
/// Maps Types to their associated ClangASTMetadata.
10811086
TypeMetadataMap m_type_metadata;
10821087

1088+
typedef llvm::DenseMap<const clang::CXXRecordDecl *, clang::AccessSpecifier>
1089+
CXXRecordDeclAccessMap;
1090+
/// Maps CXXRecordDecl to their most recent added method/field's
1091+
/// AccessSpecifier.
1092+
CXXRecordDeclAccessMap m_cxx_record_decl_access;
1093+
10831094
/// The sema associated that is currently used to build this ASTContext.
10841095
/// May be null if we are already done parsing this ASTContext or the
10851096
/// ASTContext wasn't created by parsing source code.

lldb/test/Shell/SymbolFile/NativePDB/tag-types.cpp

+27-2
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,23 @@
1111
struct Struct {
1212
// Test builtin types, which are represented by special CodeView type indices.
1313
bool B;
14+
private:
1415
char C;
16+
public:
1517
signed char SC;
18+
protected:
1619
unsigned char UC;
1720
char16_t C16;
1821
char32_t C32;
22+
protected:
1923
wchar_t WC;
2024
short S;
2125
unsigned short US;
26+
public:
2227
int I;
28+
private:
2329
unsigned int UI;
30+
public:
2431
long L;
2532
unsigned long UL;
2633
long long LL;
@@ -32,15 +39,20 @@ struct Struct {
3239

3340
// Test class
3441
class Class {
35-
public:
3642
// Test pointers to builtin types, which are represented by different special
3743
// CodeView type indices.
3844
bool *PB;
45+
public:
3946
char *PC;
47+
private:
4048
signed char *PSC;
49+
protected:
4150
unsigned char *PUC;
51+
private:
4252
char16_t *PC16;
53+
public:
4354
char32_t *PC32;
55+
private:
4456
wchar_t *PWC;
4557
short *PS;
4658
unsigned short *PUS;
@@ -155,16 +167,22 @@ int main(int argc, char **argv) {
155167
// CHECK-NEXT: (lldb) type lookup -- Struct
156168
// CHECK-NEXT: struct Struct {
157169
// CHECK-NEXT: bool B;
170+
// CHECK-NEXT: private:
158171
// CHECK-NEXT: char C;
172+
// CHECK-NEXT: public:
159173
// CHECK-NEXT: signed char SC;
174+
// CHECK-NEXT: protected:
160175
// CHECK-NEXT: unsigned char UC;
161176
// CHECK-NEXT: char16_t C16;
162177
// CHECK-NEXT: char32_t C32;
163178
// CHECK-NEXT: wchar_t WC;
164179
// CHECK-NEXT: short S;
165180
// CHECK-NEXT: unsigned short US;
181+
// CHECK-NEXT: public:
166182
// CHECK-NEXT: int I;
183+
// CHECK-NEXT: private:
167184
// CHECK-NEXT: unsigned int UI;
185+
// CHECK-NEXT: public:
168186
// CHECK-NEXT: long L;
169187
// CHECK-NEXT: unsigned long UL;
170188
// CHECK-NEXT: long long LL;
@@ -176,11 +194,17 @@ int main(int argc, char **argv) {
176194
// CHECK-NEXT: (lldb) type lookup -- Class
177195
// CHECK-NEXT: class Class {
178196
// CHECK-NEXT: bool *PB;
197+
// CHECK-NEXT: public:
179198
// CHECK-NEXT: char *PC;
199+
// CHECK-NEXT: private:
180200
// CHECK-NEXT: signed char *PSC;
201+
// CHECK-NEXT: protected:
181202
// CHECK-NEXT: unsigned char *PUC;
203+
// CHECK-NEXT: private:
182204
// CHECK-NEXT: char16_t *PC16;
205+
// CHECK-NEXT: public:
183206
// CHECK-NEXT: char32_t *PC32;
207+
// CHECK-NEXT: private:
184208
// CHECK-NEXT: wchar_t *PWC;
185209
// CHECK-NEXT: short *PS;
186210
// CHECK-NEXT: unsigned short *PUS;
@@ -217,7 +241,8 @@ int main(int argc, char **argv) {
217241
// CHECK-NEXT: }
218242
// CHECK-NEXT: (lldb) type lookup -- Derived
219243
// CHECK-NEXT: class Derived : public Class {
220-
// CHECK: Derived &Reference;
244+
// CHECK-NEXT: public:
245+
// CHECK-NEXT: Derived &Reference;
221246
// CHECK-NEXT: OneMember Member;
222247
// CHECK-NEXT: const OneMember ConstMember;
223248
// CHECK-NEXT: volatile OneMember VolatileMember;

0 commit comments

Comments
 (0)