diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -196,6 +196,11 @@ ClangASTMetadata *GetMetadata(const clang::Decl *object); ClangASTMetadata *GetMetadata(const clang::Type *object); + void SetCXXRecordDeclAccess(const clang::CXXRecordDecl *object, + clang::AccessSpecifier access); + clang::AccessSpecifier + GetCXXRecordDeclAccess(const clang::CXXRecordDecl *object); + // Basic Types CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size) override; @@ -1080,6 +1085,12 @@ /// Maps Types to their associated ClangASTMetadata. TypeMetadataMap m_type_metadata; + typedef llvm::DenseMap + CXXRecordDeclAccessMap; + /// Maps CXXRecordDecl to their most recent added method/field's + /// AccessSpecifier. + CXXRecordDeclAccessMap m_cxx_record_decl_access; + /// The sema associated that is currently used to build this ASTContext. /// May be null if we are already done parsing this ASTContext or the /// ASTContext wasn't created by parsing source code. diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -1345,7 +1345,30 @@ bool IsValueParam(const clang::TemplateArgument &argument) { return argument.getKind() == TemplateArgument::Integral; } + +void AddAccessSpecifierDecl(clang::CXXRecordDecl *cxx_record_decl, + ASTContext &ct, + clang::AccessSpecifier previous_access, + clang::AccessSpecifier access_specifier) { + if (!cxx_record_decl->isClass() && !cxx_record_decl->isStruct()) + return; + if (previous_access != access_specifier) { + // For struct, don't add AS_public if it's the first AccessSpecDecl. + // For class, don't add AS_private if it's the first AccessSpecDecl. + if ((cxx_record_decl->isStruct() && + previous_access == clang::AccessSpecifier::AS_none && + access_specifier == clang::AccessSpecifier::AS_public) || + (cxx_record_decl->isClass() && + previous_access == clang::AccessSpecifier::AS_none && + access_specifier == clang::AccessSpecifier::AS_private)) { + return; + } + cxx_record_decl->addDecl( + AccessSpecDecl::Create(ct, access_specifier, cxx_record_decl, + SourceLocation(), SourceLocation())); + } } +} // namespace static TemplateParameterList *CreateTemplateParameterList( ASTContext &ast, @@ -2552,6 +2575,22 @@ return nullptr; } +void TypeSystemClang::SetCXXRecordDeclAccess(const clang::CXXRecordDecl *object, + clang::AccessSpecifier access) { + if (access == clang::AccessSpecifier::AS_none) + m_cxx_record_decl_access.erase(object); + else + m_cxx_record_decl_access[object] = access; +} + +clang::AccessSpecifier +TypeSystemClang::GetCXXRecordDeclAccess(const clang::CXXRecordDecl *object) { + auto It = m_cxx_record_decl_access.find(object); + if (It != m_cxx_record_decl_access.end()) + return It->second; + return clang::AccessSpecifier::AS_none; +} + clang::DeclContext * TypeSystemClang::GetDeclContextForType(const CompilerType &type) { return GetDeclContextForType(ClangUtil::GetQualType(type)); @@ -7276,9 +7315,17 @@ } if (field) { - field->setAccess( - TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access)); - + clang::AccessSpecifier access_specifier = + TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access); + field->setAccess(access_specifier); + + if (clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast(record_decl)) { + AddAccessSpecifierDecl(cxx_record_decl, ast->getASTContext(), + ast->GetCXXRecordDeclAccess(cxx_record_decl), + access_specifier); + ast->SetCXXRecordDeclAccess(cxx_record_decl, access_specifier); + } record_decl->addDecl(field); VerifyDecl(field); @@ -7657,6 +7704,11 @@ cxx_method_decl->setParams(llvm::ArrayRef(params)); + AddAccessSpecifierDecl(cxx_record_decl, getASTContext(), + GetCXXRecordDeclAccess(cxx_record_decl), + access_specifier); + SetCXXRecordDeclAccess(cxx_record_decl, access_specifier); + cxx_record_decl->addDecl(cxx_method_decl); // Sometimes the debug info will mention a constructor (default/copy/move), @@ -8190,6 +8242,11 @@ if (qual_type.isNull()) return false; + TypeSystemClang *lldb_ast = + llvm::dyn_cast(type.GetTypeSystem()); + if (lldb_ast == nullptr) + return false; + // Make sure we use the same methodology as // TypeSystemClang::StartTagDeclarationDefinition() as to how we start/end // the definition. @@ -8220,6 +8277,8 @@ cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); cxx_record_decl->setHasExternalLexicalStorage(false); cxx_record_decl->setHasExternalVisibleStorage(false); + lldb_ast->SetCXXRecordDeclAccess(cxx_record_decl, + clang::AccessSpecifier::AS_none); return true; } } @@ -8233,10 +8292,6 @@ if (enum_decl->isCompleteDefinition()) return true; - TypeSystemClang *lldb_ast = - llvm::dyn_cast(type.GetTypeSystem()); - if (lldb_ast == nullptr) - return false; clang::ASTContext &ast = lldb_ast->getASTContext(); /// TODO This really needs to be fixed. diff --git a/lldb/test/Shell/SymbolFile/NativePDB/tag-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/tag-types.cpp --- a/lldb/test/Shell/SymbolFile/NativePDB/tag-types.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/tag-types.cpp @@ -11,16 +11,23 @@ struct Struct { // Test builtin types, which are represented by special CodeView type indices. bool B; +private: char C; +public: signed char SC; +protected: unsigned char UC; char16_t C16; char32_t C32; +protected: wchar_t WC; short S; unsigned short US; +public: int I; +private: unsigned int UI; +public: long L; unsigned long UL; long long LL; @@ -32,15 +39,20 @@ // Test class class Class { -public: // Test pointers to builtin types, which are represented by different special // CodeView type indices. bool *PB; +public: char *PC; +private: signed char *PSC; +protected: unsigned char *PUC; +private: char16_t *PC16; +public: char32_t *PC32; +private: wchar_t *PWC; short *PS; unsigned short *PUS; @@ -155,16 +167,22 @@ // CHECK-NEXT: (lldb) type lookup -- Struct // CHECK-NEXT: struct Struct { // CHECK-NEXT: bool B; +// CHECK-NEXT: private: // CHECK-NEXT: char C; +// CHECK-NEXT: public: // CHECK-NEXT: signed char SC; +// CHECK-NEXT: protected: // CHECK-NEXT: unsigned char UC; // CHECK-NEXT: char16_t C16; // CHECK-NEXT: char32_t C32; // CHECK-NEXT: wchar_t WC; // CHECK-NEXT: short S; // CHECK-NEXT: unsigned short US; +// CHECK-NEXT: public: // CHECK-NEXT: int I; +// CHECK-NEXT: private: // CHECK-NEXT: unsigned int UI; +// CHECK-NEXT: public: // CHECK-NEXT: long L; // CHECK-NEXT: unsigned long UL; // CHECK-NEXT: long long LL; @@ -176,11 +194,17 @@ // CHECK-NEXT: (lldb) type lookup -- Class // CHECK-NEXT: class Class { // CHECK-NEXT: bool *PB; +// CHECK-NEXT: public: // CHECK-NEXT: char *PC; +// CHECK-NEXT: private: // CHECK-NEXT: signed char *PSC; +// CHECK-NEXT: protected: // CHECK-NEXT: unsigned char *PUC; +// CHECK-NEXT: private: // CHECK-NEXT: char16_t *PC16; +// CHECK-NEXT: public: // CHECK-NEXT: char32_t *PC32; +// CHECK-NEXT: private: // CHECK-NEXT: wchar_t *PWC; // CHECK-NEXT: short *PS; // CHECK-NEXT: unsigned short *PUS; @@ -217,7 +241,8 @@ // CHECK-NEXT: } // CHECK-NEXT: (lldb) type lookup -- Derived // CHECK-NEXT: class Derived : public Class { -// CHECK: Derived &Reference; +// CHECK-NEXT: public: +// CHECK-NEXT: Derived &Reference; // CHECK-NEXT: OneMember Member; // CHECK-NEXT: const OneMember ConstMember; // CHECK-NEXT: volatile OneMember VolatileMember;