summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp386
1 files changed, 386 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp
new file mode 100644
index 0000000..f5b7f7f
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp
@@ -0,0 +1,386 @@
+//===-- CPPLanguageRuntime.cpp -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/CPPLanguageRuntime.h"
+
+#include <string.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>"));
+
+ // 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.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
+//----------------------------------------------------------------------
+CPPLanguageRuntime::~CPPLanguageRuntime()
+{
+}
+
+CPPLanguageRuntime::CPPLanguageRuntime (Process *process) :
+ LanguageRuntime (process)
+{
+
+}
+
+bool
+CPPLanguageRuntime::GetObjectDescription (Stream &str, ValueObject &object)
+{
+ // C++ has no generic way to do this.
+ return false;
+}
+
+bool
+CPPLanguageRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope)
+{
+ // C++ has no generic way to do this.
+ return false;
+}
+
+bool
+CPPLanguageRuntime::IsCPPMangledName (const char *name)
+{
+ // FIXME, we should really run through all the known C++ Language plugins and ask each one if
+ // this is a C++ mangled name, but we can put that off till there is actually more than one
+ // we care about.
+
+ if (name && name[0] == '_' && name[1] == 'Z')
+ return true;
+ else
+ return false;
+}
+
+bool
+CPPLanguageRuntime::StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end)
+{
+ if (base_name_end == NULL)
+ base_name_end = name + strlen (name);
+
+ const char *last_colon = strrchr (name, ':');
+
+ if (last_colon == NULL)
+ {
+ base_name_start = name;
+ return true;
+ }
+
+ // Can't have a C++ name that begins with a single ':', nor contains an internal single ':'
+ if (last_colon == name)
+ return false;
+ else if (last_colon[-1] != ':')
+ return false;
+ else
+ {
+ // FIXME: should check if there is
+ base_name_start = last_colon + 1;
+ return true;
+ }
+}
+
+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;
+}
+
+void
+CPPLanguageRuntime::MethodName::Clear()
+{
+ m_full.Clear();
+ m_basename = llvm::StringRef();
+ m_context = llvm::StringRef();
+ m_arguments = llvm::StringRef();
+ m_qualifiers = llvm::StringRef();
+ m_type = eTypeInvalid;
+ m_parsed = false;
+ m_parse_error = false;
+}
+
+bool
+ReverseFindMatchingChars (const llvm::StringRef &s,
+ const llvm::StringRef &left_right_chars,
+ size_t &left_pos,
+ size_t &right_pos,
+ size_t pos = llvm::StringRef::npos)
+{
+ assert (left_right_chars.size() == 2);
+ left_pos = llvm::StringRef::npos;
+ const char left_char = left_right_chars[0];
+ const char right_char = left_right_chars[1];
+ pos = s.find_last_of(left_right_chars, pos);
+ if (pos == llvm::StringRef::npos || s[pos] == left_char)
+ return false;
+ right_pos = pos;
+ uint32_t depth = 1;
+ while (pos > 0 && depth > 0)
+ {
+ pos = s.find_last_of(left_right_chars, pos);
+ if (pos == llvm::StringRef::npos)
+ return false;
+ if (s[pos] == left_char)
+ {
+ if (--depth == 0)
+ {
+ left_pos = pos;
+ return left_pos < right_pos;
+ }
+ }
+ else if (s[pos] == right_char)
+ {
+ ++depth;
+ }
+ }
+ return false;
+}
+
+void
+CPPLanguageRuntime::MethodName::Parse()
+{
+ if (!m_parsed && m_full)
+ {
+// ConstString mangled;
+// m_full.GetMangledCounterpart(mangled);
+// printf ("\n parsing = '%s'\n", m_full.GetCString());
+// if (mangled)
+// printf (" mangled = '%s'\n", mangled.GetCString());
+ m_parse_error = false;
+ m_parsed = true;
+ llvm::StringRef full (m_full.GetCString());
+
+ size_t arg_start, arg_end;
+ llvm::StringRef parens("()", 2);
+ if (ReverseFindMatchingChars (full, parens, arg_start, arg_end))
+ {
+ m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
+ if (arg_end + 1 < full.size())
+ m_qualifiers = full.substr(arg_end + 1);
+ if (arg_start > 0)
+ {
+ size_t basename_end = arg_start;
+ size_t context_end = llvm::StringRef::npos;
+ if (basename_end > 0 && full[basename_end-1] == '>')
+ {
+ // TODO: handle template junk...
+ // Templated function
+ size_t template_start, template_end;
+ llvm::StringRef lt_gt("<>", 2);
+ if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end))
+ context_end = full.rfind(':', template_start);
+ }
+ if (context_end == llvm::StringRef::npos)
+ context_end = full.rfind(':', basename_end);
+
+ if (context_end == llvm::StringRef::npos)
+ m_basename = full.substr(0, basename_end);
+ else
+ {
+ m_context = full.substr(0, context_end - 1);
+ const size_t basename_begin = context_end + 1;
+ m_basename = full.substr(basename_begin, basename_end - basename_begin);
+ }
+ m_type = eTypeUnknownMethod;
+ }
+ else
+ {
+ m_parse_error = true;
+ return;
+ }
+
+// if (!m_context.empty())
+// printf (" context = '%s'\n", m_context.str().c_str());
+// if (m_basename)
+// printf (" basename = '%s'\n", m_basename.GetCString());
+// if (!m_arguments.empty())
+// printf (" arguments = '%s'\n", m_arguments.str().c_str());
+// if (!m_qualifiers.empty())
+// printf ("qualifiers = '%s'\n", m_qualifiers.str().c_str());
+ }
+ else
+ {
+ m_parse_error = true;
+// printf ("error: didn't find matching parens for arguments\n");
+ }
+ }
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetBasename ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_basename;
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetContext ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_context;
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetArguments ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_arguments;
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetQualifiers ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_qualifiers;
+}
+
OpenPOWER on IntegriCloud