diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp')
| -rw-r--r-- | contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp | 751 |
1 files changed, 491 insertions, 260 deletions
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp index a7578de0dcac..15596cbebd14 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp @@ -12,13 +12,10 @@ #include "llvm/Support/FormatAdapters.h" #include "llvm/Support/FormatVariadic.h" -// C Includes -// C++ Includes #include <mutex> #include <string> #include <vector> -// Other libraries and framework includes // Clang headers like to use NDEBUG inside of them to enable/disable debug // related features using "#ifndef NDEBUG" preprocessor blocks to do one thing @@ -76,7 +73,6 @@ #include "lldb/Core/DumpDataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/Scalar.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Core/UniqueCStringMap.h" @@ -97,6 +93,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" +#include "lldb/Utility/Scalar.h" #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" #ifdef LLDB_ENABLE_ALL @@ -124,8 +121,204 @@ ClangASTContextSupportsLanguage(lldb::LanguageType language) { language == eLanguageTypeRust || language == eLanguageTypeExtRenderScript || // Use Clang for D until there is a proper language plugin for it - language == eLanguageTypeD; -} + language == eLanguageTypeD || + // Open Dylan compiler debug info is designed to be Clang-compatible + language == eLanguageTypeDylan; +} + +// Checks whether m1 is an overload of m2 (as opposed to an override). This is +// called by addOverridesForMethod to distinguish overrides (which share a +// vtable entry) from overloads (which require distinct entries). +bool isOverload(clang::CXXMethodDecl *m1, clang::CXXMethodDecl *m2) { + // FIXME: This should detect covariant return types, but currently doesn't. + lldbassert(&m1->getASTContext() == &m2->getASTContext() && + "Methods should have the same AST context"); + clang::ASTContext &context = m1->getASTContext(); + + const auto *m1Type = llvm::cast<clang::FunctionProtoType>( + context.getCanonicalType(m1->getType())); + + const auto *m2Type = llvm::cast<clang::FunctionProtoType>( + context.getCanonicalType(m2->getType())); + + auto compareArgTypes = [&context](const clang::QualType &m1p, + const clang::QualType &m2p) { + return context.hasSameType(m1p.getUnqualifiedType(), + m2p.getUnqualifiedType()); + }; + + // FIXME: In C++14 and later, we can just pass m2Type->param_type_end() + // as a fourth parameter to std::equal(). + return (m1->getNumParams() != m2->getNumParams()) || + !std::equal(m1Type->param_type_begin(), m1Type->param_type_end(), + m2Type->param_type_begin(), compareArgTypes); +} + +// If decl is a virtual method, walk the base classes looking for methods that +// decl overrides. This table of overridden methods is used by IRGen to +// determine the vtable layout for decl's parent class. +void addOverridesForMethod(clang::CXXMethodDecl *decl) { + if (!decl->isVirtual()) + return; + + clang::CXXBasePaths paths; + + auto find_overridden_methods = + [decl](const clang::CXXBaseSpecifier *specifier, + clang::CXXBasePath &path) { + if (auto *base_record = llvm::dyn_cast<clang::CXXRecordDecl>( + specifier->getType()->getAs<clang::RecordType>()->getDecl())) { + + clang::DeclarationName name = decl->getDeclName(); + + // If this is a destructor, check whether the base class destructor is + // virtual. + if (name.getNameKind() == clang::DeclarationName::CXXDestructorName) + if (auto *baseDtorDecl = base_record->getDestructor()) { + if (baseDtorDecl->isVirtual()) { + path.Decls = baseDtorDecl; + return true; + } else + return false; + } + + // Otherwise, search for name in the base class. + for (path.Decls = base_record->lookup(name); !path.Decls.empty(); + path.Decls = path.Decls.slice(1)) { + if (auto *method_decl = + llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front())) + if (method_decl->isVirtual() && !isOverload(decl, method_decl)) { + path.Decls = method_decl; + return true; + } + } + } + + return false; + }; + + if (decl->getParent()->lookupInBases(find_overridden_methods, paths)) { + for (auto *overridden_decl : paths.found_decls()) + decl->addOverriddenMethod( + llvm::cast<clang::CXXMethodDecl>(overridden_decl)); + } +} +} + +static lldb::addr_t GetVTableAddress(Process &process, + VTableContextBase &vtable_ctx, + ValueObject &valobj, + const ASTRecordLayout &record_layout) { + // Retrieve type info + CompilerType pointee_type; + CompilerType this_type(valobj.GetCompilerType()); + uint32_t type_info = this_type.GetTypeInfo(&pointee_type); + if (!type_info) + return LLDB_INVALID_ADDRESS; + + // Check if it's a pointer or reference + bool ptr_or_ref = false; + if (type_info & (eTypeIsPointer | eTypeIsReference)) { + ptr_or_ref = true; + type_info = pointee_type.GetTypeInfo(); + } + + // We process only C++ classes + const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus; + if ((type_info & cpp_class) != cpp_class) + return LLDB_INVALID_ADDRESS; + + // Calculate offset to VTable pointer + lldb::offset_t vbtable_ptr_offset = + vtable_ctx.isMicrosoft() ? record_layout.getVBPtrOffset().getQuantity() + : 0; + + if (ptr_or_ref) { + // We have a pointer / ref to object, so read + // VTable pointer from process memory + + if (valobj.GetAddressTypeOfChildren() != eAddressTypeLoad) + return LLDB_INVALID_ADDRESS; + + auto vbtable_ptr_addr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + if (vbtable_ptr_addr == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + vbtable_ptr_addr += vbtable_ptr_offset; + + Status err; + return process.ReadPointerFromMemory(vbtable_ptr_addr, err); + } + + // We have an object already read from process memory, + // so just extract VTable pointer from it + + DataExtractor data; + Status err; + auto size = valobj.GetData(data, err); + if (err.Fail() || vbtable_ptr_offset + data.GetAddressByteSize() > size) + return LLDB_INVALID_ADDRESS; + + return data.GetPointer(&vbtable_ptr_offset); +} + +static int64_t ReadVBaseOffsetFromVTable(Process &process, + VTableContextBase &vtable_ctx, + lldb::addr_t vtable_ptr, + const CXXRecordDecl *cxx_record_decl, + const CXXRecordDecl *base_class_decl) { + if (vtable_ctx.isMicrosoft()) { + clang::MicrosoftVTableContext &msoft_vtable_ctx = + static_cast<clang::MicrosoftVTableContext &>(vtable_ctx); + + // Get the index into the virtual base table. The + // index is the index in uint32_t from vbtable_ptr + const unsigned vbtable_index = + msoft_vtable_ctx.getVBTableIndex(cxx_record_decl, base_class_decl); + const lldb::addr_t base_offset_addr = vtable_ptr + vbtable_index * 4; + Status err; + return process.ReadSignedIntegerFromMemory(base_offset_addr, 4, INT64_MAX, + err); + } + + clang::ItaniumVTableContext &itanium_vtable_ctx = + static_cast<clang::ItaniumVTableContext &>(vtable_ctx); + + clang::CharUnits base_offset_offset = + itanium_vtable_ctx.getVirtualBaseOffsetOffset(cxx_record_decl, + base_class_decl); + const lldb::addr_t base_offset_addr = + vtable_ptr + base_offset_offset.getQuantity(); + const uint32_t base_offset_size = process.GetAddressByteSize(); + Status err; + return process.ReadSignedIntegerFromMemory(base_offset_addr, base_offset_size, + INT64_MAX, err); +} + +static bool GetVBaseBitOffset(VTableContextBase &vtable_ctx, + ValueObject &valobj, + const ASTRecordLayout &record_layout, + const CXXRecordDecl *cxx_record_decl, + const CXXRecordDecl *base_class_decl, + int32_t &bit_offset) { + ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (!process) + return false; + + lldb::addr_t vtable_ptr = + GetVTableAddress(*process, vtable_ctx, valobj, record_layout); + if (vtable_ptr == LLDB_INVALID_ADDRESS) + return false; + + auto base_offset = ReadVBaseOffsetFromVTable( + *process, vtable_ctx, vtable_ptr, cxx_record_decl, base_class_decl); + if (base_offset == INT64_MAX) + return false; + + bit_offset = base_offset * 8; + + return true; } typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, ClangASTContext *> @@ -383,7 +576,7 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { if (IK.getLanguage() == InputKind::Asm) { Opts.AsmPreprocessor = 1; } else if (IK.isObjectiveC()) { - Opts.ObjC1 = Opts.ObjC2 = 1; + Opts.ObjC = 1; } LangStandard::Kind LangStd = LangStandard::lang_unspecified; @@ -630,7 +823,6 @@ void ClangASTContext::SetExternalSource( if (ast) { ast->setExternalSource(ast_source_ap); ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(true); - // ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(true); } } @@ -641,7 +833,6 @@ void ClangASTContext::RemoveExternalSource() { llvm::IntrusiveRefCntPtr<ExternalASTSource> empty_ast_source_ap; ast->setExternalSource(empty_ast_source_ap); ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false); - // ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false); } } @@ -803,9 +994,7 @@ TargetInfo *ClangASTContext::getTargetInfo() { static inline bool QualTypeMatchesBitSize(const uint64_t bit_size, ASTContext *ast, QualType qual_type) { uint64_t qual_type_bit_size = ast->getTypeSize(qual_type); - if (qual_type_bit_size == bit_size) - return true; - return false; + return qual_type_bit_size == bit_size; } CompilerType @@ -954,9 +1143,10 @@ CompilerType ClangASTContext::GetBasicType(ASTContext *ast, uint32_t ClangASTContext::GetPointerByteSize() { if (m_pointer_byte_size == 0) - m_pointer_byte_size = GetBasicType(lldb::eBasicTypeVoid) - .GetPointerType() - .GetByteSize(nullptr); + if (auto size = GetBasicType(lldb::eBasicTypeVoid) + .GetPointerType() + .GetByteSize(nullptr)) + m_pointer_byte_size = *size; return m_pointer_byte_size; } @@ -1677,8 +1867,7 @@ CompilerType ClangASTContext::CreateObjCClass(const char *name, } static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) { - return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == - false; + return !ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()); } uint32_t @@ -1984,7 +2173,8 @@ FunctionDecl *ClangASTContext::CreateFunctionDeclaration( CompilerType ClangASTContext::CreateFunctionType( ASTContext *ast, const CompilerType &result_type, const CompilerType *args, - unsigned num_args, bool is_variadic, unsigned type_quals) { + unsigned num_args, bool is_variadic, unsigned type_quals, + clang::CallingConv cc) { if (ast == nullptr) return CompilerType(); // invalid AST @@ -2012,9 +2202,10 @@ CompilerType ClangASTContext::CreateFunctionType( // TODO: Detect calling convention in DWARF? FunctionProtoType::ExtProtoInfo proto_info; + proto_info.ExtInfo = cc; proto_info.Variadic = is_variadic; proto_info.ExceptionSpec = EST_None; - proto_info.TypeQuals = type_quals; + proto_info.TypeQuals = clang::Qualifiers::fromFastMask(type_quals); proto_info.RefQualifier = RQ_None; return CompilerType(ast, @@ -2023,14 +2214,17 @@ CompilerType ClangASTContext::CreateFunctionType( } ParmVarDecl *ClangASTContext::CreateParameterDeclaration( - const char *name, const CompilerType ¶m_type, int storage) { + clang::DeclContext *decl_ctx, const char *name, + const CompilerType ¶m_type, int storage) { ASTContext *ast = getASTContext(); assert(ast != nullptr); - return ParmVarDecl::Create(*ast, ast->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - name && name[0] ? &ast->Idents.get(name) : nullptr, - ClangUtil::GetQualType(param_type), nullptr, - (clang::StorageClass)storage, nullptr); + auto *decl = + ParmVarDecl::Create(*ast, decl_ctx, SourceLocation(), SourceLocation(), + name && name[0] ? &ast->Idents.get(name) : nullptr, + ClangUtil::GetQualType(param_type), nullptr, + (clang::StorageClass)storage, nullptr); + decl_ctx->addDecl(decl); + return decl; } void ClangASTContext::SetFunctionParameters(FunctionDecl *function_decl, @@ -2138,6 +2332,9 @@ ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx, false); // IsFixed if (enum_decl) { + if (decl_ctx) + decl_ctx->addDecl(enum_decl); + // TODO: check if we should be setting the promotion type too? enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type)); @@ -3739,9 +3936,7 @@ bool ClangASTContext::IsCXXClassType(const CompilerType &type) { return false; clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr) - return true; - return false; + return !qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr; } bool ClangASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) { @@ -4313,7 +4508,8 @@ ClangASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, // TODO: the real stride will be >= this value.. find the real one! if (stride) - *stride = element_type.GetByteSize(nullptr); + if (Optional<uint64_t> size = element_type.GetByteSize(nullptr)) + *stride = *size; return element_type; } @@ -4665,6 +4861,8 @@ CompilerType ClangASTContext::CreateTypedefType( decl->setAccess(clang::AS_public); // TODO respect proper access specifier + decl_ctx->addDecl(decl); + // Get a uniqued clang::QualType for the typedef decl type return CompilerType(clang_ast, clang_ast->getTypedefType(decl)); } @@ -5032,6 +5230,20 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type, case clang::BuiltinType::Kind::PseudoObject: case clang::BuiltinType::Kind::UnknownAny: break; + + case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload: + case clang::BuiltinType::OCLIntelSubgroupAVCImePayload: + case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload: + case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload: + case clang::BuiltinType::OCLIntelSubgroupAVCMceResult: + case clang::BuiltinType::OCLIntelSubgroupAVCImeResult: + case clang::BuiltinType::OCLIntelSubgroupAVCRefResult: + case clang::BuiltinType::OCLIntelSubgroupAVCSicResult: + case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout: + case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout: + case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin: + case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin: + break; } break; // All pointer types are represented as unsigned integer encodings. We may @@ -5319,8 +5531,20 @@ static bool ObjCDeclHasIVars(clang::ObjCInterfaceDecl *class_interface_decl, return false; } +static Optional<SymbolFile::ArrayInfo> +GetDynamicArrayInfo(ClangASTContext &ast, SymbolFile *sym_file, + clang::QualType qual_type, + const ExecutionContext *exe_ctx) { + if (qual_type->isIncompleteArrayType()) + if (auto *metadata = ast.GetMetadata(qual_type.getAsOpaquePtr())) + return sym_file->GetDynamicArrayInfoForUID(metadata->GetUserID(), + exe_ctx); + return llvm::None; +} + uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) { + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) { if (!type) return 0; @@ -5342,7 +5566,6 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, case clang::Type::Complex: return 0; - case clang::Type::Record: if (GetCompleteQualType(getASTContext(), qual_type)) { const clang::RecordType *record_type = @@ -5368,7 +5591,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, ->getDecl()); // Skip empty base classes - if (ClangASTContext::RecordHasFields(base_class_decl) == false) + if (!ClangASTContext::RecordHasFields(base_class_decl)) continue; num_children++; @@ -5420,7 +5643,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, clang::QualType pointee_type = pointer_type->getPointeeType(); uint32_t num_pointee_children = CompilerType(getASTContext(), pointee_type) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); // If this type points to a simple type, then it has 1 child if (num_pointee_children == 0) num_children = 1; @@ -5439,6 +5662,14 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, ->getSize() .getLimitedValue(); break; + case clang::Type::IncompleteArray: + if (auto array_info = + GetDynamicArrayInfo(*this, GetSymbolFile(), qual_type, exe_ctx)) + // Only 1-dimensional arrays are supported. + num_children = array_info->element_orders.size() + ? array_info->element_orders.back() + : 0; + break; case clang::Type::Pointer: { const clang::PointerType *pointer_type = @@ -5446,7 +5677,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, clang::QualType pointee_type(pointer_type->getPointeeType()); uint32_t num_pointee_children = CompilerType(getASTContext(), pointee_type) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); if (num_pointee_children == 0) { // We have a pointer to a pointee type that claims it has no children. We // will want to look at @@ -5462,7 +5693,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, clang::QualType pointee_type = reference_type->getPointeeType(); uint32_t num_pointee_children = CompilerType(getASTContext(), pointee_type) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); // If this type points to a simple type, then it has 1 child if (num_pointee_children == 0) num_children = 1; @@ -5475,14 +5706,14 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type) ->getDecl() ->getUnderlyingType()) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; case clang::Type::Auto: num_children = CompilerType(getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; case clang::Type::Elaborated: @@ -5490,14 +5721,14 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, CompilerType( getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; case clang::Type::Paren: num_children = CompilerType(getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; default: break; @@ -5735,10 +5966,10 @@ GetObjCFieldAtIndex(clang::ASTContext *ast, if (is_bitfield && ast) { clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth(); - llvm::APSInt bitfield_apsint; + clang::Expr::EvalResult result; if (bitfield_bit_size_expr && - bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, - *ast)) { + bitfield_bit_size_expr->EvaluateAsInt(result, *ast)) { + llvm::APSInt bitfield_apsint = result.Val.getInt(); *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); } } @@ -5795,10 +6026,11 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, if (is_bitfield) { clang::Expr *bitfield_bit_size_expr = field->getBitWidth(); - llvm::APSInt bitfield_apsint; + clang::Expr::EvalResult result; if (bitfield_bit_size_expr && - bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, + bitfield_bit_size_expr->EvaluateAsInt(result, *getASTContext())) { + llvm::APSInt bitfield_apsint = result.Val.getInt(); *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); } } @@ -6366,6 +6598,10 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( if (!type) return CompilerType(); + auto get_exe_scope = [&exe_ctx]() { + return exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; + }; + clang::QualType parent_qual_type(GetCanonicalQualType(type)); const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass(); @@ -6374,8 +6610,9 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( child_is_base_class = false; language_flags = 0; - const bool idx_is_valid = idx < GetNumChildren(type, omit_empty_base_classes); - uint32_t bit_offset; + const bool idx_is_valid = + idx < GetNumChildren(type, omit_empty_base_classes, exe_ctx); + int32_t bit_offset; switch (parent_type_class) { case clang::Type::Builtin: if (idx_is_valid) { @@ -6420,7 +6657,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( if (omit_empty_base_classes) { base_class_decl = llvm::cast<clang::CXXRecordDecl>( base_class->getType()->getAs<clang::RecordType>()->getDecl()); - if (ClangASTContext::RecordHasFields(base_class_decl) == false) + if (!ClangASTContext::RecordHasFields(base_class_decl)) continue; } @@ -6432,80 +6669,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( if (base_class->isVirtual()) { bool handled = false; if (valobj) { - Status err; - AddressType addr_type = eAddressTypeInvalid; - lldb::addr_t vtable_ptr_addr = - valobj->GetCPPVTableAddress(addr_type); - - if (vtable_ptr_addr != LLDB_INVALID_ADDRESS && - addr_type == eAddressTypeLoad) { - - ExecutionContext exe_ctx(valobj->GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process) { - clang::VTableContextBase *vtable_ctx = - getASTContext()->getVTableContext(); - if (vtable_ctx) { - if (vtable_ctx->isMicrosoft()) { - clang::MicrosoftVTableContext *msoft_vtable_ctx = - static_cast<clang::MicrosoftVTableContext *>( - vtable_ctx); - - if (vtable_ptr_addr) { - const lldb::addr_t vbtable_ptr_addr = - vtable_ptr_addr + - record_layout.getVBPtrOffset().getQuantity(); - - const lldb::addr_t vbtable_ptr = - process->ReadPointerFromMemory(vbtable_ptr_addr, - err); - if (vbtable_ptr != LLDB_INVALID_ADDRESS) { - // Get the index into the virtual base table. The - // index is the index in uint32_t from vbtable_ptr - const unsigned vbtable_index = - msoft_vtable_ctx->getVBTableIndex( - cxx_record_decl, base_class_decl); - const lldb::addr_t base_offset_addr = - vbtable_ptr + vbtable_index * 4; - const uint32_t base_offset = - process->ReadUnsignedIntegerFromMemory( - base_offset_addr, 4, UINT32_MAX, err); - if (base_offset != UINT32_MAX) { - handled = true; - bit_offset = base_offset * 8; - } - } - } - } else { - clang::ItaniumVTableContext *itanium_vtable_ctx = - static_cast<clang::ItaniumVTableContext *>( - vtable_ctx); - if (vtable_ptr_addr) { - const lldb::addr_t vtable_ptr = - process->ReadPointerFromMemory(vtable_ptr_addr, - err); - if (vtable_ptr != LLDB_INVALID_ADDRESS) { - clang::CharUnits base_offset_offset = - itanium_vtable_ctx->getVirtualBaseOffsetOffset( - cxx_record_decl, base_class_decl); - const lldb::addr_t base_offset_addr = - vtable_ptr + base_offset_offset.getQuantity(); - const uint32_t base_offset_size = - process->GetAddressByteSize(); - const uint64_t base_offset = - process->ReadUnsignedIntegerFromMemory( - base_offset_addr, base_offset_size, - UINT32_MAX, err); - if (base_offset < UINT32_MAX) { - handled = true; - bit_offset = base_offset * 8; - } - } - } - } - } - } - } + clang::VTableContextBase *vtable_ctx = + getASTContext()->getVTableContext(); + if (vtable_ctx) + handled = GetVBaseBitOffset(*vtable_ctx, *valobj, + record_layout, cxx_record_decl, + base_class_decl, bit_offset); } if (!handled) bit_offset = record_layout.getVBaseClassOffset(base_class_decl) @@ -6521,9 +6690,11 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( CompilerType base_class_clang_type(getASTContext(), base_class->getType()); child_name = base_class_clang_type.GetTypeName().AsCString(""); - uint64_t base_class_clang_type_bit_size = - base_class_clang_type.GetBitSize( - exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + Optional<uint64_t> size = + base_class_clang_type.GetBitSize(get_exe_scope()); + if (!size) + return {}; + uint64_t base_class_clang_type_bit_size = *size; // Base classes bit sizes should be a multiple of 8 bits in size assert(base_class_clang_type_bit_size % 8 == 0); @@ -6551,8 +6722,11 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( // alignment (field_type_info.second) from the AST context. CompilerType field_clang_type(getASTContext(), field->getType()); assert(field_idx < record_layout.getFieldCount()); - child_byte_size = field_clang_type.GetByteSize( - exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + Optional<uint64_t> size = + field_clang_type.GetByteSize(get_exe_scope()); + if (!size) + return {}; + child_byte_size = *size; const uint32_t child_bit_size = child_byte_size * 8; // Figure out the field offset within the current struct/union/class @@ -6596,8 +6770,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( CompilerType base_class_clang_type( getASTContext(), getASTContext()->getObjCInterfaceType( superclass_interface_decl)); - if (base_class_clang_type.GetNumChildren( - omit_empty_base_classes) > 0) { + if (base_class_clang_type.GetNumChildren(omit_empty_base_classes, + exe_ctx) > 0) { if (idx == 0) { clang::QualType ivar_qual_type( getASTContext()->getObjCInterfaceType( @@ -6664,9 +6838,9 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( } } - // Setting this to UINT32_MAX to make sure we don't compute it + // Setting this to INT32_MAX to make sure we don't compute it // twice... - bit_offset = UINT32_MAX; + bit_offset = INT32_MAX; if (child_byte_offset == static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET)) { @@ -6683,7 +6857,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( if (ClangASTContext::FieldIsBitfield(getASTContext(), ivar_decl, child_bitfield_bit_size)) { - if (bit_offset == UINT32_MAX) + if (bit_offset == INT32_MAX) bit_offset = interface_layout.getFieldOffset( child_idx - superclass_idx); @@ -6723,10 +6897,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( // We have a pointer to an simple type if (idx == 0 && pointee_clang_type.GetCompleteType()) { - child_byte_size = pointee_clang_type.GetByteSize( - exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee_clang_type; + if (Optional<uint64_t> size = + pointee_clang_type.GetByteSize(get_exe_scope())) { + child_byte_size = *size; + child_byte_offset = 0; + return pointee_clang_type; + } } } } @@ -6744,10 +6920,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", static_cast<uint64_t>(idx)); child_name.assign(element_name); - child_byte_size = element_type.GetByteSize( - exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; - return element_type; + if (Optional<uint64_t> size = + element_type.GetByteSize(get_exe_scope())) { + child_byte_size = *size; + child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; + return element_type; + } } } } @@ -6761,10 +6939,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( CompilerType element_type(getASTContext(), array->getElementType()); if (element_type.GetCompleteType()) { child_name = llvm::formatv("[{0}]", idx); - child_byte_size = element_type.GetByteSize( - exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; - return element_type; + if (Optional<uint64_t> size = + element_type.GetByteSize(get_exe_scope())) { + child_byte_size = *size; + child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; + return element_type; + } } } } @@ -6798,10 +6978,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( // We have a pointer to an simple type if (idx == 0) { - child_byte_size = pointee_clang_type.GetByteSize( - exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee_clang_type; + if (Optional<uint64_t> size = + pointee_clang_type.GetByteSize(get_exe_scope())) { + child_byte_size = *size; + child_byte_offset = 0; + return pointee_clang_type; + } } } break; @@ -6833,10 +7015,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( // We have a pointer to an simple type if (idx == 0) { - child_byte_size = pointee_clang_type.GetByteSize( - exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee_clang_type; + if (Optional<uint64_t> size = + pointee_clang_type.GetByteSize(get_exe_scope())) { + child_byte_size = *size; + child_byte_offset = 0; + return pointee_clang_type; + } } } } @@ -7283,14 +7467,14 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, ->getAs<clang::RecordType>() ->getDecl()); if (omit_empty_base_classes && - ClangASTContext::RecordHasFields(base_class_decl) == false) + !ClangASTContext::RecordHasFields(base_class_decl)) continue; CompilerType base_class_clang_type(getASTContext(), base_class->getType()); std::string base_class_type_name( base_class_clang_type.GetTypeName().AsCString("")); - if (base_class_type_name.compare(name) == 0) + if (base_class_type_name == name) return child_idx; ++child_idx; } @@ -7625,7 +7809,7 @@ ClangASTContext::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, return CompilerType(getASTContext(), template_arg.getAsType()); } -llvm::Optional<CompilerType::IntegralTemplateArgument> +Optional<CompilerType::IntegralTemplateArgument> ClangASTContext::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx) { const clang::ClassTemplateSpecializationDecl *template_decl = @@ -7665,11 +7849,16 @@ clang::RecordDecl *ClangASTContext::GetAsRecordDecl(const CompilerType &type) { } clang::TagDecl *ClangASTContext::GetAsTagDecl(const CompilerType &type) { - clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type); - if (qual_type.isNull()) - return nullptr; - else - return qual_type->getAsTagDecl(); + return ClangUtil::GetAsTagDecl(type); +} + +clang::TypedefNameDecl * +ClangASTContext::GetAsTypedefDecl(const CompilerType &type) { + const clang::TypedefType *typedef_type = + llvm::dyn_cast<clang::TypedefType>(ClangUtil::GetQualType(type)); + if (typedef_type) + return typedef_type->getDecl(); + return nullptr; } clang::CXXRecordDecl * @@ -7688,7 +7877,7 @@ ClangASTContext::GetAsObjCInterfaceDecl(const CompilerType &type) { } clang::FieldDecl *ClangASTContext::AddFieldToRecordType( - const CompilerType &type, const char *name, + const CompilerType &type, llvm::StringRef name, const CompilerType &field_clang_type, AccessType access, uint32_t bitfield_bit_size) { if (!type.IsValid() || !field_clang_type.IsValid()) @@ -7698,6 +7887,9 @@ clang::FieldDecl *ClangASTContext::AddFieldToRecordType( if (!ast) return nullptr; clang::ASTContext *clang_ast = ast->getASTContext(); + clang::IdentifierInfo *ident = nullptr; + if (!name.empty()) + ident = &clang_ast->Idents.get(name); clang::FieldDecl *field = nullptr; @@ -7715,14 +7907,14 @@ clang::FieldDecl *ClangASTContext::AddFieldToRecordType( field = clang::FieldDecl::Create( *clang_ast, record_decl, clang::SourceLocation(), clang::SourceLocation(), - name ? &clang_ast->Idents.get(name) : nullptr, // Identifier - ClangUtil::GetQualType(field_clang_type), // Field type - nullptr, // TInfo * - bit_width, // BitWidth - false, // Mutable - clang::ICIS_NoInit); // HasInit - - if (!name) { + ident, // Identifier + ClangUtil::GetQualType(field_clang_type), // Field type + nullptr, // TInfo * + bit_width, // BitWidth + false, // Mutable + clang::ICIS_NoInit); // HasInit + + if (name.empty()) { // Determine whether this field corresponds to an anonymous struct or // union. if (const clang::TagType *TagT = @@ -7758,9 +7950,9 @@ clang::FieldDecl *ClangASTContext::AddFieldToRecordType( field = clang::ObjCIvarDecl::Create( *clang_ast, class_interface_decl, clang::SourceLocation(), clang::SourceLocation(), - name ? &clang_ast->Idents.get(name) : nullptr, // Identifier - ClangUtil::GetQualType(field_clang_type), // Field type - nullptr, // TypeSourceInfo * + ident, // Identifier + ClangUtil::GetQualType(field_clang_type), // Field type + nullptr, // TypeSourceInfo * ConvertAccessTypeToObjCIvarAccessControl(access), bit_width, is_synthesized); @@ -7899,38 +8091,44 @@ void ClangASTContext::SetIsPacked(const CompilerType &type) { } clang::VarDecl *ClangASTContext::AddVariableToRecordType( - const CompilerType &type, const char *name, const CompilerType &var_type, - AccessType access) { - clang::VarDecl *var_decl = nullptr; - + const CompilerType &type, llvm::StringRef name, + const CompilerType &var_type, AccessType access) { if (!type.IsValid() || !var_type.IsValid()) return nullptr; + ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); if (!ast) return nullptr; clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type); - if (record_decl) { - var_decl = clang::VarDecl::Create( - *ast->getASTContext(), // ASTContext & - record_decl, // DeclContext * - clang::SourceLocation(), // clang::SourceLocation StartLoc - clang::SourceLocation(), // clang::SourceLocation IdLoc - name ? &ast->getASTContext()->Idents.get(name) - : nullptr, // clang::IdentifierInfo * - ClangUtil::GetQualType(var_type), // Variable clang::QualType - nullptr, // TypeSourceInfo * - clang::SC_Static); // StorageClass - if (var_decl) { - var_decl->setAccess( - ClangASTContext::ConvertAccessTypeToAccessSpecifier(access)); - record_decl->addDecl(var_decl); + if (!record_decl) + return nullptr; + + clang::VarDecl *var_decl = nullptr; + clang::IdentifierInfo *ident = nullptr; + if (!name.empty()) + ident = &ast->getASTContext()->Idents.get(name); + + var_decl = clang::VarDecl::Create( + *ast->getASTContext(), // ASTContext & + record_decl, // DeclContext * + clang::SourceLocation(), // clang::SourceLocation StartLoc + clang::SourceLocation(), // clang::SourceLocation IdLoc + ident, // clang::IdentifierInfo * + ClangUtil::GetQualType(var_type), // Variable clang::QualType + nullptr, // TypeSourceInfo * + clang::SC_Static); // StorageClass + if (!var_decl) + return nullptr; + + var_decl->setAccess( + ClangASTContext::ConvertAccessTypeToAccessSpecifier(access)); + record_decl->addDecl(var_decl); #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(var_decl); + VerifyDecl(var_decl); #endif - } - } + return var_decl; } @@ -8131,41 +8329,46 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType( return cxx_method_decl; } +void ClangASTContext::AddMethodOverridesForCXXRecordType( + lldb::opaque_compiler_type_t type) { + if (auto *record = GetAsCXXRecordDecl(type)) + for (auto *method : record->methods()) + addOverridesForMethod(method); +} + #pragma mark C++ Base Classes -clang::CXXBaseSpecifier * +std::unique_ptr<clang::CXXBaseSpecifier> ClangASTContext::CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type, AccessType access, bool is_virtual, bool base_of_class) { - if (type) - return new clang::CXXBaseSpecifier( - clang::SourceRange(), is_virtual, base_of_class, - ClangASTContext::ConvertAccessTypeToAccessSpecifier(access), - getASTContext()->getTrivialTypeSourceInfo(GetQualType(type)), - clang::SourceLocation()); - return nullptr; -} + if (!type) + return nullptr; -void ClangASTContext::DeleteBaseClassSpecifiers( - clang::CXXBaseSpecifier **base_classes, unsigned num_base_classes) { - for (unsigned i = 0; i < num_base_classes; ++i) { - delete base_classes[i]; - base_classes[i] = nullptr; - } + return llvm::make_unique<clang::CXXBaseSpecifier>( + clang::SourceRange(), is_virtual, base_of_class, + ClangASTContext::ConvertAccessTypeToAccessSpecifier(access), + getASTContext()->getTrivialTypeSourceInfo(GetQualType(type)), + clang::SourceLocation()); } -bool ClangASTContext::SetBaseClassesForClassType( +bool ClangASTContext::TransferBaseClasses( lldb::opaque_compiler_type_t type, - clang::CXXBaseSpecifier const *const *base_classes, - unsigned num_base_classes) { - if (type) { - clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type); - if (cxx_record_decl) { - cxx_record_decl->setBases(base_classes, num_base_classes); - return true; - } - } - return false; + std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases) { + if (!type) + return false; + clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type); + if (!cxx_record_decl) + return false; + std::vector<clang::CXXBaseSpecifier *> raw_bases; + raw_bases.reserve(bases.size()); + + // Clang will make a copy of them, so it's ok that we pass pointers that we're + // about to destroy. + for (auto &b : bases) + raw_bases.push_back(b.get()); + cxx_record_decl->setBases(raw_bases.data(), raw_bases.size()); + return true; } bool ClangASTContext::SetObjCSuperClass( @@ -8750,44 +8953,63 @@ bool ClangASTContext::CompleteTagDeclarationDefinition( return false; } -bool ClangASTContext::AddEnumerationValueToEnumerationType( - lldb::opaque_compiler_type_t type, - const CompilerType &enumerator_clang_type, const Declaration &decl, - const char *name, int64_t enum_value, uint32_t enum_value_bit_size) { - if (type && enumerator_clang_type.IsValid() && name && name[0]) { - clang::QualType enum_qual_type(GetCanonicalQualType(type)); - - bool is_signed = false; - enumerator_clang_type.IsIntegerType(is_signed); - const clang::Type *clang_type = enum_qual_type.getTypePtr(); - if (clang_type) { - const clang::EnumType *enutype = - llvm::dyn_cast<clang::EnumType>(clang_type); - - if (enutype) { - llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed); - enum_llvm_apsint = enum_value; - clang::EnumConstantDecl *enumerator_decl = - clang::EnumConstantDecl::Create( - *getASTContext(), enutype->getDecl(), clang::SourceLocation(), - name ? &getASTContext()->Idents.get(name) - : nullptr, // Identifier - ClangUtil::GetQualType(enumerator_clang_type), - nullptr, enum_llvm_apsint); - - if (enumerator_decl) { - enutype->getDecl()->addDecl(enumerator_decl); +clang::EnumConstantDecl *ClangASTContext::AddEnumerationValueToEnumerationType( + const CompilerType &enum_type, const Declaration &decl, const char *name, + const llvm::APSInt &value) { + + if (!enum_type || ConstString(name).IsEmpty()) + return nullptr; + + lldbassert(enum_type.GetTypeSystem() == static_cast<TypeSystem *>(this)); + + lldb::opaque_compiler_type_t enum_opaque_compiler_type = + enum_type.GetOpaqueQualType(); + + if (!enum_opaque_compiler_type) + return nullptr; + + clang::QualType enum_qual_type( + GetCanonicalQualType(enum_opaque_compiler_type)); + + const clang::Type *clang_type = enum_qual_type.getTypePtr(); + + if (!clang_type) + return nullptr; + + const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(clang_type); + + if (!enutype) + return nullptr; + + clang::EnumConstantDecl *enumerator_decl = clang::EnumConstantDecl::Create( + *getASTContext(), enutype->getDecl(), clang::SourceLocation(), + name ? &getASTContext()->Idents.get(name) : nullptr, // Identifier + clang::QualType(enutype, 0), nullptr, value); + + if (!enumerator_decl) + return nullptr; + + enutype->getDecl()->addDecl(enumerator_decl); #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(enumerator_decl); + VerifyDecl(enumerator_decl); #endif - return true; - } - } - } - } - return false; + return enumerator_decl; +} + +clang::EnumConstantDecl *ClangASTContext::AddEnumerationValueToEnumerationType( + const CompilerType &enum_type, const Declaration &decl, const char *name, + int64_t enum_value, uint32_t enum_value_bit_size) { + CompilerType underlying_type = + GetEnumerationIntegerType(enum_type.GetOpaqueQualType()); + bool is_signed = false; + underlying_type.IsIntegerType(is_signed); + + llvm::APSInt value(enum_value_bit_size, is_signed); + value = enum_value; + + return AddEnumerationValueToEnumerationType(enum_type, decl, name, value); } CompilerType @@ -8861,6 +9083,11 @@ ClangASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, //---------------------------------------------------------------------- #define DEPTH_INCREMENT 2 +void ClangASTContext::Dump(Stream &s) { + Decl *tu = Decl::castFromDeclContext(GetTranslationUnitDecl()); + tu->dump(s.AsRawOstream()); +} + void ClangASTContext::DumpValue( lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, const DataExtractor &data, @@ -8898,8 +9125,7 @@ void ClangASTContext::DumpValue( base_class->getType()->getAs<clang::RecordType>()->getDecl()); // Skip empty base classes - if (verbose == false && - ClangASTContext::RecordHasFields(base_class_decl) == false) + if (!verbose && !ClangASTContext::RecordHasFields(base_class_decl)) continue; if (base_class->isVirtual()) @@ -9672,11 +9898,16 @@ bool ClangASTContext::LayoutRecordType( llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) { ClangASTContext *ast = (ClangASTContext *)baton; - DWARFASTParserClang *dwarf_ast_parser = - (DWARFASTParserClang *)ast->GetDWARFParser(); - return dwarf_ast_parser->GetClangASTImporter().LayoutRecordType( - record_decl, bit_size, alignment, field_offsets, base_offsets, - vbase_offsets); + lldb_private::ClangASTImporter *importer = nullptr; + if (ast->m_dwarf_ast_parser_ap) + importer = &ast->m_dwarf_ast_parser_ap->GetClangASTImporter(); + if (!importer && ast->m_pdb_ast_parser_ap) + importer = &ast->m_pdb_ast_parser_ap->GetClangASTImporter(); + if (!importer) + return false; + + return importer->LayoutRecordType(record_decl, bit_size, alignment, + field_offsets, base_offsets, vbase_offsets); } //---------------------------------------------------------------------- |
