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 } 76 Insert (type_sp); 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 165 bool 166 TypeMap::RemoveTypeWithUID (user_id_t uid) 167 { 168 iterator pos = m_types.find(uid); 169 170 if (pos != m_types.end()) 171 { 172 m_types.erase(pos); 173 return true; 174 } 175 return false; 176 } 177 178 179 void 180 TypeMap::Dump(Stream *s, bool show_context) 181 { 182 for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 183 { 184 pos->second->Dump(s, show_context); 185 } 186 } 187 188 void 189 TypeMap::RemoveMismatchedTypes (const char *qualified_typename, 190 bool exact_match) 191 { 192 std::string type_scope; 193 std::string type_basename; 194 TypeClass type_class = eTypeClassAny; 195 if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class)) 196 { 197 type_basename = qualified_typename; 198 type_scope.clear(); 199 } 200 return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); 201 } 202 203 void 204 TypeMap::RemoveMismatchedTypes (const std::string &type_scope, 205 const std::string &type_basename, 206 TypeClass type_class, 207 bool exact_match) 208 { 209 // Our "collection" type currently is a std::map which doesn't 210 // have any good way to iterate and remove items from the map 211 // so we currently just make a new list and add all of the matching 212 // types to it, and then swap it into m_types at the end 213 collection matching_types; 214 215 iterator pos, end = m_types.end(); 216 217 for (pos = m_types.begin(); pos != end; ++pos) 218 { 219 Type* the_type = pos->second.get(); 220 bool keep_match = false; 221 TypeClass match_type_class = eTypeClassAny; 222 223 if (type_class != eTypeClassAny) 224 { 225 match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); 226 if ((match_type_class & type_class) == 0) 227 continue; 228 } 229 230 ConstString match_type_name_const_str (the_type->GetQualifiedName()); 231 if (match_type_name_const_str) 232 { 233 const char *match_type_name = match_type_name_const_str.GetCString(); 234 std::string match_type_scope; 235 std::string match_type_basename; 236 if (Type::GetTypeScopeAndBasename (match_type_name, 237 match_type_scope, 238 match_type_basename, 239 match_type_class)) 240 { 241 if (match_type_basename == type_basename) 242 { 243 const size_t type_scope_size = type_scope.size(); 244 const size_t match_type_scope_size = match_type_scope.size(); 245 if (exact_match || (type_scope_size == match_type_scope_size)) 246 { 247 keep_match = match_type_scope == type_scope; 248 } 249 else 250 { 251 if (match_type_scope_size > type_scope_size) 252 { 253 const size_t type_scope_pos = match_type_scope.rfind(type_scope); 254 if (type_scope_pos == match_type_scope_size - type_scope_size) 255 { 256 if (type_scope_pos >= 2) 257 { 258 // Our match scope ends with the type scope we were looking for, 259 // but we need to make sure what comes before the matching 260 // type scope is a namespace boundary in case we are trying to match: 261 // type_basename = "d" 262 // type_scope = "b::c::" 263 // We want to match: 264 // match_type_scope "a::b::c::" 265 // But not: 266 // match_type_scope "a::bb::c::" 267 // So below we make sure what comes before "b::c::" in match_type_scope 268 // is "::", or the namespace boundary 269 if (match_type_scope[type_scope_pos - 1] == ':' && 270 match_type_scope[type_scope_pos - 2] == ':') 271 { 272 keep_match = true; 273 } 274 } 275 } 276 } 277 } 278 } 279 } 280 else 281 { 282 // The type we are currently looking at doesn't exists 283 // in a namespace or class, so it only matches if there 284 // is no type scope... 285 keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0; 286 } 287 } 288 289 if (keep_match) 290 { 291 matching_types.insert (*pos); 292 } 293 } 294 m_types.swap(matching_types); 295 } 296 297 void 298 TypeMap::RemoveMismatchedTypes (TypeClass type_class) 299 { 300 if (type_class == eTypeClassAny) 301 return; 302 303 // Our "collection" type currently is a std::map which doesn't 304 // have any good way to iterate and remove items from the map 305 // so we currently just make a new list and add all of the matching 306 // types to it, and then swap it into m_types at the end 307 collection matching_types; 308 309 iterator pos, end = m_types.end(); 310 311 for (pos = m_types.begin(); pos != end; ++pos) 312 { 313 Type* the_type = pos->second.get(); 314 TypeClass match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); 315 if (match_type_class & type_class) 316 matching_types.insert (*pos); 317 } 318 m_types.swap(matching_types); 319 } 320