diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 11:55:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 11:55:28 +0000 |
commit | e81d9d49145e432d917eea3a70d2ae74dcad1d89 (patch) | |
tree | 9ed5e1a91f242e2cb5911577356e487a55c01b78 /source/Symbol/TypeMap.cpp | |
parent | 85d8ef8f1f0e0e063a8571944302be2d2026f823 (diff) |
Notes
Diffstat (limited to 'source/Symbol/TypeMap.cpp')
-rw-r--r-- | source/Symbol/TypeMap.cpp | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/source/Symbol/TypeMap.cpp b/source/Symbol/TypeMap.cpp new file mode 100644 index 000000000000..6dc22ccbda96 --- /dev/null +++ b/source/Symbol/TypeMap.cpp @@ -0,0 +1,322 @@ +//===-- TypeMap.cpp --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" + +#include "clang/Basic/Builtins.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" + +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" + +// Project includes +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeMap.h" + +using namespace lldb; +using namespace lldb_private; +using namespace clang; + +TypeMap::TypeMap() : + m_types () +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +TypeMap::~TypeMap() +{ +} + +void +TypeMap::Insert (const TypeSP& type_sp) +{ + // Just push each type on the back for now. We will worry about uniquing later + if (type_sp) + m_types.insert(std::make_pair(type_sp->GetID(), type_sp)); +} + + +bool +TypeMap::InsertUnique (const TypeSP& type_sp) +{ + if (type_sp) + { + user_id_t type_uid = type_sp->GetID(); + iterator pos, end = m_types.end(); + + for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos) + { + if (pos->second.get() == type_sp.get()) + return false; + } + Insert (type_sp); + } + return true; +} + +//---------------------------------------------------------------------- +// Find a base type by its unique ID. +//---------------------------------------------------------------------- +//TypeSP +//TypeMap::FindType(lldb::user_id_t uid) +//{ +// iterator pos = m_types.find(uid); +// if (pos != m_types.end()) +// return pos->second; +// return TypeSP(); +//} + +//---------------------------------------------------------------------- +// Find a type by name. +//---------------------------------------------------------------------- +//TypeMap +//TypeMap::FindTypes (const ConstString &name) +//{ +// // Do we ever need to make a lookup by name map? Here we are doing +// // a linear search which isn't going to be fast. +// TypeMap types(m_ast.getTargetInfo()->getTriple().getTriple().c_str()); +// iterator pos, end; +// for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) +// if (pos->second->GetName() == name) +// types.Insert (pos->second); +// return types; +//} + +void +TypeMap::Clear() +{ + m_types.clear(); +} + +uint32_t +TypeMap::GetSize() const +{ + return m_types.size(); +} + +bool +TypeMap::Empty() const +{ + return m_types.empty(); +} + +// GetTypeAtIndex isn't used a lot for large type lists, currently only for +// type lists that are returned for "image dump -t TYPENAME" commands and other +// simple symbol queries that grab the first result... + +TypeSP +TypeMap::GetTypeAtIndex(uint32_t idx) +{ + iterator pos, end; + uint32_t i = idx; + for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) + { + if (i == 0) + return pos->second; + --i; + } + return TypeSP(); +} + +void +TypeMap::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const +{ + for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) + { + if (!callback(pos->second)) + break; + } +} + +void +TypeMap::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback) +{ + for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) + { + if (!callback(pos->second)) + break; + } +} + +bool +TypeMap::Remove (const lldb::TypeSP &type_sp) +{ + if (type_sp) + { + lldb::user_id_t uid = type_sp->GetID(); + for (iterator pos = m_types.find(uid), end = m_types.end(); pos != end && pos->first == uid; ++pos) + { + if (pos->second == type_sp) + { + m_types.erase(pos); + return true; + } + } + } + return false; +} + +void +TypeMap::Dump(Stream *s, bool show_context) +{ + for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) + { + pos->second->Dump(s, show_context); + } +} + +void +TypeMap::RemoveMismatchedTypes (const char *qualified_typename, + bool exact_match) +{ + std::string type_scope; + std::string type_basename; + TypeClass type_class = eTypeClassAny; + if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class)) + { + type_basename = qualified_typename; + type_scope.clear(); + } + return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); +} + +void +TypeMap::RemoveMismatchedTypes (const std::string &type_scope, + const std::string &type_basename, + TypeClass type_class, + 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; + TypeClass match_type_class = eTypeClassAny; + + if (type_class != eTypeClassAny) + { + match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); + if ((match_type_class & type_class) == 0) + continue; + } + + 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, + match_type_class)) + { + 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 looking for, + // but we need to make sure what comes before the matching + // type scope is a namespace 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 +TypeMap::RemoveMismatchedTypes (TypeClass type_class) +{ + if (type_class == eTypeClassAny) + return; + + // 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(); + TypeClass match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); + if (match_type_class & type_class) + matching_types.insert (*pos); + } + m_types.swap(matching_types); +} |