mirror of
https://github.com/opnsense/src.git
synced 2026-02-27 11:50:47 -05:00
322 lines
10 KiB
C++
322 lines
10 KiB
C++
//===-- TypeMap.cpp --------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
#include <vector>
|
|
|
|
// Other libraries and framework includes
|
|
#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"
|
|
|
|
// Project includes
|
|
#include "lldb/Symbol/SymbolFile.h"
|
|
#include "lldb/Symbol/SymbolVendor.h"
|
|
#include "lldb/Symbol/Type.h"
|
|
#include "lldb/Symbol/TypeMap.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace clang;
|
|
|
|
TypeMap::TypeMap() :
|
|
m_types ()
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Destructor
|
|
//----------------------------------------------------------------------
|
|
TypeMap::~TypeMap()
|
|
{
|
|
}
|
|
|
|
void
|
|
TypeMap::Insert (const TypeSP& type_sp)
|
|
{
|
|
// Just push each type on the back for now. We will worry about uniquing later
|
|
if (type_sp)
|
|
m_types.insert(std::make_pair(type_sp->GetID(), type_sp));
|
|
}
|
|
|
|
|
|
bool
|
|
TypeMap::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;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Find a base type by its unique ID.
|
|
//----------------------------------------------------------------------
|
|
//TypeSP
|
|
//TypeMap::FindType(lldb::user_id_t uid)
|
|
//{
|
|
// iterator pos = m_types.find(uid);
|
|
// if (pos != m_types.end())
|
|
// return pos->second;
|
|
// return TypeSP();
|
|
//}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Find a type by name.
|
|
//----------------------------------------------------------------------
|
|
//TypeMap
|
|
//TypeMap::FindTypes (const ConstString &name)
|
|
//{
|
|
// // Do we ever need to make a lookup by name map? Here we are doing
|
|
// // a linear search which isn't going to be fast.
|
|
// TypeMap types(m_ast.getTargetInfo()->getTriple().getTriple().c_str());
|
|
// iterator pos, end;
|
|
// for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
|
|
// if (pos->second->GetName() == name)
|
|
// types.Insert (pos->second);
|
|
// return types;
|
|
//}
|
|
|
|
void
|
|
TypeMap::Clear()
|
|
{
|
|
m_types.clear();
|
|
}
|
|
|
|
uint32_t
|
|
TypeMap::GetSize() const
|
|
{
|
|
return m_types.size();
|
|
}
|
|
|
|
bool
|
|
TypeMap::Empty() const
|
|
{
|
|
return m_types.empty();
|
|
}
|
|
|
|
// GetTypeAtIndex isn't used a lot for large type lists, currently only for
|
|
// type lists that are returned for "image dump -t TYPENAME" commands and other
|
|
// simple symbol queries that grab the first result...
|
|
|
|
TypeSP
|
|
TypeMap::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();
|
|
}
|
|
|
|
void
|
|
TypeMap::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const
|
|
{
|
|
for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
|
|
{
|
|
if (!callback(pos->second))
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
TypeMap::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback)
|
|
{
|
|
for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
|
|
{
|
|
if (!callback(pos->second))
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool
|
|
TypeMap::Remove (const lldb::TypeSP &type_sp)
|
|
{
|
|
if (type_sp)
|
|
{
|
|
lldb::user_id_t uid = type_sp->GetID();
|
|
for (iterator pos = m_types.find(uid), end = m_types.end(); pos != end && pos->first == uid; ++pos)
|
|
{
|
|
if (pos->second == type_sp)
|
|
{
|
|
m_types.erase(pos);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
TypeMap::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);
|
|
}
|
|
}
|
|
|
|
void
|
|
TypeMap::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
|
|
TypeMap::RemoveMismatchedTypes (const std::string &type_scope,
|
|
const std::string &type_basename,
|
|
TypeClass type_class,
|
|
bool exact_match)
|
|
{
|
|
// Our "collection" type currently is a std::map which doesn't
|
|
// have any good way to iterate and remove items from the map
|
|
// so we currently just make a new list and add all of the matching
|
|
// types to it, and then swap it into m_types at the end
|
|
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 = the_type->GetForwardCompilerType ().GetTypeClass ();
|
|
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)
|
|
{
|
|
// Our match scope ends with the type scope we were looking for,
|
|
// but we need to make sure what comes before the matching
|
|
// type scope is a namespace boundary in case we are trying to match:
|
|
// type_basename = "d"
|
|
// type_scope = "b::c::"
|
|
// We want to match:
|
|
// match_type_scope "a::b::c::"
|
|
// But not:
|
|
// match_type_scope "a::bb::c::"
|
|
// So below we make sure what comes before "b::c::" in match_type_scope
|
|
// is "::", or the namespace boundary
|
|
if (match_type_scope[type_scope_pos - 1] == ':' &&
|
|
match_type_scope[type_scope_pos - 2] == ':')
|
|
{
|
|
keep_match = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The type we are currently looking at doesn't exists
|
|
// in a namespace or class, so it only matches if there
|
|
// is no type scope...
|
|
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
|
|
TypeMap::RemoveMismatchedTypes (TypeClass type_class)
|
|
{
|
|
if (type_class == eTypeClassAny)
|
|
return;
|
|
|
|
// Our "collection" type currently is a std::map which doesn't
|
|
// have any good way to iterate and remove items from the map
|
|
// so we currently just make a new list and add all of the matching
|
|
// types to it, and then swap it into m_types at the end
|
|
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 = the_type->GetForwardCompilerType ().GetTypeClass ();
|
|
if (match_type_class & type_class)
|
|
matching_types.insert (*pos);
|
|
}
|
|
m_types.swap(matching_types);
|
|
}
|