#include <vector>
#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"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeList.h"
using namespace lldb;
using namespace lldb_private;
using namespace clang;
TypeList::TypeList() :
m_types ()
{
}
TypeList::~TypeList()
{
}
void
TypeList::Insert (const TypeSP& type_sp)
{
if (type_sp)
m_types.insert(std::make_pair(type_sp->GetID(), type_sp));
}
bool
TypeList::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;
}
void
TypeList::Clear()
{
m_types.clear();
}
uint32_t
TypeList::GetSize() const
{
return m_types.size();
}
TypeSP
TypeList::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();
}
bool
TypeList::RemoveTypeWithUID (user_id_t uid)
{
iterator pos = m_types.find(uid);
if (pos != m_types.end())
{
m_types.erase(pos);
return true;
}
return false;
}
void
TypeList::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);
}
}
static bool
GetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr)
{
if (name_cstr && name_cstr[0])
{
const char *basename_cstr = name_cstr;
const char* namespace_separator = ::strstr (basename_cstr, "::");
if (namespace_separator)
{
const char* template_arg_char = ::strchr (basename_cstr, '<');
while (namespace_separator != NULL)
{
if (template_arg_char && namespace_separator > template_arg_char) break;
basename_cstr = namespace_separator + 2;
namespace_separator = strstr(basename_cstr, "::");
}
if (basename_cstr > name_cstr)
{
scope.assign (name_cstr, basename_cstr - name_cstr);
if (scope.size() >= 2 && scope[0] == ':' && scope[1] == ':')
{
if (exact_ptr)
*exact_ptr = true;
scope.erase(0,2);
}
basename.assign (basename_cstr);
return true;
}
}
}
return false;
}
void
TypeList::RemoveMismatchedTypes (const char *qualified_typename,
bool exact_match)
{
std::string type_scope;
std::string type_basename;
TypeClass type_class = eTypeClassAny;
if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class))
{
type_basename = qualified_typename;
type_scope.clear();
}
return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match);
}
void
TypeList::RemoveMismatchedTypes (const std::string &type_scope,
const std::string &type_basename,
TypeClass type_class,
bool exact_match)
{
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 = ClangASTType::GetTypeClass (the_type->GetClangAST(),
the_type->GetClangForwardType());
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();
std::string match_type_scope;
std::string 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)
{
if (match_type_scope[type_scope_pos - 1] == ':' &&
match_type_scope[type_scope_pos - 2] == ':')
{
keep_match = true;
}
}
}
}
}
}
}
else
{
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
TypeList::RemoveMismatchedTypes (TypeClass type_class)
{
if (type_class == eTypeClassAny)
return;
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 = ClangASTType::GetTypeClass (the_type->GetClangAST(),
the_type->GetClangForwardType());
if (match_type_class & type_class)
matching_types.insert (*pos);
}
m_types.swap(matching_types);
}