1 //===-- TypeMap.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 11 // C Includes 12 // C++ Includes 13 #include <vector> 14 15 // Other libraries and framework includes 16 #include "clang/AST/ASTConsumer.h" 17 #include "clang/AST/ASTContext.h" 18 #include "clang/AST/Decl.h" 19 #include "clang/AST/DeclCXX.h" 20 #include "clang/AST/DeclGroup.h" 21 22 #include "clang/Basic/Builtins.h" 23 #include "clang/Basic/IdentifierTable.h" 24 #include "clang/Basic/LangOptions.h" 25 #include "clang/Basic/SourceManager.h" 26 #include "clang/Basic/TargetInfo.h" 27 28 #include "llvm/Support/FormattedStream.h" 29 #include "llvm/Support/raw_ostream.h" 30 31 // Project includes 32 #include "lldb/Symbol/SymbolFile.h" 33 #include "lldb/Symbol/SymbolVendor.h" 34 #include "lldb/Symbol/Type.h" 35 #include "lldb/Symbol/TypeMap.h" 36 37 using namespace lldb; 38 using namespace lldb_private; 39 using namespace clang; 40 41 TypeMap::TypeMap() : 42 m_types () 43 { 44 } 45 46 //---------------------------------------------------------------------- 47 // Destructor 48 //---------------------------------------------------------------------- 49 TypeMap::~TypeMap() 50 { 51 } 52 53 void 54 TypeMap::Insert (const TypeSP& type_sp) 55 { 56 // Just push each type on the back for now. We will worry about uniquing later 57 if (type_sp) 58 m_types.insert(std::make_pair(type_sp->GetID(), type_sp)); 59 } 60 61 62 bool 63 TypeMap::InsertUnique (const TypeSP& type_sp) 64 { 65 if (type_sp) 66 { 67 user_id_t type_uid = type_sp->GetID(); 68 iterator pos, end = m_types.end(); 69 70 for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos) 71 { 72 if (pos->second.get() == type_sp.get()) 73 return false; 74 } 75 Insert (type_sp); 76 } 77 return true; 78 } 79 80 //---------------------------------------------------------------------- 81 // Find a base type by its unique ID. 82 //---------------------------------------------------------------------- 83 //TypeSP 84 //TypeMap::FindType(lldb::user_id_t uid) 85 //{ 86 // iterator pos = m_types.find(uid); 87 // if (pos != m_types.end()) 88 // return pos->second; 89 // return TypeSP(); 90 //} 91 92 //---------------------------------------------------------------------- 93 // Find a type by name. 94 //---------------------------------------------------------------------- 95 //TypeMap 96 //TypeMap::FindTypes (const ConstString &name) 97 //{ 98 // // Do we ever need to make a lookup by name map? Here we are doing 99 // // a linear search which isn't going to be fast. 100 // TypeMap types(m_ast.getTargetInfo()->getTriple().getTriple().c_str()); 101 // iterator pos, end; 102 // for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 103 // if (pos->second->GetName() == name) 104 // types.Insert (pos->second); 105 // return types; 106 //} 107 108 void 109 TypeMap::Clear() 110 { 111 m_types.clear(); 112 } 113 114 uint32_t 115 TypeMap::GetSize() const 116 { 117 return m_types.size(); 118 } 119 120 bool 121 TypeMap::Empty() const 122 { 123 return m_types.empty(); 124 } 125 126 // GetTypeAtIndex isn't used a lot for large type lists, currently only for 127 // type lists that are returned for "image dump -t TYPENAME" commands and other 128 // simple symbol queries that grab the first result... 129 130 TypeSP 131 TypeMap::GetTypeAtIndex(uint32_t idx) 132 { 133 iterator pos, end; 134 uint32_t i = idx; 135 for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 136 { 137 if (i == 0) 138 return pos->second; 139 --i; 140 } 141 return TypeSP(); 142 } 143 144 void 145 TypeMap::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const 146 { 147 for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 148 { 149 if (!callback(pos->second)) 150 break; 151 } 152 } 153 154 void 155 TypeMap::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback) 156 { 157 for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 158 { 159 if (!callback(pos->second)) 160 break; 161 } 162 } 163 164 bool 165 TypeMap::Remove (const lldb::TypeSP &type_sp) 166 { 167 if (type_sp) 168 { 169 lldb::user_id_t uid = type_sp->GetID(); 170 for (iterator pos = m_types.find(uid), end = m_types.end(); pos != end && pos->first == uid; ++pos) 171 { 172 if (pos->second == type_sp) 173 { 174 m_types.erase(pos); 175 return true; 176 } 177 } 178 } 179 return false; 180 } 181 182 void 183 TypeMap::Dump(Stream *s, bool show_context) 184 { 185 for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 186 { 187 pos->second->Dump(s, show_context); 188 } 189 } 190 191 void 192 TypeMap::RemoveMismatchedTypes (const char *qualified_typename, 193 bool exact_match) 194 { 195 std::string type_scope; 196 std::string type_basename; 197 TypeClass type_class = eTypeClassAny; 198 if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class)) 199 { 200 type_basename = qualified_typename; 201 type_scope.clear(); 202 } 203 return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); 204 } 205 206 void 207 TypeMap::RemoveMismatchedTypes (const std::string &type_scope, 208 const std::string &type_basename, 209 TypeClass type_class, 210 bool exact_match) 211 { 212 // Our "collection" type currently is a std::map which doesn't 213 // have any good way to iterate and remove items from the map 214 // so we currently just make a new list and add all of the matching 215 // types to it, and then swap it into m_types at the end 216 collection matching_types; 217 218 iterator pos, end = m_types.end(); 219 220 for (pos = m_types.begin(); pos != end; ++pos) 221 { 222 Type* the_type = pos->second.get(); 223 bool keep_match = false; 224 TypeClass match_type_class = eTypeClassAny; 225 226 if (type_class != eTypeClassAny) 227 { 228 match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); 229 if ((match_type_class & type_class) == 0) 230 continue; 231 } 232 233 ConstString match_type_name_const_str (the_type->GetQualifiedName()); 234 if (match_type_name_const_str) 235 { 236 const char *match_type_name = match_type_name_const_str.GetCString(); 237 std::string match_type_scope; 238 std::string match_type_basename; 239 if (Type::GetTypeScopeAndBasename (match_type_name, 240 match_type_scope, 241 match_type_basename, 242 match_type_class)) 243 { 244 if (match_type_basename == type_basename) 245 { 246 const size_t type_scope_size = type_scope.size(); 247 const size_t match_type_scope_size = match_type_scope.size(); 248 if (exact_match || (type_scope_size == match_type_scope_size)) 249 { 250 keep_match = match_type_scope == type_scope; 251 } 252 else 253 { 254 if (match_type_scope_size > type_scope_size) 255 { 256 const size_t type_scope_pos = match_type_scope.rfind(type_scope); 257 if (type_scope_pos == match_type_scope_size - type_scope_size) 258 { 259 if (type_scope_pos >= 2) 260 { 261 // Our match scope ends with the type scope we were looking for, 262 // but we need to make sure what comes before the matching 263 // type scope is a namespace boundary in case we are trying to match: 264 // type_basename = "d" 265 // type_scope = "b::c::" 266 // We want to match: 267 // match_type_scope "a::b::c::" 268 // But not: 269 // match_type_scope "a::bb::c::" 270 // So below we make sure what comes before "b::c::" in match_type_scope 271 // is "::", or the namespace boundary 272 if (match_type_scope[type_scope_pos - 1] == ':' && 273 match_type_scope[type_scope_pos - 2] == ':') 274 { 275 keep_match = true; 276 } 277 } 278 } 279 } 280 } 281 } 282 } 283 else 284 { 285 // The type we are currently looking at doesn't exists 286 // in a namespace or class, so it only matches if there 287 // is no type scope... 288 keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0; 289 } 290 } 291 292 if (keep_match) 293 { 294 matching_types.insert (*pos); 295 } 296 } 297 m_types.swap(matching_types); 298 } 299 300 void 301 TypeMap::RemoveMismatchedTypes (TypeClass type_class) 302 { 303 if (type_class == eTypeClassAny) 304 return; 305 306 // Our "collection" type currently is a std::map which doesn't 307 // have any good way to iterate and remove items from the map 308 // so we currently just make a new list and add all of the matching 309 // types to it, and then swap it into m_types at the end 310 collection matching_types; 311 312 iterator pos, end = m_types.end(); 313 314 for (pos = m_types.begin(); pos != end; ++pos) 315 { 316 Type* the_type = pos->second.get(); 317 TypeClass match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); 318 if (match_type_class & type_class) 319 matching_types.insert (*pos); 320 } 321 m_types.swap(matching_types); 322 } 323