diff options
-rw-r--r-- | lldb/include/lldb/Target/CPPLanguageRuntime.h | 9 | ||||
-rw-r--r-- | lldb/source/Target/CPPLanguageRuntime.cpp | 151 |
2 files changed, 160 insertions, 0 deletions
diff --git a/lldb/include/lldb/Target/CPPLanguageRuntime.h b/lldb/include/lldb/Target/CPPLanguageRuntime.h index e2da738fcbd..5a59b44b5a0 100644 --- a/lldb/include/lldb/Target/CPPLanguageRuntime.h +++ b/lldb/include/lldb/Target/CPPLanguageRuntime.h @@ -12,6 +12,7 @@ // C Includes // C++ Includes +#include <vector> // Other libraries and framework includes // Project includes #include "lldb/Core/PluginInterface.h" @@ -50,6 +51,14 @@ public: static bool StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end); + + // in some cases, compilers will output different names for one same type. when tht happens, it might be impossible + // to construct SBType objects for a valid type, because the name that is available is not the same as the name that + // can be used as a search key in FindTypes(). the equivalents map here is meant to return possible alternative names + // for a type through which a search can be conducted. Currently, this is only enabled for C++ but can be extended + // to ObjC or other languages if necessary + static uint32_t + FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents); protected: //------------------------------------------------------------------ diff --git a/lldb/source/Target/CPPLanguageRuntime.cpp b/lldb/source/Target/CPPLanguageRuntime.cpp index 22fbd8479b5..889fc9fb947 100644 --- a/lldb/source/Target/CPPLanguageRuntime.cpp +++ b/lldb/source/Target/CPPLanguageRuntime.cpp @@ -8,12 +8,147 @@ //===----------------------------------------------------------------------===// #include "lldb/Target/CPPLanguageRuntime.h" + #include "lldb/Core/PluginManager.h" +#include "lldb/Core/UniqueCStringMap.h" #include "lldb/Target/ExecutionContext.h" using namespace lldb; using namespace lldb_private; +class CPPRuntimeEquivalents +{ +public: + CPPRuntimeEquivalents () + { + + 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(); + } + + void + Add (ConstString& type_name, + ConstString& type_equivalent) + { + m_impl.Insert(type_name.AsCString(), type_equivalent); + } + + uint32_t + FindExactMatches (ConstString& type_name, + std::vector<ConstString>& equivalents) + { + + uint32_t count = 0; + + for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString()); + match != NULL; + match = m_impl.FindNextValueForName(match)) + { + equivalents.push_back(match->value); + count++; + } + + return count; + } + + // partial matches can occur when a name with equivalents is a template argument. + // e.g. we may have "class Foo" be a match for "struct Bar". if we have a typename + // such as "class Templatized<class Foo, Anything>" we want this to be replaced with + // "class Templatized<struct Bar, Anything>". Since partial matching is time consuming + // once we get a partial match, we add it to the exact matches list for faster retrieval + uint32_t + FindPartialMatches (ConstString& type_name, + std::vector<ConstString>& equivalents) + { + + uint32_t count = 0; + + const char* type_name_cstr = type_name.AsCString(); + + size_t items_count = m_impl.GetSize(); + + for (size_t item = 0; item < items_count; item++) + { + const char* key_cstr = m_impl.GetCStringAtIndex(item); + if ( strstr(type_name_cstr,key_cstr) ) + { + count += AppendReplacements(type_name_cstr, + key_cstr, + equivalents); + } + } + + return count; + + } + +private: + + std::string& replace (std::string& target, + std::string& pattern, + std::string& with) + { + size_t pos; + size_t pattern_len = pattern.size(); + + while ( (pos = target.find(pattern)) != std::string::npos ) + target.replace(pos, pattern_len, with); + + return target; + } + + uint32_t + AppendReplacements (const char* original, + const char *matching_key, + std::vector<ConstString>& equivalents) + { + + std::string matching_key_str(matching_key); + ConstString original_const(original); + + uint32_t count = 0; + + for (ImplData match = m_impl.FindFirstValueForName(matching_key); + match != NULL; + match = m_impl.FindNextValueForName(match)) + { + std::string target(original); + std::string equiv_class(match->value.AsCString()); + + replace (target, matching_key_str, equiv_class); + + ConstString target_const(target.c_str()); + +// you will most probably want to leave this off since it might make this map grow indefinitely +#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW + Add(original_const, target_const); +#endif + equivalents.push_back(target_const); + + count++; + } + + return count; + } + + typedef UniqueCStringMap<ConstString> Impl; + typedef const Impl::Entry* ImplData; + Impl m_impl; +}; + +static CPPRuntimeEquivalents& +GetEquivalentsMap () +{ + static CPPRuntimeEquivalents g_equivalents_map; + return g_equivalents_map; +} + //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- @@ -118,3 +253,19 @@ CPPLanguageRuntime::IsPossibleCPPCall (const char *name, const char *&base_name_ return StripNamespacesFromVariableName (name, base_name_start, base_name_end); } + +uint32_t +CPPLanguageRuntime::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents) +{ + uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents); + + bool might_have_partials= + ( count == 0 ) // if we have a full name match just use it + && (strchr(type_name.AsCString(), '<') != NULL // we should only have partial matches when templates are involved, check that we have + && strchr(type_name.AsCString(), '>') != NULL); // angle brackets in the type_name before trying to scan for partial matches + + if ( might_have_partials ) + count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents); + + return count; +} |