From: Raphael Isemann Date: Tue, 26 Nov 2019 10:54:30 +0000 (+0100) Subject: [lldb][NFCI] Extract subroutine parsing from DWARFASTParserClang::ParseTypeFromDWARF X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=94939650b632cd44e518a9adeb16ab82dddd9375;p=platform%2Fupstream%2Fllvm.git [lldb][NFCI] Extract subroutine parsing from DWARFASTParserClang::ParseTypeFromDWARF Part of the work to split up this monolithic parsing function. Should be NFC but due to the kafkaesque control flow in this case statement this might have some unintended side effects. --- diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index ea0f027..aca87b3 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -798,428 +798,436 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: case DW_TAG_subroutine_type: { - bool is_variadic = false; - bool is_static = false; - bool has_template_params = false; + type_sp = ParseSubroutine(die, attrs); + break; + } + case DW_TAG_array_type: { + type_sp = ParseArrayType(die, attrs); + break; + } + case DW_TAG_ptr_to_member_type: { + type_sp = ParsePointerToMemberType(die, attrs); + break; + } + default: + dwarf->GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and " + "attach the file at the start of this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + break; + } - unsigned type_quals = 0; + // TODO: We should consider making the switch above exhaustive to simplify + // control flow in ParseTypeFromDWARF. Then, we could simply replace this + // return statement with a call to llvm_unreachable. + return UpdateSymbolContextScopeForType(sc, die, type_sp); +} - std::string object_pointer_name; - if (attrs.object_pointer) { - const char *object_pointer_name_cstr = attrs.object_pointer.GetName(); - if (object_pointer_name_cstr) - object_pointer_name = object_pointer_name_cstr; - } +TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs) { + Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION | + DWARF_LOG_LOOKUPS)); - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); + SymbolFileDWARF *dwarf = die.GetDWARF(); + const dw_tag_t tag = die.Tag(); - CompilerType return_clang_type; - Type *func_type = NULL; - - if (attrs.type.IsValid()) - func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true); - - if (func_type) - return_clang_type = func_type->GetForwardCompilerType(); - else - return_clang_type = m_ast.GetBasicType(eBasicTypeVoid); - - std::vector function_param_types; - std::vector function_param_decls; - - // Parse the function children for the parameters - - DWARFDIE decl_ctx_die; - clang::DeclContext *containing_decl_ctx = - GetClangDeclContextContainingDIE(die, &decl_ctx_die); - const clang::Decl::Kind containing_decl_kind = - containing_decl_ctx->getDeclKind(); - - bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind); - // Start off static. This will be set to false in - // ParseChildParameters(...) if we find a "this" parameters as the - // first parameter - if (is_cxx_method) { - is_static = true; - } - - if (die.HasChildren()) { - bool skip_artificial = true; - ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static, - is_variadic, has_template_params, - function_param_types, function_param_decls, - type_quals); - } - - bool ignore_containing_context = false; - // Check for templatized class member functions. If we had any - // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter - // the DW_TAG_subprogram DIE, then we can't let this become a method in - // a class. Why? Because templatized functions are only emitted if one - // of the templatized methods is used in the current compile unit and - // we will end up with classes that may or may not include these member - // functions and this means one class won't match another class - // definition and it affects our ability to use a class in the clang - // expression parser. So for the greater good, we currently must not - // allow any template member functions in a class definition. - if (is_cxx_method && has_template_params) { - ignore_containing_context = true; - is_cxx_method = false; - } - - // clang_type will get the function prototype clang type after this - // call - clang_type = m_ast.CreateFunctionType( - return_clang_type, function_param_types.data(), - function_param_types.size(), is_variadic, type_quals); - - if (attrs.name) { - bool type_handled = false; - if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) { - ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true); - if (objc_method.IsValid(true)) { - CompilerType class_opaque_type; - ConstString class_name(objc_method.GetClassName()); - if (class_name) { - TypeSP complete_objc_class_type_sp( - dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(), - class_name, false)); - - if (complete_objc_class_type_sp) { - CompilerType type_clang_forward_type = - complete_objc_class_type_sp->GetForwardCompilerType(); - if (ClangASTContext::IsObjCObjectOrInterfaceType( - type_clang_forward_type)) - class_opaque_type = type_clang_forward_type; - } + bool is_variadic = false; + bool is_static = false; + bool has_template_params = false; + + unsigned type_quals = 0; + + std::string object_pointer_name; + if (attrs.object_pointer) { + const char *object_pointer_name_cstr = attrs.object_pointer.GetName(); + if (object_pointer_name_cstr) + object_pointer_name = object_pointer_name_cstr; + } + + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + CompilerType return_clang_type; + Type *func_type = NULL; + + if (attrs.type.IsValid()) + func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true); + + if (func_type) + return_clang_type = func_type->GetForwardCompilerType(); + else + return_clang_type = m_ast.GetBasicType(eBasicTypeVoid); + + std::vector function_param_types; + std::vector function_param_decls; + + // Parse the function children for the parameters + + DWARFDIE decl_ctx_die; + clang::DeclContext *containing_decl_ctx = + GetClangDeclContextContainingDIE(die, &decl_ctx_die); + const clang::Decl::Kind containing_decl_kind = + containing_decl_ctx->getDeclKind(); + + bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind); + // Start off static. This will be set to false in + // ParseChildParameters(...) if we find a "this" parameters as the + // first parameter + if (is_cxx_method) { + is_static = true; + } + + if (die.HasChildren()) { + bool skip_artificial = true; + ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static, + is_variadic, has_template_params, + function_param_types, function_param_decls, + type_quals); + } + + bool ignore_containing_context = false; + // Check for templatized class member functions. If we had any + // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter + // the DW_TAG_subprogram DIE, then we can't let this become a method in + // a class. Why? Because templatized functions are only emitted if one + // of the templatized methods is used in the current compile unit and + // we will end up with classes that may or may not include these member + // functions and this means one class won't match another class + // definition and it affects our ability to use a class in the clang + // expression parser. So for the greater good, we currently must not + // allow any template member functions in a class definition. + if (is_cxx_method && has_template_params) { + ignore_containing_context = true; + is_cxx_method = false; + } + + // clang_type will get the function prototype clang type after this + // call + CompilerType clang_type = m_ast.CreateFunctionType( + return_clang_type, function_param_types.data(), + function_param_types.size(), is_variadic, type_quals); + + if (attrs.name) { + bool type_handled = false; + if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) { + ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true); + if (objc_method.IsValid(true)) { + CompilerType class_opaque_type; + ConstString class_name(objc_method.GetClassName()); + if (class_name) { + TypeSP complete_objc_class_type_sp( + dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(), + class_name, false)); + + if (complete_objc_class_type_sp) { + CompilerType type_clang_forward_type = + complete_objc_class_type_sp->GetForwardCompilerType(); + if (ClangASTContext::IsObjCObjectOrInterfaceType( + type_clang_forward_type)) + class_opaque_type = type_clang_forward_type; } + } - if (class_opaque_type) { - // If accessibility isn't set to anything valid, assume public - // for now... - if (attrs.accessibility == eAccessNone) - attrs.accessibility = eAccessPublic; - - clang::ObjCMethodDecl *objc_method_decl = - m_ast.AddMethodToObjCObjectType( - class_opaque_type, attrs.name.GetCString(), clang_type, - attrs.accessibility, attrs.is_artificial, is_variadic); - type_handled = objc_method_decl != NULL; - if (type_handled) { - LinkDeclContextToDIE(objc_method_decl, die); - m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), " - "please file a bug and attach the file at the start of " - "this error message", - die.GetOffset(), tag, DW_TAG_value_to_name(tag)); - } + if (class_opaque_type) { + // If accessibility isn't set to anything valid, assume public + // for now... + if (attrs.accessibility == eAccessNone) + attrs.accessibility = eAccessPublic; + + clang::ObjCMethodDecl *objc_method_decl = + m_ast.AddMethodToObjCObjectType( + class_opaque_type, attrs.name.GetCString(), clang_type, + attrs.accessibility, attrs.is_artificial, is_variadic); + type_handled = objc_method_decl != NULL; + if (type_handled) { + LinkDeclContextToDIE(objc_method_decl, die); + m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), " + "please file a bug and attach the file at the start of " + "this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); } - } else if (is_cxx_method) { - // Look at the parent of this DIE and see if is is a class or - // struct and see if this is actually a C++ method - Type *class_type = dwarf->ResolveType(decl_ctx_die); - if (class_type) { - bool alternate_defn = false; - if (class_type->GetID() != decl_ctx_die.GetID() || - IsClangModuleFwdDecl(decl_ctx_die)) { - alternate_defn = true; - - // We uniqued the parent class of this function to another - // class so we now need to associate all dies under - // "decl_ctx_die" to DIEs in the DIE for "class_type"... - DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID()); - - if (class_type_die) { - std::vector failures; - - CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, - class_type, failures); - - // FIXME do something with these failures that's - // smarter than just dropping them on the ground. - // Unfortunately classes don't like having stuff added - // to them after their definitions are complete... - - type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { - type_sp = type_ptr->shared_from_this(); - break; - } + } + } else if (is_cxx_method) { + // Look at the parent of this DIE and see if is is a class or + // struct and see if this is actually a C++ method + Type *class_type = dwarf->ResolveType(decl_ctx_die); + if (class_type) { + bool alternate_defn = false; + if (class_type->GetID() != decl_ctx_die.GetID() || + IsClangModuleFwdDecl(decl_ctx_die)) { + alternate_defn = true; + + // We uniqued the parent class of this function to another + // class so we now need to associate all dies under + // "decl_ctx_die" to DIEs in the DIE for "class_type"... + DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID()); + + if (class_type_die) { + std::vector failures; + + CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, + class_type, failures); + + // FIXME do something with these failures that's + // smarter than just dropping them on the ground. + // Unfortunately classes don't like having stuff added + // to them after their definitions are complete... + + Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { + return type_ptr->shared_from_this(); } } + } - if (attrs.specification.IsValid()) { - // We have a specification which we are going to base our - // function prototype off of, so we need this type to be - // completed so that the m_die_to_decl_ctx for the method in - // the specification has a valid clang decl context. - class_type->GetForwardCompilerType(); - // If we have a specification, then the function type should - // have been made with the specification and not with this - // die. - DWARFDIE spec_die = attrs.specification.Reference(); - clang::DeclContext *spec_clang_decl_ctx = - GetClangDeclContextForDIE(spec_die); - if (spec_clang_decl_ctx) { - LinkDeclContextToDIE(spec_clang_decl_ctx, die); - } else { - dwarf->GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x" - ") has no decl\n", - die.GetID(), spec_die.GetOffset()); - } - type_handled = true; - } else if (attrs.abstract_origin.IsValid()) { - // We have a specification which we are going to base our - // function prototype off of, so we need this type to be - // completed so that the m_die_to_decl_ctx for the method in - // the abstract origin has a valid clang decl context. - class_type->GetForwardCompilerType(); - - DWARFDIE abs_die = attrs.abstract_origin.Reference(); - clang::DeclContext *abs_clang_decl_ctx = - GetClangDeclContextForDIE(abs_die); - if (abs_clang_decl_ctx) { - LinkDeclContextToDIE(abs_clang_decl_ctx, die); - } else { - dwarf->GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x" - ") has no decl\n", - die.GetID(), abs_die.GetOffset()); - } - type_handled = true; + if (attrs.specification.IsValid()) { + // We have a specification which we are going to base our + // function prototype off of, so we need this type to be + // completed so that the m_die_to_decl_ctx for the method in + // the specification has a valid clang decl context. + class_type->GetForwardCompilerType(); + // If we have a specification, then the function type should + // have been made with the specification and not with this + // die. + DWARFDIE spec_die = attrs.specification.Reference(); + clang::DeclContext *spec_clang_decl_ctx = + GetClangDeclContextForDIE(spec_die); + if (spec_clang_decl_ctx) { + LinkDeclContextToDIE(spec_clang_decl_ctx, die); } else { - CompilerType class_opaque_type = - class_type->GetForwardCompilerType(); - if (ClangASTContext::IsCXXClassType(class_opaque_type)) { - if (class_opaque_type.IsBeingDefined() || alternate_defn) { - if (!is_static && !die.HasChildren()) { - // We have a C++ member function with no children (this - // pointer!) and clang will get mad if we try and make - // a function that isn't well formed in the DWARF, so - // we will just skip it... - type_handled = true; - } else { - bool add_method = true; - if (alternate_defn) { - // If an alternate definition for the class exists, - // then add the method only if an equivalent is not - // already present. - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl( - class_opaque_type.GetOpaqueQualType()); - if (record_decl) { - for (auto method_iter = record_decl->method_begin(); - method_iter != record_decl->method_end(); - method_iter++) { - clang::CXXMethodDecl *method_decl = *method_iter; - if (method_decl->getNameInfo().getAsString() == - attrs.name.GetStringRef()) { - if (method_decl->getType() == - ClangUtil::GetQualType(clang_type)) { - add_method = false; - LinkDeclContextToDIE(method_decl, die); - type_handled = true; - - break; - } + dwarf->GetObjectFile()->GetModule()->ReportWarning( + "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x" + ") has no decl\n", + die.GetID(), spec_die.GetOffset()); + } + type_handled = true; + } else if (attrs.abstract_origin.IsValid()) { + // We have a specification which we are going to base our + // function prototype off of, so we need this type to be + // completed so that the m_die_to_decl_ctx for the method in + // the abstract origin has a valid clang decl context. + class_type->GetForwardCompilerType(); + + DWARFDIE abs_die = attrs.abstract_origin.Reference(); + clang::DeclContext *abs_clang_decl_ctx = + GetClangDeclContextForDIE(abs_die); + if (abs_clang_decl_ctx) { + LinkDeclContextToDIE(abs_clang_decl_ctx, die); + } else { + dwarf->GetObjectFile()->GetModule()->ReportWarning( + "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x" + ") has no decl\n", + die.GetID(), abs_die.GetOffset()); + } + type_handled = true; + } else { + CompilerType class_opaque_type = + class_type->GetForwardCompilerType(); + if (ClangASTContext::IsCXXClassType(class_opaque_type)) { + if (class_opaque_type.IsBeingDefined() || alternate_defn) { + if (!is_static && !die.HasChildren()) { + // We have a C++ member function with no children (this + // pointer!) and clang will get mad if we try and make + // a function that isn't well formed in the DWARF, so + // we will just skip it... + type_handled = true; + } else { + bool add_method = true; + if (alternate_defn) { + // If an alternate definition for the class exists, + // then add the method only if an equivalent is not + // already present. + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl( + class_opaque_type.GetOpaqueQualType()); + if (record_decl) { + for (auto method_iter = record_decl->method_begin(); + method_iter != record_decl->method_end(); + method_iter++) { + clang::CXXMethodDecl *method_decl = *method_iter; + if (method_decl->getNameInfo().getAsString() == + attrs.name.GetStringRef()) { + if (method_decl->getType() == + ClangUtil::GetQualType(clang_type)) { + add_method = false; + LinkDeclContextToDIE(method_decl, die); + type_handled = true; + + break; } } } } + } - if (add_method) { - llvm::PrettyStackTraceFormat stack_trace( - "SymbolFileDWARF::ParseType() is adding a method " - "%s to class %s in DIE 0x%8.8" PRIx64 " from %s", - attrs.name.GetCString(), - class_type->GetName().GetCString(), die.GetID(), - dwarf->GetObjectFile() - ->GetFileSpec() - .GetPath() - .c_str()); - - const bool is_attr_used = false; - // Neither GCC 4.2 nor clang++ currently set a valid - // accessibility in the DWARF for C++ methods... - // Default to public for now... - if (attrs.accessibility == eAccessNone) - attrs.accessibility = eAccessPublic; - - clang::CXXMethodDecl *cxx_method_decl = - m_ast.AddMethodToCXXRecordType( - class_opaque_type.GetOpaqueQualType(), - attrs.name.GetCString(), attrs.mangled_name, - clang_type, attrs.accessibility, attrs.is_virtual, - is_static, attrs.is_inline, attrs.is_explicit, - is_attr_used, attrs.is_artificial); - - type_handled = cxx_method_decl != NULL; - // Artificial methods are always handled even when we - // don't create a new declaration for them. - type_handled |= attrs.is_artificial; - - if (cxx_method_decl) { - LinkDeclContextToDIE(cxx_method_decl, die); - - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - - if (!object_pointer_name.empty()) { - metadata.SetObjectPtrName( - object_pointer_name.c_str()); - LLDB_LOGF(log, - "Setting object pointer name: %s on method " - "object %p.\n", - object_pointer_name.c_str(), - static_cast(cxx_method_decl)); - } - m_ast.SetMetadata(cxx_method_decl, metadata); - } else { - ignore_containing_context = true; + if (add_method) { + llvm::PrettyStackTraceFormat stack_trace( + "SymbolFileDWARF::ParseType() is adding a method " + "%s to class %s in DIE 0x%8.8" PRIx64 " from %s", + attrs.name.GetCString(), + class_type->GetName().GetCString(), die.GetID(), + dwarf->GetObjectFile() + ->GetFileSpec() + .GetPath() + .c_str()); + + const bool is_attr_used = false; + // Neither GCC 4.2 nor clang++ currently set a valid + // accessibility in the DWARF for C++ methods... + // Default to public for now... + if (attrs.accessibility == eAccessNone) + attrs.accessibility = eAccessPublic; + + clang::CXXMethodDecl *cxx_method_decl = + m_ast.AddMethodToCXXRecordType( + class_opaque_type.GetOpaqueQualType(), + attrs.name.GetCString(), attrs.mangled_name, + clang_type, attrs.accessibility, attrs.is_virtual, + is_static, attrs.is_inline, attrs.is_explicit, + is_attr_used, attrs.is_artificial); + + type_handled = cxx_method_decl != NULL; + // Artificial methods are always handled even when we + // don't create a new declaration for them. + type_handled |= attrs.is_artificial; + + if (cxx_method_decl) { + LinkDeclContextToDIE(cxx_method_decl, die); + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + + if (!object_pointer_name.empty()) { + metadata.SetObjectPtrName( + object_pointer_name.c_str()); + LLDB_LOGF(log, + "Setting object pointer name: %s on method " + "object %p.\n", + object_pointer_name.c_str(), + static_cast(cxx_method_decl)); } + m_ast.SetMetadata(cxx_method_decl, metadata); + } else { + ignore_containing_context = true; } } - } else { - // We were asked to parse the type for a method in a - // class, yet the class hasn't been asked to complete - // itself through the clang::ExternalASTSource protocol, - // so we need to just have the class complete itself and - // do things the right way, then our - // DIE should then have an entry in the - // dwarf->GetDIEToType() map. First - // we need to modify the dwarf->GetDIEToType() so it - // doesn't think we are trying to parse this DIE - // anymore... - dwarf->GetDIEToType()[die.GetDIE()] = NULL; - - // Now we get the full type to force our class type to - // complete itself using the clang::ExternalASTSource - // protocol which will parse all base classes and all - // methods (including the method for this DIE). - class_type->GetFullCompilerType(); - - // The type for this DIE should have been filled in the - // function call above - type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { - type_sp = type_ptr->shared_from_this(); - break; - } - - // FIXME This is fixing some even uglier behavior but we - // really need to - // uniq the methods of each class as well as the class - // itself. - type_handled = true; } + } else { + // We were asked to parse the type for a method in a + // class, yet the class hasn't been asked to complete + // itself through the clang::ExternalASTSource protocol, + // so we need to just have the class complete itself and + // do things the right way, then our + // DIE should then have an entry in the + // dwarf->GetDIEToType() map. First + // we need to modify the dwarf->GetDIEToType() so it + // doesn't think we are trying to parse this DIE + // anymore... + dwarf->GetDIEToType()[die.GetDIE()] = NULL; + + // Now we get the full type to force our class type to + // complete itself using the clang::ExternalASTSource + // protocol which will parse all base classes and all + // methods (including the method for this DIE). + class_type->GetFullCompilerType(); + + // The type for this DIE should have been filled in the + // function call above + Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { + return type_ptr->shared_from_this(); + } + + // FIXME This is fixing some even uglier behavior but we + // really need to + // uniq the methods of each class as well as the class + // itself. + type_handled = true; } } } } } + } - if (!type_handled) { - clang::FunctionDecl *function_decl = nullptr; - clang::FunctionDecl *template_function_decl = nullptr; + if (!type_handled) { + clang::FunctionDecl *function_decl = nullptr; + clang::FunctionDecl *template_function_decl = nullptr; - if (attrs.abstract_origin.IsValid()) { - DWARFDIE abs_die = attrs.abstract_origin.Reference(); + if (attrs.abstract_origin.IsValid()) { + DWARFDIE abs_die = attrs.abstract_origin.Reference(); - if (dwarf->ResolveType(abs_die)) { - function_decl = llvm::dyn_cast_or_null( - GetCachedClangDeclContextForDIE(abs_die)); + if (dwarf->ResolveType(abs_die)) { + function_decl = llvm::dyn_cast_or_null( + GetCachedClangDeclContextForDIE(abs_die)); - if (function_decl) { - LinkDeclContextToDIE(function_decl, die); - } + if (function_decl) { + LinkDeclContextToDIE(function_decl, die); } } + } - if (!function_decl) { - // We just have a function that isn't part of a class - function_decl = m_ast.CreateFunctionDeclaration( + if (!function_decl) { + // We just have a function that isn't part of a class + function_decl = m_ast.CreateFunctionDeclaration( + ignore_containing_context ? m_ast.GetTranslationUnitDecl() + : containing_decl_ctx, + attrs.name.GetCString(), clang_type, attrs.storage, + attrs.is_inline); + + if (has_template_params) { + ClangASTContext::TemplateParameterInfos template_param_infos; + ParseTemplateParameterInfos(die, template_param_infos); + template_function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, attrs.name.GetCString(), clang_type, attrs.storage, attrs.is_inline); + clang::FunctionTemplateDecl *func_template_decl = + m_ast.CreateFunctionTemplateDecl( + containing_decl_ctx, template_function_decl, + attrs.name.GetCString(), template_param_infos); + m_ast.CreateFunctionTemplateSpecializationInfo( + function_decl, func_template_decl, template_param_infos); + } - if (has_template_params) { - ClangASTContext::TemplateParameterInfos template_param_infos; - ParseTemplateParameterInfos(die, template_param_infos); - template_function_decl = m_ast.CreateFunctionDeclaration( - ignore_containing_context ? m_ast.GetTranslationUnitDecl() - : containing_decl_ctx, - attrs.name.GetCString(), clang_type, attrs.storage, - attrs.is_inline); - clang::FunctionTemplateDecl *func_template_decl = - m_ast.CreateFunctionTemplateDecl( - containing_decl_ctx, template_function_decl, - attrs.name.GetCString(), template_param_infos); - m_ast.CreateFunctionTemplateSpecializationInfo( - function_decl, func_template_decl, template_param_infos); - } - - lldbassert(function_decl); + lldbassert(function_decl); - if (function_decl) { - LinkDeclContextToDIE(function_decl, die); + if (function_decl) { + LinkDeclContextToDIE(function_decl, die); - if (!function_param_decls.empty()) { - m_ast.SetFunctionParameters(function_decl, + if (!function_param_decls.empty()) { + m_ast.SetFunctionParameters(function_decl, + &function_param_decls.front(), + function_param_decls.size()); + if (template_function_decl) + m_ast.SetFunctionParameters(template_function_decl, &function_param_decls.front(), function_param_decls.size()); - if (template_function_decl) - m_ast.SetFunctionParameters(template_function_decl, - &function_param_decls.front(), - function_param_decls.size()); - } + } - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); - if (!object_pointer_name.empty()) { - metadata.SetObjectPtrName(object_pointer_name.c_str()); - LLDB_LOGF(log, - "Setting object pointer name: %s on function " - "object %p.", - object_pointer_name.c_str(), - static_cast(function_decl)); - } - m_ast.SetMetadata(function_decl, metadata); + if (!object_pointer_name.empty()) { + metadata.SetObjectPtrName(object_pointer_name.c_str()); + LLDB_LOGF(log, + "Setting object pointer name: %s on function " + "object %p.", + object_pointer_name.c_str(), + static_cast(function_decl)); } + m_ast.SetMetadata(function_decl, metadata); } } } - type_sp = std::make_shared( - die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Full); - assert(type_sp.get()); - } break; - - case DW_TAG_array_type: { - type_sp = ParseArrayType(die, attrs); - break; - } - case DW_TAG_ptr_to_member_type: { - type_sp = ParsePointerToMemberType(die, attrs); - break; } - default: - dwarf->GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and " - "attach the file at the start of this error message", - die.GetOffset(), tag, DW_TAG_value_to_name(tag)); - break; - } - - // TODO: We should consider making the switch above exhaustive to simplify - // control flow in ParseTypeFromDWARF. Then, we could simply replace this - // return statement with a call to llvm_unreachable. - return UpdateSymbolContextScopeForType(sc, die, type_sp); + return std::make_shared( + die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Full); } TypeSP DWARFASTParserClang::ParseArrayType(const DWARFDIE &die, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 53e7b01..ef15590 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -170,6 +170,8 @@ protected: lldb::ModuleSP GetModuleForType(const DWARFDIE &die); private: + lldb::TypeSP ParseSubroutine(const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); // FIXME: attrs should be passed as a const reference. lldb::TypeSP ParseArrayType(const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs);