| //===-- 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) { |
| llvm::StringRef type_scope; |
| llvm::StringRef type_basename; |
| TypeClass type_class = eTypeClassAny; |
| if (!Type::GetTypeScopeAndBasename(qualified_typename, type_scope, |
| type_basename, type_class)) { |
| type_basename = qualified_typename; |
| type_scope = ""; |
| } |
| 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(); |
| llvm::StringRef match_type_scope; |
| llvm::StringRef 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); |
| } |