diff options
| author | Greg Clayton <gclayton@apple.com> | 2012-03-26 23:03:23 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2012-03-26 23:03:23 +0000 |
| commit | 84db9105d24a326f35054f103fbb468eb6d9bfeb (patch) | |
| tree | f2d1a6c18e9f3b6843cba0e65ed5c89ac3fbbfcd /lldb/source | |
| parent | 98e5d863ad3515ff119d120a1eb40c1c6a345443 (diff) | |
| download | bcm5719-llvm-84db9105d24a326f35054f103fbb468eb6d9bfeb.tar.gz bcm5719-llvm-84db9105d24a326f35054f103fbb468eb6d9bfeb.zip | |
<rdar://problem/11113279>
Fixed type lookups to "do the right thing". Prior to this fix, looking up a type using "foo::bar" would result in a type list that contains all types that had "bar" as a basename unless the symbol file was able to match fully qualified names (which our DWARF parser does not).
This fix will allow type matches to be made based on the basename and then have the types that don't match filtered out. Types by name can be fully qualified, or partially qualified with the new "bool exact_match" parameter to the Module::FindTypes() method.
This fixes some issue that we discovered with dynamic type resolution as well as improves the overall type lookups in LLDB.
llvm-svn: 153482
Diffstat (limited to 'lldb/source')
29 files changed, 462 insertions, 197 deletions
diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp index 3090fb4d473..463669fe22c 100644 --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -425,12 +425,12 @@ SBModule::FindFirstType (const char *name_cstr) SymbolContext sc; TypeList type_list; uint32_t num_matches = 0; + const bool exact_match = false; ConstString name(name_cstr); num_matches = module_sp->FindTypes (sc, name, - NULL, - false, + exact_match, 1, type_list); @@ -451,13 +451,13 @@ SBModule::FindTypes (const char *type) { SymbolContext sc; TypeList type_list; + const bool exact_match = false; uint32_t num_matches = 0; ConstString name(type); num_matches = module_sp->FindTypes (sc, name, - NULL, - false, + exact_match, UINT32_MAX, type_list); diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 4d7b828dd51..0adbb0af490 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -1954,14 +1954,15 @@ SBTarget::FindTypes (const char* type) { ModuleList& images = target_sp->GetImages(); ConstString name_const(type); + bool exact_match = false; SymbolContext sc; TypeList type_list; - uint32_t num_matches = images.FindTypes(sc, - name_const, - true, - UINT32_MAX, - type_list); + uint32_t num_matches = images.FindTypes2 (sc, + name_const, + exact_match, + UINT32_MAX, + type_list); for (size_t idx = 0; idx < num_matches; idx++) { diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index f1d651faf3e..fa9d6b7b2f9 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -441,7 +441,8 @@ SBType::GetName() if (!IsValid()) return ""; - return ClangASTType::GetConstTypeName(m_opaque_sp->GetOpaqueQualType()).GetCString(); + return ClangASTType::GetConstTypeName(m_opaque_sp->GetASTContext(), + m_opaque_sp->GetOpaqueQualType()).GetCString(); } lldb::TypeClass diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index c3d966ff07e..c5a5fd27294 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -138,7 +138,8 @@ SBValue::GetTypeName () const char *name = NULL; lldb::ValueObjectSP value_sp(GetSP()); if (value_sp) - name = value_sp->GetTypeName().GetCString(); + //name = value_sp->GetTypeName().GetCString(); + name = value_sp->GetQualifiedTypeName().GetCString(); LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 30c5d946eac..6da176dbf87 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -386,7 +386,7 @@ public: { // We are viewing memory as a type SymbolContext sc; - const bool append = true; + const bool exact_match = false; TypeList type_list; uint32_t reference_count = 0; uint32_t pointer_count = 0; @@ -458,17 +458,16 @@ public: { sc.module_sp->FindTypes (sc, lookup_type_name, - NULL, - append, + exact_match, 1, type_list); } } if (type_list.GetSize() == 0) { - target->GetImages().FindTypes (sc, + target->GetImages().FindTypes2 (sc, lookup_type_name, - append, + exact_match, 1, type_list); } diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 890a60102f9..9fe9f0f8e0a 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1585,12 +1585,13 @@ LookupTypeInModule (CommandInterpreter &interpreter, if (module && name_cstr && name_cstr[0]) { TypeList type_list; - const uint32_t max_num_matches = 1; + const uint32_t max_num_matches = UINT32_MAX; uint32_t num_matches = 0; + bool name_is_fully_qualified = false; SymbolContext sc; ConstString name(name_cstr); - num_matches = module->FindTypes(sc, name, NULL, true, max_num_matches, type_list); + num_matches = module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches, type_list); if (num_matches) { diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index 958ac18c9b6..0496780724a 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -630,7 +630,7 @@ FormatManager::LoadSTLFormatters() std_string_summary_sp); gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"), std_string_summary_sp); - gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char, class std::char_traits<char>, class std::allocator<char> >"), + gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"), std_string_summary_sp); @@ -676,7 +676,7 @@ FormatManager::LoadLibcxxFormatters() libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::string"), std_string_summary_sp); - libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::basic_string<char, class std::__1::char_traits<char>, class std::__1::allocator<char> >"), + libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"), std_string_summary_sp); SyntheticChildren::Flags stl_synth_flags; diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index dea7b1f4b0b..48fc499c91b 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -632,7 +632,12 @@ Module::FindFunctions (const RegularExpression& regex, } uint32_t -Module::FindTypes_Impl (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types) +Module::FindTypes_Impl (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + bool append, + uint32_t max_matches, + TypeList& types) { Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); if (sc.module_sp.get() == NULL || sc.module_sp.get() == this) @@ -644,46 +649,59 @@ Module::FindTypes_Impl (const SymbolContext& sc, const ConstString &name, const return 0; } -// depending on implementation details, type lookup might fail because of -// embedded spurious namespace:: prefixes. this call strips them, paying -// attention to the fact that a type might have namespace'd type names as -// arguments to templates, and those must not be stripped off -static const char* -StripTypeName(const char* name_cstr) +uint32_t +Module::FindTypesInNamespace (const SymbolContext& sc, + const ConstString &type_name, + const ClangNamespaceDecl *namespace_decl, + uint32_t max_matches, + TypeList& type_list) { - // Protect against null c string. - if (!name_cstr) - return name_cstr; - const char* skip_namespace = strstr(name_cstr, "::"); - const char* template_arg_char = strchr(name_cstr, '<'); - while (skip_namespace != NULL) - { - if (template_arg_char != NULL && - skip_namespace > template_arg_char) // but namespace'd template arguments are still good to go - break; - name_cstr = skip_namespace+2; - skip_namespace = strstr(name_cstr, "::"); - } - return name_cstr; + const bool append = true; + return FindTypes_Impl(sc, type_name, namespace_decl, append, max_matches, type_list); } uint32_t -Module::FindTypes (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types) +Module::FindTypes (const SymbolContext& sc, + const ConstString &name, + bool exact_match, + uint32_t max_matches, + TypeList& types) { - uint32_t retval = FindTypes_Impl(sc, name, namespace_decl, append, max_matches, types); - - if (retval == 0) + uint32_t num_matches = 0; + const char *type_name_cstr = name.GetCString(); + std::string type_scope; + std::string type_basename; + const bool append = true; + if (Type::GetTypeScopeAndBasename (type_name_cstr, type_scope, type_basename)) { - const char *orig_name = name.GetCString(); - const char *stripped = StripTypeName(orig_name); - // Only do this lookup if StripTypeName has stripped the name: - if (stripped != orig_name) - return FindTypes_Impl(sc, ConstString(stripped), namespace_decl, append, max_matches, types); + // Check if "name" starts with "::" which means the qualified type starts + // from the root namespace and implies and exact match. The typenames we + // get back from clang do not start with "::" so we need to strip this off + // in order to get the qualfied names to match + + if (type_scope.size() >= 2 && type_scope[0] == ':' && type_scope[1] == ':') + { + type_scope.erase(0,2); + exact_match = true; + } + ConstString type_basename_const_str (type_basename.c_str()); + if (FindTypes_Impl(sc, type_basename_const_str, NULL, append, max_matches, types)) + { + types.RemoveMismatchedTypes (type_scope, type_basename, exact_match); + num_matches = types.GetSize(); + } else - return 0; + { + types.Clear(); + } } else - return retval; + { + // The type is not in a namespace/class scope, just search for it by basename + num_matches = FindTypes_Impl(sc, name, NULL, append, max_matches, types); + } + + return num_matches; } diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index 0cc97988029..b612a0cd9d8 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -352,19 +352,16 @@ ModuleList::FindModule (const UUID &uuid) uint32_t -ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) +ModuleList::FindTypes2 (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, uint32_t max_matches, TypeList& types) { Mutex::Locker locker(m_modules_mutex); - - if (!append) - types.Clear(); uint32_t total_matches = 0; collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { if (sc.module_sp.get() == NULL || sc.module_sp.get() == (*pos).get()) - total_matches += (*pos)->FindTypes (sc, name, NULL, true, max_matches, types); + total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types); if (total_matches >= max_matches) break; diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 3d3d03aa746..e072b491652 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -1676,6 +1676,19 @@ ValueObject::GetDeclaration (Declaration &decl) return false; } +ConstString +ValueObject::GetTypeName() +{ + return ClangASTType::GetConstTypeName (GetClangAST(), GetClangType()); +} + +ConstString +ValueObject::GetQualifiedTypeName() +{ + return ClangASTType::GetConstQualifiedTypeName (GetClangAST(), GetClangType()); +} + + LanguageType ValueObject::GetObjectRuntimeLanguage () { @@ -2640,13 +2653,10 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, else { if (ClangASTType::GetMinimumLanguage(root->GetClangAST(), - root->GetClangType()) == eLanguageTypeObjC - && - ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(root->GetClangType())) == false - && - root->HasSyntheticValue() - && - options.m_no_synthetic_children == false) + root->GetClangType()) == eLanguageTypeObjC + && ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(root->GetClangType())) == false + && root->HasSyntheticValue() + && options.m_no_synthetic_children == false) { root = root->GetSyntheticValue()->GetChildAtIndex(index, true); } @@ -3152,7 +3162,8 @@ DumpValueObject_Impl (Stream &s, // Always show the type for the top level items. if (options.m_show_types || (curr_depth == 0 && !options.m_flat_output)) { - const char* typeName = valobj->GetTypeName().AsCString("<invalid type>"); + const char* typeName = valobj->GetQualifiedTypeName().AsCString("<invalid type>"); + //const char* typeName = valobj->GetTypeName().AsCString("<invalid type>"); s.Printf("(%s", typeName); // only show dynamic types if the user really wants to see types if (options.m_show_types && options.m_use_dynamic != eNoDynamicValues && diff --git a/lldb/source/Core/ValueObjectChild.cpp b/lldb/source/Core/ValueObjectChild.cpp index 0cb0d6e9eac..52e773d3772 100644 --- a/lldb/source/Core/ValueObjectChild.cpp +++ b/lldb/source/Core/ValueObjectChild.cpp @@ -73,7 +73,7 @@ ValueObjectChild::GetTypeName() { if (m_type_name.IsEmpty()) { - m_type_name = ClangASTType::GetConstTypeName (GetClangType()); + m_type_name = ClangASTType::GetConstTypeName (GetClangAST(), GetClangType()); if (m_type_name) { if (m_bitfield_bit_size > 0) @@ -91,6 +91,26 @@ ValueObjectChild::GetTypeName() return m_type_name; } +ConstString +ValueObjectChild::GetQualifiedTypeName() +{ + ConstString qualified_name = ClangASTType::GetConstQualifiedTypeName (GetClangAST(), GetClangType()); + if (qualified_name) + { + if (m_bitfield_bit_size > 0) + { + const char *clang_type_name = qualified_name.AsCString(); + if (clang_type_name) + { + std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0); + ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, m_bitfield_bit_size); + qualified_name.SetCString(&bitfield_type_name.front()); + } + } + } + return qualified_name; +} + bool ValueObjectChild::UpdateValue () { diff --git a/lldb/source/Core/ValueObjectConstResult.cpp b/lldb/source/Core/ValueObjectConstResult.cpp index dfa4cfa981a..08d983276a9 100644 --- a/lldb/source/Core/ValueObjectConstResult.cpp +++ b/lldb/source/Core/ValueObjectConstResult.cpp @@ -316,7 +316,7 @@ ConstString ValueObjectConstResult::GetTypeName() { if (m_type_name.IsEmpty()) - m_type_name = ClangASTType::GetConstTypeName (GetClangType()); + m_type_name = ClangASTType::GetConstTypeName (GetClangAST(), GetClangType()); return m_type_name; } diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp index 2e9f06728f4..6fd4ee88592 100644 --- a/lldb/source/Core/ValueObjectDynamicValue.cpp +++ b/lldb/source/Core/ValueObjectDynamicValue.cpp @@ -66,12 +66,6 @@ ValueObjectCast::GetClangTypeImpl () return m_cast_type.GetOpaqueQualType(); } -ConstString -ValueObjectCast::GetTypeName() -{ - return ClangASTType::GetConstTypeName (GetClangType()); -} - uint32_t ValueObjectCast::CalculateNumChildren() { @@ -172,7 +166,7 @@ ValueObjectDynamicValue::GetTypeName() { const bool success = UpdateValueIfNeeded(false); if (success && m_type_sp) - return ClangASTType::GetConstTypeName (GetClangType()); + return ClangASTType::GetConstTypeName (GetClangAST(), GetClangType()); else return m_parent->GetTypeName(); } diff --git a/lldb/source/Core/ValueObjectMemory.cpp b/lldb/source/Core/ValueObjectMemory.cpp index 960895fa66e..7b3dbf2f307 100644 --- a/lldb/source/Core/ValueObjectMemory.cpp +++ b/lldb/source/Core/ValueObjectMemory.cpp @@ -143,7 +143,7 @@ ValueObjectMemory::GetTypeName() { if (m_type_sp) return m_type_sp->GetName(); - return ClangASTType::GetConstTypeName (m_clang_type.GetOpaqueQualType()); + return ClangASTType::GetConstTypeName (GetClangAST(), m_clang_type.GetOpaqueQualType()); } uint32_t diff --git a/lldb/source/Core/ValueObjectRegister.cpp b/lldb/source/Core/ValueObjectRegister.cpp index 425b461cdcb..befd610f65f 100644 --- a/lldb/source/Core/ValueObjectRegister.cpp +++ b/lldb/source/Core/ValueObjectRegister.cpp @@ -326,7 +326,7 @@ ConstString ValueObjectRegister::GetTypeName() { if (m_type_name.IsEmpty()) - m_type_name = ClangASTType::GetConstTypeName (GetClangType()); + m_type_name = ClangASTType::GetConstTypeName (GetClangAST(), GetClangType()); return m_type_name; } diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index f5c5d0132da..d71ec97ce3c 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -67,8 +67,16 @@ ValueObjectVariable::GetTypeName() Type * var_type = m_variable_sp->GetType(); if (var_type) return var_type->GetName(); - ConstString empty_type_name; - return empty_type_name; + return ConstString(); +} + +ConstString +ValueObjectVariable::GetQualifiedTypeName() +{ + Type * var_type = m_variable_sp->GetType(); + if (var_type) + return var_type->GetQualifiedName(); + return ConstString(); } uint32_t diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Expression/ClangASTSource.cpp index 08f63b5c8f8..9933ed1976e 100644 --- a/lldb/source/Expression/ClangASTSource.cpp +++ b/lldb/source/Expression/ClangASTSource.cpp @@ -206,7 +206,7 @@ ClangASTSource::CompleteType (TagDecl *tag_decl) SymbolContext null_sc; ConstString name(tag_decl->getName().str().c_str()); - i->first->FindTypes(null_sc, name, &i->second, true, UINT32_MAX, types); + i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types); for (uint32_t ti = 0, te = types.GetSize(); ti != te && !found; @@ -244,7 +244,8 @@ ClangASTSource::CompleteType (TagDecl *tag_decl) ModuleList &module_list = m_target->GetImages(); - module_list.FindTypes(null_sc, name, true, UINT32_MAX, types); + bool exact_match = false; + module_list.FindTypes2 (null_sc, name, exact_match, UINT32_MAX, types); for (uint32_t ti = 0, te = types.GetSize(); ti != te && !found; @@ -592,11 +593,12 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, { TypeList types; SymbolContext null_sc; + const bool exact_match = false; if (module_sp && namespace_decl) - module_sp->FindTypes(null_sc, name, &namespace_decl, true, 1, types); + module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types); else - m_target->GetImages().FindTypes(null_sc, name, true, 1, types); + m_target->GetImages().FindTypes2(null_sc, name, exact_match, 1, types); if (types.GetSize()) { diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp index a3d177cf4c1..a6344f925ee 100644 --- a/lldb/source/Expression/ClangFunction.cpp +++ b/lldb/source/Expression/ClangFunction.cpp @@ -113,7 +113,8 @@ ClangFunction::CompileFunction (Stream &errors) // FIXME: How does clang tell us there's no return value? We need to handle that case. unsigned num_errors = 0; - std::string return_type_str (ClangASTType::GetTypeNameForOpaqueQualType (m_function_return_qual_type)); + std::string return_type_str (ClangASTType::GetTypeNameForOpaqueQualType (m_clang_ast_context->getASTContext(), + m_function_return_qual_type)); // Cons up the function we're going to wrap our call in, then compile it... // We declare the function "extern "C"" because the compiler might be in C++ @@ -159,7 +160,8 @@ ClangFunction::CompileFunction (Stream &errors) if (trust_function) { lldb::clang_type_t arg_clang_type = m_function_ptr->GetArgumentTypeAtIndex(i); - type_name = ClangASTType::GetTypeNameForOpaqueQualType (arg_clang_type); + type_name = ClangASTType::GetTypeNameForOpaqueQualType (m_clang_ast_context->getASTContext(), + arg_clang_type); } else { @@ -167,7 +169,8 @@ ClangFunction::CompileFunction (Stream &errors) lldb::clang_type_t clang_qual_type = arg_value->GetClangType (); if (clang_qual_type != NULL) { - type_name = ClangASTType::GetTypeNameForOpaqueQualType (clang_qual_type); + type_name = ClangASTType::GetTypeNameForOpaqueQualType (m_clang_ast_context->getASTContext(), + clang_qual_type); } else { diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 0f8d70487b4..5a4f4f7ad73 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -57,9 +57,6 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, // Only a pointer or reference type can have a different dynamic and static type: if (CouldHaveDynamicValue (in_value)) { - // FIXME: Can we get the Clang Type and ask it if the thing is really virtual? That would avoid false positives, - // at the cost of not looking for the dynamic type of objects if DWARF->Clang gets it wrong. - // First job, pull out the address at 0 offset from the object. AddressType address_type; lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); @@ -107,52 +104,76 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, const char *name = symbol->GetMangled().GetDemangledName().AsCString(); if (strstr(name, vtable_demangled_prefix) == name) { + printf ("0x%16.16llx: static-type = '%s' has vtable symbol '%s'\n", + original_ptr, + in_value.GetTypeName().GetCString(), + name); // We are a C++ class, that's good. Get the class name and look it up: const char *class_name = name + strlen(vtable_demangled_prefix); class_type_or_name.SetName (class_name); + const bool exact_match = true; TypeList class_types; - uint32_t num_matches = target->GetImages().FindTypes (sc, - ConstString(class_name), - true, - UINT32_MAX, - class_types); + uint32_t num_matches = target->GetImages().FindTypes2 (sc, + ConstString(class_name), + exact_match, + UINT32_MAX, + class_types); + if (num_matches == 0) + { + printf ("0x%16.16llx: is not dynamic\n", original_ptr); + return false; + } if (num_matches == 1) { + lldb::TypeSP type_sp(class_types.GetTypeAtIndex(0)); + + printf ("0x%16.16llx: static-type = '%s' has single matching dynamic type: uid={0x%llx}, type-name='%s'\n", + original_ptr, + in_value.GetTypeName().AsCString(), + type_sp->GetID(), + type_sp->GetName().GetCString()); + class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0)); } else if (num_matches > 1) { for (size_t i = 0; i < num_matches; i++) { - lldb::TypeSP this_type(class_types.GetTypeAtIndex(i)); - if (this_type) + lldb::TypeSP type_sp(class_types.GetTypeAtIndex(i)); + if (type_sp) { - if (ClangASTContext::IsCXXClassType(this_type->GetClangFullType())) - { - // There can only be one type with a given name, - // so we've just found duplicate definitions, and this - // one will do as well as any other. - // We don't consider something to have a dynamic type if - // it is the same as the static type. So compare against - // the value we were handed: - - clang::ASTContext *in_ast_ctx = in_value.GetClangAST (); - clang::ASTContext *this_ast_ctx = this_type->GetClangAST (); - if (in_ast_ctx != this_ast_ctx - || !ClangASTContext::AreTypesSame (in_ast_ctx, - in_value.GetClangType(), - this_type->GetClangFullType())) - { - class_type_or_name.SetTypeSP (this_type); - return true; - } - return false; - } + printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types: uid={0x%llx}, type-name='%s'\n", + original_ptr, + in_value.GetTypeName().AsCString(), + type_sp->GetID(), + type_sp->GetName().GetCString()); + + +// if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType())) +// { +// // There can only be one type with a given name, +// // so we've just found duplicate definitions, and this +// // one will do as well as any other. +// // We don't consider something to have a dynamic type if +// // it is the same as the static type. So compare against +// // the value we were handed: +// +// clang::ASTContext *in_ast_ctx = in_value.GetClangAST (); +// clang::ASTContext *this_ast_ctx = type_sp->GetClangAST (); +// if (in_ast_ctx != this_ast_ctx +// || !ClangASTContext::AreTypesSame (in_ast_ctx, +// in_value.GetClangType(), +// type_sp->GetClangFullType())) +// { +// class_type_or_name.SetTypeSP (this_type); +// return true; +// } +// return false; +// } } } - } - else return false; + } // The offset_to_top is two pointers above the address. Address offset_to_top_address = address_point_address; @@ -187,7 +208,6 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, } } } - } return false; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index c80cc880c1e..8d92a9bcfe8 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -349,9 +349,10 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value, TypeList class_types; SymbolContext sc; - uint32_t num_matches = target.GetImages().FindTypes (sc, + const bool exact_match = true; + uint32_t num_matches = target.GetImages().FindTypes2 (sc, class_type_or_name.GetName(), - true, + exact_match, UINT32_MAX, class_types); if (num_matches == 1) diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index df0c555729e..eea30625be0 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -476,12 +476,6 @@ PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info) if (IsHost()) { - if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) - { - const bool is_localhost = true; - if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost)) - return error; - } error = Platform::LaunchProcess (launch_info); } else diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index dd22838bf11..44e66b5b571 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1991,7 +1991,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (lldb::clang_type_t clang_type if (class_language == eLanguageTypeObjC) { - std::string class_str (ClangASTType::GetTypeNameForOpaqueQualType(clang_type)); + std::string class_str (ClangASTType::GetTypeNameForOpaqueQualType(ast.getASTContext(), clang_type)); if (!class_str.empty()) { diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 3a78854db84..4f1d77a9603 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -1038,10 +1038,10 @@ ClangASTContext::CopyDecl (ASTContext *dst_ast, } bool -ClangASTContext::AreTypesSame(ASTContext *ast, - clang_type_t type1, - clang_type_t type2, - bool ignore_qualifiers) +ClangASTContext::AreTypesSame (ASTContext *ast, + clang_type_t type1, + clang_type_t type2, + bool ignore_qualifiers) { QualType type1_qual = QualType::getFromOpaquePtr(type1); QualType type2_qual = QualType::getFromOpaquePtr(type2); @@ -3797,7 +3797,7 @@ ClangASTContext::GetChildClangTypeAtIndex // Base classes should be a multiple of 8 bits in size child_byte_offset = bit_offset/8; - child_name = ClangASTType::GetTypeNameForQualType(base_class->getType()); + child_name = ClangASTType::GetTypeNameForQualType(ast, base_class->getType()); uint64_t clang_type_info_bit_size = ast->getTypeSize(base_class->getType()); @@ -4662,7 +4662,7 @@ ClangASTContext::GetIndexOfChildWithName if (omit_empty_base_classes && RecordHasFields(base_class_decl) == false) continue; - std::string base_class_type_name (ClangASTType::GetTypeNameForQualType(base_class->getType())); + std::string base_class_type_name (ClangASTType::GetTypeNameForQualType(ast, base_class->getType())); if (base_class_type_name.compare (name) == 0) return child_idx; ++child_idx; diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index 543fad954c7..c7b522c7659 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -47,87 +47,64 @@ ClangASTType::~ClangASTType() } std::string -ClangASTType::GetTypeNameForQualType (clang::QualType qual_type) +ClangASTType::GetTypeNameForQualType (clang::ASTContext *ast, clang::QualType qual_type) { std::string type_name; + clang::PrintingPolicy printing_policy (ast->getPrintingPolicy()); + printing_policy.SuppressTagKeyword = true; const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>(); if (typedef_type) { const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); - type_name = typedef_decl->getQualifiedNameAsString(); + type_name = typedef_decl->getQualifiedNameAsString(printing_policy); } else { - type_name = qual_type.getAsString(); + type_name = qual_type.getAsString(printing_policy); } - - // There is no call to a clang type to get the type name without the - // class/struct/union/enum on the front, so lets strip it here - const char *type_name_cstr = type_name.c_str(); - if (type_name_cstr[0] == 'c' && - type_name_cstr[1] == 'l' && - type_name_cstr[2] == 'a' && - type_name_cstr[3] == 's' && - type_name_cstr[4] == 's' && - type_name_cstr[5] == ' ') - { - type_name.erase (0, 6); - } - else if (type_name_cstr[0] == 's' && - type_name_cstr[1] == 't' && - type_name_cstr[2] == 'r' && - type_name_cstr[3] == 'u' && - type_name_cstr[4] == 'c' && - type_name_cstr[5] == 't' && - type_name_cstr[6] == ' ') - { - type_name.erase (0, 7); - } - else if (type_name_cstr[0] == 'u' && - type_name_cstr[1] == 'n' && - type_name_cstr[2] == 'i' && - type_name_cstr[3] == 'o' && - type_name_cstr[4] == 'n' && - type_name_cstr[5] == ' ') - { - type_name.erase (0, 6); - } - else if (type_name_cstr[0] == 'e' && - type_name_cstr[1] == 'n' && - type_name_cstr[2] == 'u' && - type_name_cstr[3] == 'm' && - type_name_cstr[4] == ' ') - { - type_name.erase (0, 5); - } - return type_name; } std::string -ClangASTType::GetTypeNameForOpaqueQualType (clang_type_t opaque_qual_type) +ClangASTType::GetTypeNameForOpaqueQualType (clang::ASTContext *ast, clang_type_t opaque_qual_type) { - return GetTypeNameForQualType (clang::QualType::getFromOpaquePtr(opaque_qual_type)); + return GetTypeNameForQualType (ast, clang::QualType::getFromOpaquePtr(opaque_qual_type)); } ConstString ClangASTType::GetConstTypeName () { + // TODO: verify if we actually need to complete a type just to get its type name???? + if (!ClangASTContext::GetCompleteType (this->m_ast, this->m_type)) + return ConstString("<invalid>"); + return GetConstTypeName (m_ast, m_type); +} + +ConstString +ClangASTType::GetConstQualifiedTypeName () +{ + // TODO: verify if we actually need to complete a type just to get its fully qualified type name???? if (!ClangASTContext::GetCompleteType (this->m_ast, this->m_type)) return ConstString("<invalid>"); - return GetConstTypeName (m_type); + return GetConstQualifiedTypeName (m_ast, m_type); } ConstString -ClangASTType::GetConstTypeName (clang_type_t clang_type) +ClangASTType::GetConstQualifiedTypeName (clang::ASTContext *ast, clang_type_t opaque_qual_type) +{ + return ConstString (GetTypeNameForQualType (ast, clang::QualType::getFromOpaquePtr(opaque_qual_type)).c_str()); +} + + +ConstString +ClangASTType::GetConstTypeName (clang::ASTContext *ast, clang_type_t clang_type) { if (!clang_type) return ConstString("<invalid>"); - clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type)); - std::string type_name (GetTypeNameForQualType (qual_type)); + std::string type_name (GetTypeNameForOpaqueQualType(ast, clang_type)); ConstString const_type_name; if (type_name.empty()) const_type_name.SetCString ("<invalid>"); diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 24196228506..a3a9a4f319a 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -120,8 +120,19 @@ Type::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_name) *s << "id = " << (const UserID&)*this; // Call the name accessor to make sure we resolve the type name - if (show_name && GetName()) - *s << ", name = \"" << m_name << '"'; + if (show_name) + { + const ConstString &type_name = GetName(); + if (type_name) + { + *s << ", name = \"" << type_name << '"'; + ConstString qualified_type_name (GetQualifiedName()); + if (qualified_type_name != type_name) + { + *s << ", qualified = \"" << qualified_type_name << '"'; + } + } + } // Call the get byte size accesor so we resolve our byte size if (GetByteSize()) @@ -213,7 +224,7 @@ Type::GetName() if (!m_name) { if (ResolveClangType(eResolveStateForward)) - m_name = ClangASTType::GetConstTypeName (m_clang_type); + m_name = ClangASTType::GetConstTypeName (GetClangASTContext ().getASTContext(), m_clang_type); } return m_name; } @@ -693,6 +704,49 @@ Type::IsRealObjCClass() return false; } +ConstString +Type::GetQualifiedName () +{ + ConstString qualified_name (ClangASTType::GetTypeNameForOpaqueQualType (GetClangASTContext ().getASTContext(), GetClangForwardType()).c_str()); + return qualified_name; +} + + +bool +Type::GetTypeScopeAndBasename (const char* name_cstr, + std::string &scope, + std::string &basename) +{ + // Protect against null c string. + + if (name_cstr && name_cstr[0]) + { + const char *basename_cstr = name_cstr; + const char* namespace_separator = ::strstr (basename_cstr, "::"); + if (namespace_separator) + { + const char* template_arg_char = ::strchr (basename_cstr, '<'); + while (namespace_separator != NULL) + { + if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go + break; + basename_cstr = namespace_separator + 2; + namespace_separator = strstr(basename_cstr, "::"); + } + if (basename_cstr > name_cstr) + { + scope.assign (name_cstr, basename_cstr - name_cstr); + basename.assign (basename_cstr); + return true; + } + } + } + return false; +} + + + + TypeAndOrName::TypeAndOrName () : m_type_sp(), m_type_name() { diff --git a/lldb/source/Symbol/TypeList.cpp b/lldb/source/Symbol/TypeList.cpp index b6ddb42bd49..f90334ea9ec 100644 --- a/lldb/source/Symbol/TypeList.cpp +++ b/lldb/source/Symbol/TypeList.cpp @@ -135,6 +135,20 @@ TypeList::GetTypeAtIndex(uint32_t idx) return TypeSP(); } +bool +TypeList::RemoveTypeWithUID (user_id_t uid) +{ + iterator pos = m_types.find(uid); + + if (pos != m_types.end()) + { + m_types.erase(pos); + return true; + } + return false; +} + + void TypeList::Dump(Stream *s, bool show_context) { @@ -144,6 +158,147 @@ TypeList::Dump(Stream *s, bool show_context) } } +// depending on implementation details, type lookup might fail because of +// embedded spurious namespace:: prefixes. this call strips them, paying +// attention to the fact that a type might have namespace'd type names as +// arguments to templates, and those must not be stripped off +static bool +GetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr) +{ + // Protect against null c string. + + if (name_cstr && name_cstr[0]) + { + const char *basename_cstr = name_cstr; + const char* namespace_separator = ::strstr (basename_cstr, "::"); + if (namespace_separator) + { + const char* template_arg_char = ::strchr (basename_cstr, '<'); + while (namespace_separator != NULL) + { + if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go + break; + basename_cstr = namespace_separator + 2; + namespace_separator = strstr(basename_cstr, "::"); + } + if (basename_cstr > name_cstr) + { + scope.assign (name_cstr, basename_cstr - name_cstr); + if (scope.size() >= 2 && scope[0] == ':' && scope[1] == ':') + { + // The typename passed in started with "::" so make sure we only do exact matches + if (exact_ptr) + *exact_ptr = true; + // Strip the leading "::" as this won't ever show in qualified typenames we get + // from clang. + scope.erase(0,2); + } + basename.assign (basename_cstr); + return true; + } + } + } + return false; +} + +void +TypeList::RemoveMismatchedTypes (const char *qualified_typename, + bool exact_match) +{ + std::string type_scope; + std::string type_basename; + if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename)) + { + type_basename = qualified_typename; + type_scope.clear(); + } + return RemoveMismatchedTypes (type_scope, type_basename, exact_match); +} + +void +TypeList::RemoveMismatchedTypes (const std::string &type_scope, + const std::string &type_basename, + bool exact_match) +{ + // Our "collection" type currently is a std::map which doesn't + // have any good way to iterate and remove items from the map + // so we currently just make a new list and add all of the matching + // types to it, and then swap it into m_types at the end + collection matching_types; + + iterator pos, end = m_types.end(); + + for (pos = m_types.begin(); pos != end; ++pos) + { + Type* the_type = pos->second.get(); + bool keep_match = false; + + ConstString match_type_name_const_str (the_type->GetQualifiedName()); + if (match_type_name_const_str) + { + const char *match_type_name = match_type_name_const_str.GetCString(); + std::string match_type_scope; + std::string match_type_basename; + if (Type::GetTypeScopeAndBasename (match_type_name, + match_type_scope, + match_type_basename)) + { + if (match_type_basename == type_basename) + { + const size_t type_scope_size = type_scope.size(); + const size_t match_type_scope_size = match_type_scope.size(); + if (exact_match || (type_scope_size == match_type_scope_size)) + { + keep_match = match_type_scope == type_scope; + } + else + { + if (match_type_scope_size > type_scope_size) + { + const size_t type_scope_pos = match_type_scope.rfind(type_scope); + if (type_scope_pos == match_type_scope_size - type_scope_size) + { + if (type_scope_pos >= 2) + { + // Our match scope ends with the type scope we were lookikng for, + // but we need to make sure what comes before the matching + // type scope is a namepace boundary in case we are trying to match: + // type_basename = "d" + // type_scope = "b::c::" + // We want to match: + // match_type_scope "a::b::c::" + // But not: + // match_type_scope "a::bb::c::" + // So below we make sure what comes before "b::c::" in match_type_scope + // is "::", or the namespace boundary + if (match_type_scope[type_scope_pos - 1] == ':' && + match_type_scope[type_scope_pos - 2] == ':') + { + keep_match = true; + } + } + } + } + } + } + } + else + { + // The type we are currently looking at doesn't exists + // in a namespace or class, so it only matches if there + // is no type scope... + keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0; + } + } + + if (keep_match) + { + matching_types.insert (*pos); + } + } + m_types.swap(matching_types); +} + //void * //TypeList::CreateClangPointerType (Type *type) //{ diff --git a/lldb/source/Target/CPPLanguageRuntime.cpp b/lldb/source/Target/CPPLanguageRuntime.cpp index 889fc9fb947..6b36d14a114 100644 --- a/lldb/source/Target/CPPLanguageRuntime.cpp +++ b/lldb/source/Target/CPPLanguageRuntime.cpp @@ -23,11 +23,9 @@ public: { m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>")); - m_impl.Append(ConstString("class std::basic_string<char, class std::char_traits<char>, class std::allocator<char> >").AsCString(), ConstString("basic_string<char>")); // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>")); - m_impl.Append(ConstString("class std::basic_string<char, class std::char_traits<char>, class std::allocator<char> >").AsCString(), ConstString("std::asic_string<char>")); m_impl.Sort(); } diff --git a/lldb/source/Target/ObjCLanguageRuntime.cpp b/lldb/source/Target/ObjCLanguageRuntime.cpp index 6d6caefa64f..db51729ee99 100644 --- a/lldb/source/Target/ObjCLanguageRuntime.cpp +++ b/lldb/source/Target/ObjCLanguageRuntime.cpp @@ -130,17 +130,15 @@ ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name) return TypeSP(); const SymbolContext null_sc; - const ClangNamespaceDecl *null_namespace_decl = NULL; - const bool append = false; + const bool exact_match = true; const uint32_t max_matches = UINT32_MAX; TypeList types; - module_sp->FindTypes(null_sc, - name, - null_namespace_decl, - append, - max_matches, - types); + module_sp->FindTypes (null_sc, + name, + exact_match, + max_matches, + types); if (types.GetSize() == 1) { diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index cc8070d437c..dcb8ba10c52 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -567,7 +567,19 @@ Platform::LaunchProcess (ProcessLaunchInfo &launch_info) // Take care of the host case so that each subclass can just // call this function to get the host functionality. if (IsHost()) + { + if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY")) + launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY); + + if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) + { + const bool is_localhost = true; + if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost)) + return error; + } + error = Host::LaunchProcess (launch_info); + } else error.SetErrorString ("base lldb_private::Platform class can't launch remote processes"); return error; |

