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<CompilerType> function_param_types;
- std::vector<clang::ParmVarDecl *> 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<CompilerType> function_param_types;
+ std::vector<clang::ParmVarDecl *> 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<DWARFDIE> 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<DWARFDIE> 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<void *>(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<void *>(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. <rdar://problem/11240464>
- 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. <rdar://problem/11240464>
+ 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<clang::FunctionDecl>(
- GetCachedClangDeclContextForDIE(abs_die));
+ if (dwarf->ResolveType(abs_die)) {
+ function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(
+ 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<void *>(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<void *>(function_decl));
}
+ m_ast.SetMetadata(function_decl, metadata);
}
}
}
- type_sp = std::make_shared<Type>(
- 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<Type>(
+ 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,