diff options
44 files changed, 581 insertions, 259 deletions
diff --git a/lldb/include/lldb/Core/FormatNavigator.h b/lldb/include/lldb/Core/FormatNavigator.h index f65eba416fb..eef20cc3dd0 100644 --- a/lldb/include/lldb/Core/FormatNavigator.h +++ b/lldb/include/lldb/Core/FormatNavigator.h @@ -519,11 +519,11 @@ protected: return false; } - bool Get(ValueObject& valobj, - clang::QualType type, - MapValueType& entry, - lldb::DynamicValueType use_dynamic, - uint32_t& reason) + bool Get (ValueObject& valobj, + clang::QualType type, // TODO: find out why "type" is passed in the type when it belongs to valobj? Can it ever differ? + MapValueType& entry, + lldb::DynamicValueType use_dynamic, + uint32_t& reason) { LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); if (type.isNull()) @@ -541,7 +541,7 @@ protected: log->Printf("type is NULL, returning"); return false; } - ConstString typeName(ClangASTType::GetTypeNameForQualType(type).c_str()); + ConstString typeName(ClangASTType::GetTypeNameForQualType(valobj.GetClangAST(), type).c_str()); if (valobj.GetBitfieldBitSize() > 0) { diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 0dd8db5a44b..9c596e11fe7 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -620,32 +620,66 @@ public: //------------------------------------------------------------------ /// Find types by name. /// + /// Type lookups in modules go through the SymbolVendor (which will + /// use one or more SymbolFile subclasses). The SymbolFile needs to + /// be able to lookup types by basename and not the fully qualified + /// typename. This allows the type accelerator tables to stay small, + /// even with heavily templatized C++. The type search will then + /// narrow down the search results. If "exact_match" is true, then + /// the type search will only match exact type name matches. If + /// "exact_match" is false, the type will match as long as the base + /// typename matches and as long as any immediate containing + /// namespaces/class scopes that are specified match. So to search + /// for a type "d" in "b::c", the name "b::c::d" can be specified + /// and it will match any class/namespace "b" which contains a + /// class/namespace "c" which contains type "d". We do this to + /// allow users to not always have to specify complete scoping on + /// all expressions, but it also allows for exact matching when + /// required. + /// /// @param[in] sc /// A symbol context that scopes where to extract a type list /// from. /// - /// @param[in] name - /// The name of the type we are looking for. + /// @param[in] type_name + /// The name of the type we are looking for that is a fully + /// or partially qualfieid type name. /// - /// @param[in] namespace_decl - /// If valid, a namespace to search in. + /// @param[in] exact_match + /// If \b true, \a type_name is fully qualifed and must match + /// exactly. If \b false, \a type_name is a partially qualfied + /// name where the leading namespaces or classes can be + /// omitted to make finding types that a user may type + /// easier. /// - /// @param[in] append - /// If \b true, any matches will be appended to \a - /// variable_list, else matches replace the contents of - /// \a variable_list. + /// @param[out] type_list + /// A type list gets populated with any matches. /// - /// @param[in] max_matches - /// Allow the number of matches to be limited to \a - /// max_matches. Specify UINT32_MAX to get all possible matches. + /// @return + /// The number of matches added to \a type_list. + //------------------------------------------------------------------ + uint32_t + FindTypes (const SymbolContext& sc, + const ConstString &type_name, + bool exact_match, + uint32_t max_matches, + TypeList& types); + + //------------------------------------------------------------------ + /// Find types by name that are in a namespace. This function is + /// used by the expression parser when searches need to happen in + /// an exact namespace scope. /// - /// @param[in] encoding - /// Limit the search to specific types, or get all types if - /// set to Type::invalid. + /// @param[in] sc + /// A symbol context that scopes where to extract a type list + /// from. /// - /// @param[in] udt_name - /// If the encoding is a user defined type, specify the name - /// of the user defined type ("struct", "union", "class", etc). + /// @param[in] type_name + /// The name of a type within a namespace that should not include + /// any qualifying namespaces (just a type basename). + /// + /// @param[in] namespace_decl + /// The namespace declaration that this type must exist in. /// /// @param[out] type_list /// A type list gets populated with any matches. @@ -654,12 +688,11 @@ public: /// The number of matches added to \a type_list. //------------------------------------------------------------------ uint32_t - FindTypes (const SymbolContext& sc, - const ConstString &name, - const ClangNamespaceDecl *namespace_decl, - bool append, - uint32_t max_matches, - TypeList& types); + FindTypesInNamespace (const SymbolContext& sc, + const ConstString &type_name, + const ClangNamespaceDecl *namespace_decl, + uint32_t max_matches, + TypeList& type_list); //------------------------------------------------------------------ /// Get const accessor for the module architecture. diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index bb6f0288112..1d31c415216 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -340,10 +340,10 @@ public: /// The number of matches added to \a type_list. //------------------------------------------------------------------ uint32_t - FindTypes (const SymbolContext& sc, - const ConstString &name, - bool append, - uint32_t max_matches, + FindTypes2 (const SymbolContext& sc, + const ConstString &name, + bool name_is_fully_qualified, + uint32_t max_matches, TypeList& types); bool diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index ed8948a1719..17d03fbbf26 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -566,12 +566,15 @@ public: virtual lldb::ValueType GetValueType() const = 0; - virtual ConstString - GetTypeName() = 0; - //------------------------------------------------------------------ // Sublasses can implement the functions below. //------------------------------------------------------------------ + virtual ConstString + GetTypeName(); + + virtual ConstString + GetQualifiedTypeName(); + virtual lldb::LanguageType GetObjectRuntimeLanguage(); diff --git a/lldb/include/lldb/Core/ValueObjectChild.h b/lldb/include/lldb/Core/ValueObjectChild.h index 2e0384edd0b..4e1e47fa613 100644 --- a/lldb/include/lldb/Core/ValueObjectChild.h +++ b/lldb/include/lldb/Core/ValueObjectChild.h @@ -59,6 +59,9 @@ public: virtual ConstString GetTypeName(); + virtual ConstString + GetQualifiedTypeName(); + virtual bool IsInScope (); diff --git a/lldb/include/lldb/Core/ValueObjectDynamicValue.h b/lldb/include/lldb/Core/ValueObjectDynamicValue.h index a6fdab49bb6..7b2785f5229 100644 --- a/lldb/include/lldb/Core/ValueObjectDynamicValue.h +++ b/lldb/include/lldb/Core/ValueObjectDynamicValue.h @@ -33,9 +33,6 @@ namespace lldb_private { virtual size_t GetByteSize(); - virtual ConstString - GetTypeName(); - virtual uint32_t CalculateNumChildren(); diff --git a/lldb/include/lldb/Core/ValueObjectVariable.h b/lldb/include/lldb/Core/ValueObjectVariable.h index 2051abcef36..70807b43003 100644 --- a/lldb/include/lldb/Core/ValueObjectVariable.h +++ b/lldb/include/lldb/Core/ValueObjectVariable.h @@ -37,6 +37,9 @@ public: virtual ConstString GetTypeName(); + virtual ConstString + GetQualifiedTypeName(); + virtual uint32_t CalculateNumChildren(); diff --git a/lldb/include/lldb/Symbol/ClangASTType.h b/lldb/include/lldb/Symbol/ClangASTType.h index 75f71d16a86..623499ac047 100644 --- a/lldb/include/lldb/Symbol/ClangASTType.h +++ b/lldb/include/lldb/Symbol/ClangASTType.h @@ -78,15 +78,25 @@ public: ConstString GetConstTypeName (); + + ConstString + GetConstQualifiedTypeName (); static ConstString - GetConstTypeName (lldb::clang_type_t clang_type); + GetConstTypeName (clang::ASTContext *ast, + lldb::clang_type_t clang_type); + static ConstString + GetConstQualifiedTypeName (clang::ASTContext *ast, + lldb::clang_type_t clang_type); + static std::string - GetTypeNameForQualType (clang::QualType qual_type); + GetTypeNameForQualType (clang::ASTContext *ast, + clang::QualType qual_type); static std::string - GetTypeNameForOpaqueQualType (lldb::clang_type_t opaque_qual_type); + GetTypeNameForOpaqueQualType (clang::ASTContext *ast, + lldb::clang_type_t opaque_qual_type); uint32_t GetClangTypeBitWidth (); diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index dc59bea74e8..829b0a287a3 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -147,6 +147,9 @@ public: return m_name; } + ConstString + GetQualifiedName (); + void DumpValue(ExecutionContext *exe_ctx, Stream *s, @@ -240,6 +243,12 @@ public: static int Compare(const Type &a, const Type &b); + // From a fully qualified typename, split the type into the type basename + // and the remaining type scope (namespaces/classes). + static bool + GetTypeScopeAndBasename (const char* name_cstr, + std::string &scope, + std::string &basename); void SetEncodingType (Type *encoding_type) { @@ -491,7 +500,7 @@ public: { return m_name; } - + uint64_t GetBitOffset () const { diff --git a/lldb/include/lldb/Symbol/TypeList.h b/lldb/include/lldb/Symbol/TypeList.h index 3ed3471a996..9be29e1b57a 100644 --- a/lldb/include/lldb/Symbol/TypeList.h +++ b/lldb/include/lldb/Symbol/TypeList.h @@ -51,6 +51,17 @@ public: lldb::TypeSP GetTypeAtIndex(uint32_t idx); + bool + RemoveTypeWithUID (lldb::user_id_t uid); + + void + RemoveMismatchedTypes (const char *qualified_typename, + bool exact_match); + + void + RemoveMismatchedTypes (const std::string &type_scope, + const std::string &type_basename, + bool exact_match); private: typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection; typedef collection::iterator iterator; 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; diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py index 2da88eee5d4..871dfe77871 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py @@ -58,7 +58,7 @@ class LibcxxMapDataFormatterTestCase(TestBase): self.runCmd("frame variable ii -T") - self.runCmd("type summary add -x \"std::map<\" --summary-string \"map has ${svar%#} items\" -e") + self.runCmd("type summary add -x \"std::__1::map<\" --summary-string \"map has ${svar%#} items\" -e") self.expect('frame variable ii', substrs = ['map has 0 items', @@ -135,9 +135,6 @@ class LibcxxMapDataFormatterTestCase(TestBase): self.runCmd("n") self.runCmd("frame variable si -T") - #self.runCmd("type summary add std::strint_map strint_map --summary-string \"map has ${svar%#} items\" -e") - #self.runCmd("type synth add std::strint_map strint_map -l StdMapSynthProvider") - self.expect('frame variable si', substrs = ['map has 0 items', '{}']) @@ -210,9 +207,6 @@ class LibcxxMapDataFormatterTestCase(TestBase): self.runCmd("n") self.runCmd("frame variable is -T") - #self.runCmd("type summary add std::intstr_map intstr_map --summary-string \"map has ${svar%#} items\" -e") - #self.runCmd("type synth add std::intstr_map intstr_map -l StdMapSynthProvider") - self.expect('frame variable is', substrs = ['map has 0 items', '{}']) diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py index 9ac78c94117..18ac94a3411 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py @@ -135,9 +135,6 @@ class StdMapDataFormatterTestCase(TestBase): self.runCmd("n") self.runCmd("frame variable si -T") - #self.runCmd("type summary add std::strint_map strint_map --summary-string \"map has ${svar%#} items\" -e") - #self.runCmd("type synth add std::strint_map strint_map -l StdMapSynthProvider") - self.expect('frame variable si', substrs = ['map has 0 items', '{}']) @@ -210,9 +207,6 @@ class StdMapDataFormatterTestCase(TestBase): self.runCmd("n") self.runCmd("frame variable is -T") - #self.runCmd("type summary add std::intstr_map intstr_map --summary-string \"map has ${svar%#} items\" -e") - #self.runCmd("type synth add std::intstr_map intstr_map -l StdMapSynthProvider") - self.expect('frame variable is', substrs = ['map has 0 items', '{}']) diff --git a/lldb/test/lang/c/set_values/TestSetValues.py b/lldb/test/lang/c/set_values/TestSetValues.py index 7808b761c95..d9e1ebf1c31 100644 --- a/lldb/test/lang/c/set_values/TestSetValues.py +++ b/lldb/test/lang/c/set_values/TestSetValues.py @@ -99,12 +99,12 @@ class SetValuesTestCase(TestBase): # main.c:57 # Check that 'frame variable -T' displays the correct data type and value. self.expect("frame variable -T", VARIABLES_DISPLAYED_CORRECTLY, - startstr = "(long int) i = 33") + startstr = "(long) i = 33") # Now set variable 'i' and check that it is correctly displayed. self.runCmd("expression i = 33333") self.expect("frame variable -T", VARIABLES_DISPLAYED_CORRECTLY, - startstr = "(long int) i = 33333") + startstr = "(long) i = 33333") self.runCmd("continue") diff --git a/lldb/test/lang/cpp/signed_types/TestSignedTypes.py b/lldb/test/lang/cpp/signed_types/TestSignedTypes.py index 7a3e8665982..a4c74313c68 100644 --- a/lldb/test/lang/cpp/signed_types/TestSignedTypes.py +++ b/lldb/test/lang/cpp/signed_types/TestSignedTypes.py @@ -58,8 +58,8 @@ class UnsignedTypesTestCase(TestBase): patterns = ["\((short int|short)\) the_signed_short = 99"], substrs = ["(signed char) the_signed_char = 'c'", "(int) the_signed_int = 99", - "(long int) the_signed_long = 99", - "(long long int) the_signed_long_long = 99"]) + "(long) the_signed_long = 99", + "(long long) the_signed_long_long = 99"]) if __name__ == '__main__': diff --git a/lldb/test/lang/cpp/unsigned_types/TestUnsignedTypes.py b/lldb/test/lang/cpp/unsigned_types/TestUnsignedTypes.py index b616f4682ed..8355e8c55cc 100644 --- a/lldb/test/lang/cpp/unsigned_types/TestUnsignedTypes.py +++ b/lldb/test/lang/cpp/unsigned_types/TestUnsignedTypes.py @@ -55,8 +55,8 @@ class UnsignedTypesTestCase(TestBase): startstr = "(unsigned char) the_unsigned_char = 'c'", patterns = ["\((short unsigned int|unsigned short)\) the_unsigned_short = 99"], substrs = ["(unsigned int) the_unsigned_int = 99", - "(long unsigned int) the_unsigned_long = 99", - "(long long unsigned int) the_unsigned_long_long = 99", + "(unsigned long) the_unsigned_long = 99", + "(unsigned long long) the_unsigned_long_long = 99", "(uint32_t) the_uint32 = 99"]) |

