TypeList.cpp revision 341825
1//===-- TypeList.cpp --------------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10// C Includes 11// C++ Includes 12#include <vector> 13 14// Other libraries and framework includes 15#include "llvm/Support/FormattedStream.h" 16#include "llvm/Support/raw_ostream.h" 17 18// Project includes 19#include "lldb/Symbol/SymbolFile.h" 20#include "lldb/Symbol/SymbolVendor.h" 21#include "lldb/Symbol/Type.h" 22#include "lldb/Symbol/TypeList.h" 23 24using namespace lldb; 25using namespace lldb_private; 26 27TypeList::TypeList() : m_types() {} 28 29//---------------------------------------------------------------------- 30// Destructor 31//---------------------------------------------------------------------- 32TypeList::~TypeList() {} 33 34void TypeList::Insert(const TypeSP &type_sp) { 35 // Just push each type on the back for now. We will worry about uniquing 36 // later 37 if (type_sp) 38 m_types.push_back(type_sp); 39} 40 41//---------------------------------------------------------------------- 42// Find a base type by its unique ID. 43//---------------------------------------------------------------------- 44// TypeSP 45// TypeList::FindType(lldb::user_id_t uid) 46//{ 47// iterator pos = m_types.find(uid); 48// if (pos != m_types.end()) 49// return pos->second; 50// return TypeSP(); 51//} 52 53//---------------------------------------------------------------------- 54// Find a type by name. 55//---------------------------------------------------------------------- 56// TypeList 57// TypeList::FindTypes (const ConstString &name) 58//{ 59// // Do we ever need to make a lookup by name map? Here we are doing 60// // a linear search which isn't going to be fast. 61// TypeList types(m_ast.getTargetInfo()->getTriple().getTriple().c_str()); 62// iterator pos, end; 63// for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 64// if (pos->second->GetName() == name) 65// types.Insert (pos->second); 66// return types; 67//} 68 69void TypeList::Clear() { m_types.clear(); } 70 71uint32_t TypeList::GetSize() const { return m_types.size(); } 72 73// GetTypeAtIndex isn't used a lot for large type lists, currently only for 74// type lists that are returned for "image dump -t TYPENAME" commands and other 75// simple symbol queries that grab the first result... 76 77TypeSP TypeList::GetTypeAtIndex(uint32_t idx) { 78 iterator pos, end; 79 uint32_t i = idx; 80 assert(i < GetSize() && "Accessing past the end of a TypeList"); 81 for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 82 if (i == 0) 83 return *pos; 84 --i; 85 } 86 return TypeSP(); 87} 88 89void TypeList::ForEach( 90 std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const { 91 for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 92 if (!callback(*pos)) 93 break; 94 } 95} 96 97void TypeList::ForEach( 98 std::function<bool(lldb::TypeSP &type_sp)> const &callback) { 99 for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 100 if (!callback(*pos)) 101 break; 102 } 103} 104 105void TypeList::Dump(Stream *s, bool show_context) { 106 for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 107 pos->get()->Dump(s, show_context); 108 } 109} 110 111void TypeList::RemoveMismatchedTypes(const char *qualified_typename, 112 bool exact_match) { 113 llvm::StringRef type_scope; 114 llvm::StringRef type_basename; 115 TypeClass type_class = eTypeClassAny; 116 if (!Type::GetTypeScopeAndBasename(qualified_typename, type_scope, 117 type_basename, type_class)) { 118 type_basename = qualified_typename; 119 type_scope = ""; 120 } 121 return RemoveMismatchedTypes(type_scope, type_basename, type_class, 122 exact_match); 123} 124 125void TypeList::RemoveMismatchedTypes(const std::string &type_scope, 126 const std::string &type_basename, 127 TypeClass type_class, bool exact_match) { 128 // Our "collection" type currently is a std::map which doesn't have any good 129 // way to iterate and remove items from the map so we currently just make a 130 // new list and add all of the matching types to it, and then swap it into 131 // m_types at the end 132 collection matching_types; 133 134 iterator pos, end = m_types.end(); 135 136 for (pos = m_types.begin(); pos != end; ++pos) { 137 Type *the_type = pos->get(); 138 bool keep_match = false; 139 TypeClass match_type_class = eTypeClassAny; 140 141 if (type_class != eTypeClassAny) { 142 match_type_class = the_type->GetForwardCompilerType().GetTypeClass(); 143 if ((match_type_class & type_class) == 0) 144 continue; 145 } 146 147 ConstString match_type_name_const_str(the_type->GetQualifiedName()); 148 if (match_type_name_const_str) { 149 const char *match_type_name = match_type_name_const_str.GetCString(); 150 llvm::StringRef match_type_scope; 151 llvm::StringRef match_type_basename; 152 if (Type::GetTypeScopeAndBasename(match_type_name, match_type_scope, 153 match_type_basename, 154 match_type_class)) { 155 if (match_type_basename == type_basename) { 156 const size_t type_scope_size = type_scope.size(); 157 const size_t match_type_scope_size = match_type_scope.size(); 158 if (exact_match || (type_scope_size == match_type_scope_size)) { 159 keep_match = match_type_scope == type_scope; 160 } else { 161 if (match_type_scope_size > type_scope_size) { 162 const size_t type_scope_pos = match_type_scope.rfind(type_scope); 163 if (type_scope_pos == match_type_scope_size - type_scope_size) { 164 if (type_scope_pos >= 2) { 165 // Our match scope ends with the type scope we were looking 166 // for, but we need to make sure what comes before the 167 // matching type scope is a namespace boundary in case we are 168 // trying to match: type_basename = "d" type_scope = "b::c::" 169 // We want to match: 170 // match_type_scope "a::b::c::" 171 // But not: 172 // match_type_scope "a::bb::c::" 173 // So below we make sure what comes before "b::c::" in 174 // match_type_scope is "::", or the namespace boundary 175 if (match_type_scope[type_scope_pos - 1] == ':' && 176 match_type_scope[type_scope_pos - 2] == ':') { 177 keep_match = true; 178 } 179 } 180 } 181 } 182 } 183 } 184 } else { 185 // The type we are currently looking at doesn't exists in a namespace 186 // or class, so it only matches if there is no type scope... 187 keep_match = 188 type_scope.empty() && type_basename.compare(match_type_name) == 0; 189 } 190 } 191 192 if (keep_match) { 193 matching_types.push_back(*pos); 194 } 195 } 196 m_types.swap(matching_types); 197} 198 199void TypeList::RemoveMismatchedTypes(TypeClass type_class) { 200 if (type_class == eTypeClassAny) 201 return; 202 203 // Our "collection" type currently is a std::map which doesn't have any good 204 // way to iterate and remove items from the map so we currently just make a 205 // new list and add all of the matching types to it, and then swap it into 206 // m_types at the end 207 collection matching_types; 208 209 iterator pos, end = m_types.end(); 210 211 for (pos = m_types.begin(); pos != end; ++pos) { 212 Type *the_type = pos->get(); 213 TypeClass match_type_class = 214 the_type->GetForwardCompilerType().GetTypeClass(); 215 if (match_type_class & type_class) 216 matching_types.push_back(*pos); 217 } 218 m_types.swap(matching_types); 219} 220