Path: blob/main/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
39645 views
//===-- DWARFASTParserClang.h -----------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERCLANG_H9#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERCLANG_H1011#include "clang/AST/CharUnits.h"12#include "clang/AST/Type.h"13#include "llvm/ADT/DenseMap.h"14#include "llvm/ADT/SmallPtrSet.h"15#include "llvm/ADT/SmallVector.h"1617#include "DWARFASTParser.h"18#include "DWARFDIE.h"19#include "DWARFDefines.h"20#include "DWARFFormValue.h"21#include "LogChannelDWARF.h"22#include "lldb/Core/PluginInterface.h"2324#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"25#include "Plugins/Language/ObjC/ObjCLanguage.h"26#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"2728#include <optional>29#include <vector>3031namespace lldb_private {32class CompileUnit;33}34namespace lldb_private::plugin {35namespace dwarf {36class DWARFDebugInfoEntry;37class SymbolFileDWARF;38} // namespace dwarf39} // namespace lldb_private::plugin4041struct ParsedDWARFTypeAttributes;4243class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {44public:45DWARFASTParserClang(lldb_private::TypeSystemClang &ast);4647~DWARFASTParserClang() override;4849// DWARFASTParser interface.50lldb::TypeSP51ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,52const lldb_private::plugin::dwarf::DWARFDIE &die,53bool *type_is_new_ptr) override;5455lldb_private::ConstString ConstructDemangledNameFromDWARF(56const lldb_private::plugin::dwarf::DWARFDIE &die) override;5758lldb_private::Function *59ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,60const lldb_private::plugin::dwarf::DWARFDIE &die,61const lldb_private::AddressRange &func_range) override;6263bool64CompleteTypeFromDWARF(const lldb_private::plugin::dwarf::DWARFDIE &die,65lldb_private::Type *type,66lldb_private::CompilerType &compiler_type) override;6768lldb_private::CompilerDecl GetDeclForUIDFromDWARF(69const lldb_private::plugin::dwarf::DWARFDIE &die) override;7071void EnsureAllDIEsInDeclContextHaveBeenParsed(72lldb_private::CompilerDeclContext decl_context) override;7374lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF(75const lldb_private::plugin::dwarf::DWARFDIE &die) override;7677lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF(78const lldb_private::plugin::dwarf::DWARFDIE &die) override;7980lldb_private::ClangASTImporter &GetClangASTImporter();8182/// Extracts an value for a given Clang integer type from a DWARFFormValue.83///84/// \param int_type The Clang type that defines the bit size and signedness85/// of the integer that should be extracted. Has to be either86/// an integer type or an enum type. For enum types the87/// underlying integer type will be considered as the88/// expected integer type that should be extracted.89/// \param form_value The DWARFFormValue that contains the integer value.90/// \return An APInt containing the same integer value as the given91/// DWARFFormValue with the bit width of the given integer type.92/// Returns an error if the value in the DWARFFormValue does not fit93/// into the given integer type or the integer type isn't supported.94llvm::Expected<llvm::APInt> ExtractIntFromFormValue(95const lldb_private::CompilerType &int_type,96const lldb_private::plugin::dwarf::DWARFFormValue &form_value) const;9798/// Returns the template parameters of a class DWARFDIE as a string.99///100/// This is mostly useful for -gsimple-template-names which omits template101/// parameters from the DIE name and instead always adds template parameter102/// children DIEs.103///104/// \param die The struct/class DWARFDIE containing template parameters.105/// \return A string, including surrounding '<>', of the template parameters.106/// If the DIE's name already has '<>', returns an empty string because107/// it's assumed that the caller is using the DIE name anyway.108std::string GetDIEClassTemplateParams(109const lldb_private::plugin::dwarf::DWARFDIE &die) override;110111void MapDeclDIEToDefDIE(const lldb_private::plugin::dwarf::DWARFDIE &decl_die,112const lldb_private::plugin::dwarf::DWARFDIE &def_die);113114protected:115/// Protected typedefs and members.116/// @{117class DelayedAddObjCClassProperty;118typedef std::vector<DelayedAddObjCClassProperty> DelayedPropertyList;119120typedef llvm::DenseMap<121const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *,122clang::DeclContext *>123DIEToDeclContextMap;124typedef std::multimap<const clang::DeclContext *,125const lldb_private::plugin::dwarf::DWARFDIE>126DeclContextToDIEMap;127typedef llvm::DenseMap<128const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *,129lldb_private::OptionalClangModuleID>130DIEToModuleMap;131typedef llvm::DenseMap<132const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *, clang::Decl *>133DIEToDeclMap;134135lldb_private::TypeSystemClang &m_ast;136DIEToDeclMap m_die_to_decl;137DIEToDeclContextMap m_die_to_decl_ctx;138DeclContextToDIEMap m_decl_ctx_to_die;139DIEToModuleMap m_die_to_module;140std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up;141/// @}142143clang::DeclContext *144GetDeclContextForBlock(const lldb_private::plugin::dwarf::DWARFDIE &die);145146clang::BlockDecl *147ResolveBlockDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);148149clang::NamespaceDecl *150ResolveNamespaceDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);151152/// Returns the namespace decl that a DW_TAG_imported_declaration imports.153///154/// \param[in] die The import declaration to resolve. If the DIE is not a155/// DW_TAG_imported_declaration the behaviour is undefined.156///157/// \returns The decl corresponding to the namespace that the specified158/// 'die' imports. If the imported entity is not a namespace159/// or another import declaration, returns nullptr. If an error160/// occurs, returns nullptr.161clang::NamespaceDecl *ResolveImportedDeclarationDIE(162const lldb_private::plugin::dwarf::DWARFDIE &die);163164bool ParseTemplateDIE(const lldb_private::plugin::dwarf::DWARFDIE &die,165lldb_private::TypeSystemClang::TemplateParameterInfos166&template_param_infos);167168bool ParseTemplateParameterInfos(169const lldb_private::plugin::dwarf::DWARFDIE &parent_die,170lldb_private::TypeSystemClang::TemplateParameterInfos171&template_param_infos);172173void GetUniqueTypeNameAndDeclaration(174const lldb_private::plugin::dwarf::DWARFDIE &die,175lldb::LanguageType language, lldb_private::ConstString &unique_typename,176lldb_private::Declaration &decl_declaration);177178bool ParseChildMembers(179const lldb_private::plugin::dwarf::DWARFDIE &die,180lldb_private::CompilerType &class_compiler_type,181std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,182std::vector<lldb_private::plugin::dwarf::DWARFDIE> &member_function_dies,183std::vector<lldb_private::plugin::dwarf::DWARFDIE> &contained_type_dies,184DelayedPropertyList &delayed_properties,185const lldb::AccessType default_accessibility,186lldb_private::ClangASTImporter::LayoutInfo &layout_info);187188size_t189ParseChildParameters(clang::DeclContext *containing_decl_ctx,190const lldb_private::plugin::dwarf::DWARFDIE &parent_die,191bool skip_artificial, bool &is_static, bool &is_variadic,192bool &has_template_params,193std::vector<lldb_private::CompilerType> &function_args,194std::vector<clang::ParmVarDecl *> &function_param_decls,195unsigned &type_quals);196197size_t ParseChildEnumerators(198lldb_private::CompilerType &compiler_type, bool is_signed,199uint32_t enumerator_byte_size,200const lldb_private::plugin::dwarf::DWARFDIE &parent_die);201202/// Parse a structure, class, or union type DIE.203lldb::TypeSP204ParseStructureLikeDIE(const lldb_private::SymbolContext &sc,205const lldb_private::plugin::dwarf::DWARFDIE &die,206ParsedDWARFTypeAttributes &attrs);207208clang::Decl *209GetClangDeclForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);210211clang::DeclContext *212GetClangDeclContextForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);213214clang::DeclContext *GetClangDeclContextContainingDIE(215const lldb_private::plugin::dwarf::DWARFDIE &die,216lldb_private::plugin::dwarf::DWARFDIE *decl_ctx_die);217lldb_private::OptionalClangModuleID218GetOwningClangModule(const lldb_private::plugin::dwarf::DWARFDIE &die);219220bool CopyUniqueClassMethodTypes(221const lldb_private::plugin::dwarf::DWARFDIE &src_class_die,222const lldb_private::plugin::dwarf::DWARFDIE &dst_class_die,223lldb_private::Type *class_type,224std::vector<lldb_private::plugin::dwarf::DWARFDIE> &failures);225226clang::DeclContext *GetCachedClangDeclContextForDIE(227const lldb_private::plugin::dwarf::DWARFDIE &die);228229void LinkDeclContextToDIE(clang::DeclContext *decl_ctx,230const lldb_private::plugin::dwarf::DWARFDIE &die);231232void LinkDeclToDIE(clang::Decl *decl,233const lldb_private::plugin::dwarf::DWARFDIE &die);234235/// If \p type_sp is valid, calculate and set its symbol context scope, and236/// update the type list for its backing symbol file.237///238/// Returns \p type_sp.239lldb::TypeSP UpdateSymbolContextScopeForType(240const lldb_private::SymbolContext &sc,241const lldb_private::plugin::dwarf::DWARFDIE &die, lldb::TypeSP type_sp);242243/// Follow Clang Module Skeleton CU references to find a type definition.244lldb::TypeSP245ParseTypeFromClangModule(const lldb_private::SymbolContext &sc,246const lldb_private::plugin::dwarf::DWARFDIE &die,247lldb_private::Log *log);248249// Return true if this type is a declaration to a type in an external250// module.251lldb::ModuleSP252GetModuleForType(const lldb_private::plugin::dwarf::DWARFDIE &die);253254static bool classof(const DWARFASTParser *Parser) {255return Parser->GetKind() == Kind::DWARFASTParserClang;256}257258private:259struct FieldInfo {260uint64_t bit_size = 0;261uint64_t bit_offset = 0;262bool is_bitfield = false;263bool is_artificial = false;264265FieldInfo() = default;266267void SetIsBitfield(bool flag) { is_bitfield = flag; }268bool IsBitfield() { return is_bitfield; }269270void SetIsArtificial(bool flag) { is_artificial = flag; }271bool IsArtificial() const { return is_artificial; }272273bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const {274// Any subsequent bitfields must not overlap and must be at a higher275// bit offset than any previous bitfield + size.276return (bit_size + bit_offset) <= next_bit_offset;277}278};279280/// Parsed form of all attributes that are relevant for parsing type members.281struct MemberAttributes {282explicit MemberAttributes(283const lldb_private::plugin::dwarf::DWARFDIE &die,284const lldb_private::plugin::dwarf::DWARFDIE &parent_die,285lldb::ModuleSP module_sp);286const char *name = nullptr;287/// Indicates how many bits into the word (according to the host endianness)288/// the low-order bit of the field starts. Can be negative.289int64_t bit_offset = 0;290/// Indicates the size of the field in bits.291size_t bit_size = 0;292uint64_t data_bit_offset = UINT64_MAX;293lldb::AccessType accessibility = lldb::eAccessNone;294std::optional<uint64_t> byte_size;295std::optional<lldb_private::plugin::dwarf::DWARFFormValue> const_value_form;296lldb_private::plugin::dwarf::DWARFFormValue encoding_form;297/// Indicates the byte offset of the word from the base address of the298/// structure.299uint32_t member_byte_offset = UINT32_MAX;300bool is_artificial = false;301bool is_declaration = false;302};303304/// Returns 'true' if we should create an unnamed bitfield305/// and add it to the parser's current AST.306///307/// \param[in] last_field_info FieldInfo of the previous DW_TAG_member308/// we parsed.309/// \param[in] last_field_end Offset (in bits) where the last parsed field310/// ended.311/// \param[in] this_field_info FieldInfo of the current DW_TAG_member312/// being parsed.313/// \param[in] layout_info Layout information of all decls parsed by the314/// current parser.315bool ShouldCreateUnnamedBitfield(316FieldInfo const &last_field_info, uint64_t last_field_end,317FieldInfo const &this_field_info,318lldb_private::ClangASTImporter::LayoutInfo const &layout_info) const;319320/// Parses a DW_TAG_APPLE_property DIE and appends the parsed data to the321/// list of delayed Objective-C properties.322///323/// Note: The delayed property needs to be finalized to actually create the324/// property declarations in the module AST.325///326/// \param die The DW_TAG_APPLE_property DIE that will be parsed.327/// \param parent_die The parent DIE.328/// \param class_clang_type The Objective-C class that will contain the329/// created property.330/// \param delayed_properties The list of delayed properties that the result331/// will be appended to.332void333ParseObjCProperty(const lldb_private::plugin::dwarf::DWARFDIE &die,334const lldb_private::plugin::dwarf::DWARFDIE &parent_die,335const lldb_private::CompilerType &class_clang_type,336DelayedPropertyList &delayed_properties);337338void339ParseSingleMember(const lldb_private::plugin::dwarf::DWARFDIE &die,340const lldb_private::plugin::dwarf::DWARFDIE &parent_die,341const lldb_private::CompilerType &class_clang_type,342lldb::AccessType default_accessibility,343lldb_private::ClangASTImporter::LayoutInfo &layout_info,344FieldInfo &last_field_info);345346/// If the specified 'die' represents a static data member, creates347/// a 'clang::VarDecl' for it and attaches it to specified parent348/// 'class_clang_type'.349///350/// \param[in] die The member declaration we want to create a351/// clang::VarDecl for.352///353/// \param[in] attrs The parsed attributes for the specified 'die'.354///355/// \param[in] class_clang_type The parent RecordType of the static356/// member this function will create.357void CreateStaticMemberVariable(358const lldb_private::plugin::dwarf::DWARFDIE &die,359const MemberAttributes &attrs,360const lldb_private::CompilerType &class_clang_type);361362bool CompleteRecordType(const lldb_private::plugin::dwarf::DWARFDIE &die,363lldb_private::Type *type,364lldb_private::CompilerType &clang_type);365bool CompleteEnumType(const lldb_private::plugin::dwarf::DWARFDIE &die,366lldb_private::Type *type,367lldb_private::CompilerType &clang_type);368369lldb::TypeSP370ParseTypeModifier(const lldb_private::SymbolContext &sc,371const lldb_private::plugin::dwarf::DWARFDIE &die,372ParsedDWARFTypeAttributes &attrs);373lldb::TypeSP ParseEnum(const lldb_private::SymbolContext &sc,374const lldb_private::plugin::dwarf::DWARFDIE &die,375ParsedDWARFTypeAttributes &attrs);376lldb::TypeSP ParseSubroutine(const lldb_private::plugin::dwarf::DWARFDIE &die,377const ParsedDWARFTypeAttributes &attrs);378379/// Helper function called by \ref ParseSubroutine when parsing ObjC-methods.380///381/// \param[in] objc_method Name of the ObjC method being parsed.382///383/// \param[in] die The DIE that represents the ObjC method being parsed.384///385/// \param[in] clang_type The CompilerType representing the function prototype386/// of the ObjC method being parsed.387///388/// \param[in] attrs DWARF attributes for \ref die.389///390/// \param[in] is_variadic Is true iff we're parsing a variadic method.391///392/// \returns true on success393bool394ParseObjCMethod(const lldb_private::ObjCLanguage::MethodName &objc_method,395const lldb_private::plugin::dwarf::DWARFDIE &die,396lldb_private::CompilerType clang_type,397const ParsedDWARFTypeAttributes &attrs, bool is_variadic);398399/// Helper function called by \ref ParseSubroutine when parsing C++ methods.400///401/// \param[in] die The DIE that represents the C++ method being parsed.402///403/// \param[in] clang_type The CompilerType representing the function prototype404/// of the C++ method being parsed.405///406/// \param[in] attrs DWARF attributes for \ref die.407///408/// \param[in] decl_ctx_die The DIE representing the DeclContext of the C++409/// method being parsed.410///411/// \param[in] is_static Is true iff we're parsing a static method.412///413/// \param[out] ignore_containing_context Will get set to true if the caller414/// should treat this C++ method as-if it was not a C++ method.415/// Currently used as a hack to work around templated C++ methods416/// causing class definitions to mismatch between CUs.417///418/// \returns A pair of <bool, TypeSP>. The first element is 'true' on success.419/// The second element is non-null if we have previously parsed this420/// method (a null TypeSP does not indicate failure).421std::pair<bool, lldb::TypeSP>422ParseCXXMethod(const lldb_private::plugin::dwarf::DWARFDIE &die,423lldb_private::CompilerType clang_type,424const ParsedDWARFTypeAttributes &attrs,425const lldb_private::plugin::dwarf::DWARFDIE &decl_ctx_die,426bool is_static, bool &ignore_containing_context);427428lldb::TypeSP ParseArrayType(const lldb_private::plugin::dwarf::DWARFDIE &die,429const ParsedDWARFTypeAttributes &attrs);430lldb::TypeSP431ParsePointerToMemberType(const lldb_private::plugin::dwarf::DWARFDIE &die,432const ParsedDWARFTypeAttributes &attrs);433434/// Parses a DW_TAG_inheritance DIE into a base/super class.435///436/// \param die The DW_TAG_inheritance DIE to parse.437/// \param parent_die The parent DIE of the given DIE.438/// \param class_clang_type The C++/Objective-C class representing parent_die.439/// For an Objective-C class this method sets the super class on success. For440/// a C++ class this will *not* add the result as a base class.441/// \param default_accessibility The default accessibility that is given to442/// base classes if they don't have an explicit accessibility set.443/// \param module_sp The current Module.444/// \param base_classes The list of C++ base classes that will be appended445/// with the parsed base class on success.446/// \param layout_info The layout information that will be updated for C++447/// base classes with the base offset.448void ParseInheritance(449const lldb_private::plugin::dwarf::DWARFDIE &die,450const lldb_private::plugin::dwarf::DWARFDIE &parent_die,451const lldb_private::CompilerType class_clang_type,452const lldb::AccessType default_accessibility,453const lldb::ModuleSP &module_sp,454std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,455lldb_private::ClangASTImporter::LayoutInfo &layout_info);456457/// Parses DW_TAG_variant_part DIE into a structure that encodes all variants458/// Note that this is currently being emitted by rustc and not Clang459/// \param die DW_TAG_variant_part DIE to parse460/// \param parent_die The parent DW_TAG_structure_type to parse461/// \param class_clang_type The Rust struct representing parent_die.462/// \param default_accesibility The default accessibility that is given to463/// base classes if they don't have an explicit accessibility set464/// \param layout_info The layout information that will be updated for465// base classes with the base offset466void467ParseRustVariantPart(lldb_private::plugin::dwarf::DWARFDIE &die,468const lldb_private::plugin::dwarf::DWARFDIE &parent_die,469lldb_private::CompilerType &class_clang_type,470const lldb::AccessType default_accesibility,471lldb_private::ClangASTImporter::LayoutInfo &layout_info);472};473474/// Parsed form of all attributes that are relevant for type reconstruction.475/// Some attributes are relevant for all kinds of types (declaration), while476/// others are only meaningful to a specific type (is_virtual)477struct ParsedDWARFTypeAttributes {478explicit ParsedDWARFTypeAttributes(479const lldb_private::plugin::dwarf::DWARFDIE &die);480481lldb::AccessType accessibility = lldb::eAccessNone;482bool is_artificial = false;483bool is_complete_objc_class = false;484bool is_explicit = false;485bool is_forward_declaration = false;486bool is_inline = false;487bool is_scoped_enum = false;488bool is_vector = false;489bool is_virtual = false;490bool is_objc_direct_call = false;491bool exports_symbols = false;492clang::StorageClass storage = clang::SC_None;493const char *mangled_name = nullptr;494lldb_private::ConstString name;495lldb_private::Declaration decl;496lldb_private::plugin::dwarf::DWARFDIE object_pointer;497lldb_private::plugin::dwarf::DWARFFormValue abstract_origin;498lldb_private::plugin::dwarf::DWARFFormValue containing_type;499lldb_private::plugin::dwarf::DWARFFormValue signature;500lldb_private::plugin::dwarf::DWARFFormValue specification;501lldb_private::plugin::dwarf::DWARFFormValue type;502lldb::LanguageType class_language = lldb::eLanguageTypeUnknown;503std::optional<uint64_t> byte_size;504std::optional<uint64_t> alignment;505size_t calling_convention = llvm::dwarf::DW_CC_normal;506uint32_t bit_stride = 0;507uint32_t byte_stride = 0;508uint32_t encoding = 0;509clang::RefQualifierKind ref_qual =510clang::RQ_None; ///< Indicates ref-qualifier of511///< C++ member function if present.512///< Is RQ_None otherwise.513};514515#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERCLANG_H516517518