TypeList.cpp revision 254721
1181344Sdfr//===-- TypeList.cpp --------------------------------------------*- C++ -*-===// 2181344Sdfr// 3181344Sdfr// The LLVM Compiler Infrastructure 4181344Sdfr// 5181344Sdfr// This file is distributed under the University of Illinois Open Source 6181344Sdfr// License. See LICENSE.TXT for details. 7181344Sdfr// 8181344Sdfr//===----------------------------------------------------------------------===// 9181344Sdfr 10181344Sdfr 11181344Sdfr// C Includes 12181344Sdfr// C++ Includes 13181344Sdfr#include <vector> 14181344Sdfr 15181344Sdfr// Other libraries and framework includes 16181344Sdfr#include "clang/AST/ASTConsumer.h" 17181344Sdfr#include "clang/AST/ASTContext.h" 18181344Sdfr#include "clang/AST/Decl.h" 19181344Sdfr#include "clang/AST/DeclCXX.h" 20181344Sdfr#include "clang/AST/DeclGroup.h" 21181344Sdfr 22181344Sdfr#include "clang/Basic/Builtins.h" 23181344Sdfr#include "clang/Basic/IdentifierTable.h" 24181344Sdfr#include "clang/Basic/LangOptions.h" 25181344Sdfr#include "clang/Basic/SourceManager.h" 26181344Sdfr#include "clang/Basic/TargetInfo.h" 27181344Sdfr 28181344Sdfr#include "llvm/Support/FormattedStream.h" 29181344Sdfr#include "llvm/Support/raw_ostream.h" 30181344Sdfr 31181344Sdfr// Project includes 32181344Sdfr#include "lldb/Symbol/SymbolFile.h" 33181344Sdfr#include "lldb/Symbol/SymbolVendor.h" 34181344Sdfr#include "lldb/Symbol/Type.h" 35181344Sdfr#include "lldb/Symbol/TypeList.h" 36181344Sdfr 37181344Sdfrusing namespace lldb; 38181344Sdfrusing namespace lldb_private; 39181344Sdfrusing namespace clang; 40181344Sdfr 41181344SdfrTypeList::TypeList() : 42181344Sdfr m_types () 43181344Sdfr{ 44181344Sdfr} 45181344Sdfr 46181344Sdfr//---------------------------------------------------------------------- 47181344Sdfr// Destructor 48181344Sdfr//---------------------------------------------------------------------- 49181344SdfrTypeList::~TypeList() 50181344Sdfr{ 51181344Sdfr} 52181344Sdfr 53181344Sdfrvoid 54181344SdfrTypeList::Insert (const TypeSP& type_sp) 55181344Sdfr{ 56181344Sdfr // Just push each type on the back for now. We will worry about uniquing later 57181344Sdfr if (type_sp) 58181344Sdfr m_types.insert(std::make_pair(type_sp->GetID(), type_sp)); 59181344Sdfr} 60181344Sdfr 61181344Sdfr 62181344Sdfrbool 63181344SdfrTypeList::InsertUnique (const TypeSP& type_sp) 64181344Sdfr{ 65181344Sdfr if (type_sp) 66181344Sdfr { 67181344Sdfr user_id_t type_uid = type_sp->GetID(); 68181344Sdfr iterator pos, end = m_types.end(); 69181344Sdfr 70181344Sdfr for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos) 71181344Sdfr { 72181344Sdfr if (pos->second.get() == type_sp.get()) 73181344Sdfr return false; 74181344Sdfr } 75181344Sdfr } 76181344Sdfr Insert (type_sp); 77181344Sdfr return true; 78181344Sdfr} 79181344Sdfr 80181344Sdfr//---------------------------------------------------------------------- 81181344Sdfr// Find a base type by its unique ID. 82181344Sdfr//---------------------------------------------------------------------- 83181344Sdfr//TypeSP 84181344Sdfr//TypeList::FindType(lldb::user_id_t uid) 85181344Sdfr//{ 86181344Sdfr// iterator pos = m_types.find(uid); 87181344Sdfr// if (pos != m_types.end()) 88181344Sdfr// return pos->second; 89181344Sdfr// return TypeSP(); 90181344Sdfr//} 91181344Sdfr 92181344Sdfr//---------------------------------------------------------------------- 93181344Sdfr// Find a type by name. 94181344Sdfr//---------------------------------------------------------------------- 95181344Sdfr//TypeList 96181344Sdfr//TypeList::FindTypes (const ConstString &name) 97181344Sdfr//{ 98181344Sdfr// // Do we ever need to make a lookup by name map? Here we are doing 99181344Sdfr// // a linear search which isn't going to be fast. 100181344Sdfr// TypeList types(m_ast.getTargetInfo()->getTriple().getTriple().c_str()); 101181344Sdfr// iterator pos, end; 102181344Sdfr// for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 103181344Sdfr// if (pos->second->GetName() == name) 104181344Sdfr// types.Insert (pos->second); 105181344Sdfr// return types; 106181344Sdfr//} 107181344Sdfr 108181344Sdfrvoid 109181344SdfrTypeList::Clear() 110181344Sdfr{ 111181344Sdfr m_types.clear(); 112181344Sdfr} 113181344Sdfr 114181344Sdfruint32_t 115181344SdfrTypeList::GetSize() const 116181344Sdfr{ 117181344Sdfr return m_types.size(); 118181344Sdfr} 119181344Sdfr 120181344Sdfr// GetTypeAtIndex isn't used a lot for large type lists, currently only for 121181344Sdfr// type lists that are returned for "image dump -t TYPENAME" commands and other 122181344Sdfr// simple symbol queries that grab the first result... 123181344Sdfr 124181344SdfrTypeSP 125181344SdfrTypeList::GetTypeAtIndex(uint32_t idx) 126181344Sdfr{ 127181344Sdfr iterator pos, end; 128181344Sdfr uint32_t i = idx; 129181344Sdfr for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 130181344Sdfr { 131181344Sdfr if (i == 0) 132181344Sdfr return pos->second; 133181344Sdfr --i; 134181344Sdfr } 135181344Sdfr return TypeSP(); 136181344Sdfr} 137181344Sdfr 138181344Sdfrvoid 139181344SdfrTypeList::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const 140181344Sdfr{ 141181344Sdfr for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 142181344Sdfr { 143181344Sdfr if (!callback(pos->second)) 144181344Sdfr break; 145181344Sdfr } 146181344Sdfr} 147181344Sdfr 148181344Sdfrvoid 149181344SdfrTypeList::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback) 150181344Sdfr{ 151181344Sdfr for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 152181344Sdfr { 153181344Sdfr if (!callback(pos->second)) 154181344Sdfr break; 155181344Sdfr } 156181344Sdfr} 157181344Sdfr 158181344Sdfr 159181344Sdfrbool 160181344SdfrTypeList::RemoveTypeWithUID (user_id_t uid) 161181344Sdfr{ 162181344Sdfr iterator pos = m_types.find(uid); 163181344Sdfr 164181344Sdfr if (pos != m_types.end()) 165181344Sdfr { 166181344Sdfr m_types.erase(pos); 167181344Sdfr return true; 168181344Sdfr } 169181344Sdfr return false; 170181344Sdfr} 171181344Sdfr 172181344Sdfr 173181344Sdfrvoid 174181344SdfrTypeList::Dump(Stream *s, bool show_context) 175181344Sdfr{ 176181344Sdfr for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 177181344Sdfr { 178181344Sdfr pos->second->Dump(s, show_context); 179181344Sdfr } 180181344Sdfr} 181181344Sdfr 182181344Sdfr// depending on implementation details, type lookup might fail because of 183181344Sdfr// embedded spurious namespace:: prefixes. this call strips them, paying 184181344Sdfr// attention to the fact that a type might have namespace'd type names as 185181344Sdfr// arguments to templates, and those must not be stripped off 186181344Sdfrstatic bool 187181344SdfrGetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr) 188181344Sdfr{ 189181344Sdfr // Protect against null c string. 190181344Sdfr 191181344Sdfr if (name_cstr && name_cstr[0]) 192181344Sdfr { 193181344Sdfr const char *basename_cstr = name_cstr; 194181344Sdfr const char* namespace_separator = ::strstr (basename_cstr, "::"); 195181344Sdfr if (namespace_separator) 196181344Sdfr { 197181344Sdfr const char* template_arg_char = ::strchr (basename_cstr, '<'); 198181344Sdfr while (namespace_separator != NULL) 199181344Sdfr { 200181344Sdfr if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go 201181344Sdfr break; 202181344Sdfr basename_cstr = namespace_separator + 2; 203181344Sdfr namespace_separator = strstr(basename_cstr, "::"); 204181344Sdfr } 205181344Sdfr if (basename_cstr > name_cstr) 206181344Sdfr { 207181344Sdfr scope.assign (name_cstr, basename_cstr - name_cstr); 208181344Sdfr if (scope.size() >= 2 && scope[0] == ':' && scope[1] == ':') 209181344Sdfr { 210181344Sdfr // The typename passed in started with "::" so make sure we only do exact matches 211181344Sdfr if (exact_ptr) 212181344Sdfr *exact_ptr = true; 213181344Sdfr // Strip the leading "::" as this won't ever show in qualified typenames we get 214181344Sdfr // from clang. 215181344Sdfr scope.erase(0,2); 216181344Sdfr } 217181344Sdfr basename.assign (basename_cstr); 218181344Sdfr return true; 219181344Sdfr } 220181344Sdfr } 221181344Sdfr } 222181344Sdfr return false; 223181344Sdfr} 224181344Sdfr 225181344Sdfrvoid 226181344SdfrTypeList::RemoveMismatchedTypes (const char *qualified_typename, 227181344Sdfr bool exact_match) 228181344Sdfr{ 229181344Sdfr std::string type_scope; 230181344Sdfr std::string type_basename; 231181344Sdfr TypeClass type_class = eTypeClassAny; 232181344Sdfr if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class)) 233181344Sdfr { 234181344Sdfr type_basename = qualified_typename; 235181344Sdfr type_scope.clear(); 236181344Sdfr } 237181344Sdfr return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); 238181344Sdfr} 239181344Sdfr 240181344Sdfrvoid 241181344SdfrTypeList::RemoveMismatchedTypes (const std::string &type_scope, 242181344Sdfr const std::string &type_basename, 243181344Sdfr TypeClass type_class, 244181344Sdfr bool exact_match) 245181344Sdfr{ 246181344Sdfr // Our "collection" type currently is a std::map which doesn't 247181344Sdfr // have any good way to iterate and remove items from the map 248181344Sdfr // so we currently just make a new list and add all of the matching 249181344Sdfr // types to it, and then swap it into m_types at the end 250181344Sdfr collection matching_types; 251181344Sdfr 252181344Sdfr iterator pos, end = m_types.end(); 253181344Sdfr 254181344Sdfr for (pos = m_types.begin(); pos != end; ++pos) 255181344Sdfr { 256181344Sdfr Type* the_type = pos->second.get(); 257181344Sdfr bool keep_match = false; 258181344Sdfr TypeClass match_type_class = eTypeClassAny; 259181344Sdfr 260181344Sdfr if (type_class != eTypeClassAny) 261181344Sdfr { 262181344Sdfr match_type_class = the_type->GetClangForwardType().GetTypeClass (); 263181344Sdfr if ((match_type_class & type_class) == 0) 264181344Sdfr continue; 265181344Sdfr } 266181344Sdfr 267181344Sdfr ConstString match_type_name_const_str (the_type->GetQualifiedName()); 268181344Sdfr if (match_type_name_const_str) 269181344Sdfr { 270181344Sdfr const char *match_type_name = match_type_name_const_str.GetCString(); 271181344Sdfr std::string match_type_scope; 272181344Sdfr std::string match_type_basename; 273181344Sdfr if (Type::GetTypeScopeAndBasename (match_type_name, 274181344Sdfr match_type_scope, 275181344Sdfr match_type_basename, 276181344Sdfr match_type_class)) 277181344Sdfr { 278181344Sdfr if (match_type_basename == type_basename) 279181344Sdfr { 280181344Sdfr const size_t type_scope_size = type_scope.size(); 281181344Sdfr const size_t match_type_scope_size = match_type_scope.size(); 282181344Sdfr if (exact_match || (type_scope_size == match_type_scope_size)) 283181344Sdfr { 284181344Sdfr keep_match = match_type_scope == type_scope; 285181344Sdfr } 286181344Sdfr else 287181344Sdfr { 288181344Sdfr if (match_type_scope_size > type_scope_size) 289181344Sdfr { 290181344Sdfr const size_t type_scope_pos = match_type_scope.rfind(type_scope); 291181344Sdfr if (type_scope_pos == match_type_scope_size - type_scope_size) 292181344Sdfr { 293181344Sdfr if (type_scope_pos >= 2) 294181344Sdfr { 295181344Sdfr // Our match scope ends with the type scope we were lookikng for, 296181344Sdfr // but we need to make sure what comes before the matching 297181344Sdfr // type scope is a namepace boundary in case we are trying to match: 298181344Sdfr // type_basename = "d" 299181344Sdfr // type_scope = "b::c::" 300181344Sdfr // We want to match: 301181344Sdfr // match_type_scope "a::b::c::" 302181344Sdfr // But not: 303181344Sdfr // match_type_scope "a::bb::c::" 304181344Sdfr // So below we make sure what comes before "b::c::" in match_type_scope 305181344Sdfr // is "::", or the namespace boundary 306181344Sdfr if (match_type_scope[type_scope_pos - 1] == ':' && 307181344Sdfr match_type_scope[type_scope_pos - 2] == ':') 308181344Sdfr { 309181344Sdfr keep_match = true; 310181344Sdfr } 311181344Sdfr } 312181344Sdfr } 313181344Sdfr } 314181344Sdfr } 315181344Sdfr } 316181344Sdfr } 317181344Sdfr else 318181344Sdfr { 319181344Sdfr // The type we are currently looking at doesn't exists 320181344Sdfr // in a namespace or class, so it only matches if there 321181344Sdfr // is no type scope... 322181344Sdfr keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0; 323181344Sdfr } 324181344Sdfr } 325181344Sdfr 326181344Sdfr if (keep_match) 327181344Sdfr { 328181344Sdfr matching_types.insert (*pos); 329181344Sdfr } 330181344Sdfr } 331181344Sdfr m_types.swap(matching_types); 332181344Sdfr} 333181344Sdfr 334181344Sdfrvoid 335181344SdfrTypeList::RemoveMismatchedTypes (TypeClass type_class) 336181344Sdfr{ 337181344Sdfr if (type_class == eTypeClassAny) 338181344Sdfr return; 339181344Sdfr 340181344Sdfr // Our "collection" type currently is a std::map which doesn't 341181344Sdfr // have any good way to iterate and remove items from the map 342181344Sdfr // so we currently just make a new list and add all of the matching 343181344Sdfr // types to it, and then swap it into m_types at the end 344181344Sdfr collection matching_types; 345181344Sdfr 346181344Sdfr iterator pos, end = m_types.end(); 347181344Sdfr 348181344Sdfr for (pos = m_types.begin(); pos != end; ++pos) 349181344Sdfr { 350181344Sdfr Type* the_type = pos->second.get(); 351181344Sdfr TypeClass match_type_class = the_type->GetClangForwardType().GetTypeClass (); 352181344Sdfr if (match_type_class & type_class) 353181344Sdfr matching_types.insert (*pos); 354181344Sdfr } 355181344Sdfr m_types.swap(matching_types); 356181344Sdfr} 357181344Sdfr