forked from OSchip/llvm-project
<rdar://problem/11113279>
Fixed type lookups to "do the right thing". Prior to this fix, looking up a type using "foo::bar" would result in a type list that contains all types that had "bar" as a basename unless the symbol file was able to match fully qualified names (which our DWARF parser does not). This fix will allow type matches to be made based on the basename and then have the types that don't match filtered out. Types by name can be fully qualified, or partially qualified with the new "bool exact_match" parameter to the Module::FindTypes() method. This fixes some issue that we discovered with dynamic type resolution as well as improves the overall type lookups in LLDB. llvm-svn: 153482
This commit is contained in:
parent
98e5d863ad
commit
84db9105d2
|
@ -519,11 +519,11 @@ protected:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Get(ValueObject& valobj,
|
||||
clang::QualType type,
|
||||
MapValueType& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t& reason)
|
||||
bool Get (ValueObject& valobj,
|
||||
clang::QualType type, // TODO: find out why "type" is passed in the type when it belongs to valobj? Can it ever differ?
|
||||
MapValueType& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t& reason)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
if (type.isNull())
|
||||
|
@ -541,7 +541,7 @@ protected:
|
|||
log->Printf("type is NULL, returning");
|
||||
return false;
|
||||
}
|
||||
ConstString typeName(ClangASTType::GetTypeNameForQualType(type).c_str());
|
||||
ConstString typeName(ClangASTType::GetTypeNameForQualType(valobj.GetClangAST(), type).c_str());
|
||||
|
||||
if (valobj.GetBitfieldBitSize() > 0)
|
||||
{
|
||||
|
|
|
@ -620,32 +620,37 @@ public:
|
|||
//------------------------------------------------------------------
|
||||
/// Find types by name.
|
||||
///
|
||||
/// Type lookups in modules go through the SymbolVendor (which will
|
||||
/// use one or more SymbolFile subclasses). The SymbolFile needs to
|
||||
/// be able to lookup types by basename and not the fully qualified
|
||||
/// typename. This allows the type accelerator tables to stay small,
|
||||
/// even with heavily templatized C++. The type search will then
|
||||
/// narrow down the search results. If "exact_match" is true, then
|
||||
/// the type search will only match exact type name matches. If
|
||||
/// "exact_match" is false, the type will match as long as the base
|
||||
/// typename matches and as long as any immediate containing
|
||||
/// namespaces/class scopes that are specified match. So to search
|
||||
/// for a type "d" in "b::c", the name "b::c::d" can be specified
|
||||
/// and it will match any class/namespace "b" which contains a
|
||||
/// class/namespace "c" which contains type "d". We do this to
|
||||
/// allow users to not always have to specify complete scoping on
|
||||
/// all expressions, but it also allows for exact matching when
|
||||
/// required.
|
||||
///
|
||||
/// @param[in] sc
|
||||
/// A symbol context that scopes where to extract a type list
|
||||
/// from.
|
||||
///
|
||||
/// @param[in] name
|
||||
/// The name of the type we are looking for.
|
||||
/// @param[in] type_name
|
||||
/// The name of the type we are looking for that is a fully
|
||||
/// or partially qualfieid type name.
|
||||
///
|
||||
/// @param[in] namespace_decl
|
||||
/// If valid, a namespace to search in.
|
||||
///
|
||||
/// @param[in] append
|
||||
/// If \b true, any matches will be appended to \a
|
||||
/// variable_list, else matches replace the contents of
|
||||
/// \a variable_list.
|
||||
///
|
||||
/// @param[in] max_matches
|
||||
/// Allow the number of matches to be limited to \a
|
||||
/// max_matches. Specify UINT32_MAX to get all possible matches.
|
||||
///
|
||||
/// @param[in] encoding
|
||||
/// Limit the search to specific types, or get all types if
|
||||
/// set to Type::invalid.
|
||||
///
|
||||
/// @param[in] udt_name
|
||||
/// If the encoding is a user defined type, specify the name
|
||||
/// of the user defined type ("struct", "union", "class", etc).
|
||||
/// @param[in] exact_match
|
||||
/// If \b true, \a type_name is fully qualifed and must match
|
||||
/// exactly. If \b false, \a type_name is a partially qualfied
|
||||
/// name where the leading namespaces or classes can be
|
||||
/// omitted to make finding types that a user may type
|
||||
/// easier.
|
||||
///
|
||||
/// @param[out] type_list
|
||||
/// A type list gets populated with any matches.
|
||||
|
@ -655,12 +660,40 @@ public:
|
|||
//------------------------------------------------------------------
|
||||
uint32_t
|
||||
FindTypes (const SymbolContext& sc,
|
||||
const ConstString &name,
|
||||
const ClangNamespaceDecl *namespace_decl,
|
||||
bool append,
|
||||
uint32_t max_matches,
|
||||
const ConstString &type_name,
|
||||
bool exact_match,
|
||||
uint32_t max_matches,
|
||||
TypeList& types);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Find types by name that are in a namespace. This function is
|
||||
/// used by the expression parser when searches need to happen in
|
||||
/// an exact namespace scope.
|
||||
///
|
||||
/// @param[in] sc
|
||||
/// A symbol context that scopes where to extract a type list
|
||||
/// from.
|
||||
///
|
||||
/// @param[in] type_name
|
||||
/// The name of a type within a namespace that should not include
|
||||
/// any qualifying namespaces (just a type basename).
|
||||
///
|
||||
/// @param[in] namespace_decl
|
||||
/// The namespace declaration that this type must exist in.
|
||||
///
|
||||
/// @param[out] type_list
|
||||
/// A type list gets populated with any matches.
|
||||
///
|
||||
/// @return
|
||||
/// The number of matches added to \a type_list.
|
||||
//------------------------------------------------------------------
|
||||
uint32_t
|
||||
FindTypesInNamespace (const SymbolContext& sc,
|
||||
const ConstString &type_name,
|
||||
const ClangNamespaceDecl *namespace_decl,
|
||||
uint32_t max_matches,
|
||||
TypeList& type_list);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get const accessor for the module architecture.
|
||||
///
|
||||
|
|
|
@ -340,10 +340,10 @@ public:
|
|||
/// The number of matches added to \a type_list.
|
||||
//------------------------------------------------------------------
|
||||
uint32_t
|
||||
FindTypes (const SymbolContext& sc,
|
||||
const ConstString &name,
|
||||
bool append,
|
||||
uint32_t max_matches,
|
||||
FindTypes2 (const SymbolContext& sc,
|
||||
const ConstString &name,
|
||||
bool name_is_fully_qualified,
|
||||
uint32_t max_matches,
|
||||
TypeList& types);
|
||||
|
||||
bool
|
||||
|
|
|
@ -566,12 +566,15 @@ public:
|
|||
virtual lldb::ValueType
|
||||
GetValueType() const = 0;
|
||||
|
||||
virtual ConstString
|
||||
GetTypeName() = 0;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Sublasses can implement the functions below.
|
||||
//------------------------------------------------------------------
|
||||
virtual ConstString
|
||||
GetTypeName();
|
||||
|
||||
virtual ConstString
|
||||
GetQualifiedTypeName();
|
||||
|
||||
virtual lldb::LanguageType
|
||||
GetObjectRuntimeLanguage();
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@ public:
|
|||
virtual ConstString
|
||||
GetTypeName();
|
||||
|
||||
virtual ConstString
|
||||
GetQualifiedTypeName();
|
||||
|
||||
virtual bool
|
||||
IsInScope ();
|
||||
|
||||
|
|
|
@ -33,9 +33,6 @@ namespace lldb_private {
|
|||
virtual size_t
|
||||
GetByteSize();
|
||||
|
||||
virtual ConstString
|
||||
GetTypeName();
|
||||
|
||||
virtual uint32_t
|
||||
CalculateNumChildren();
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ public:
|
|||
virtual ConstString
|
||||
GetTypeName();
|
||||
|
||||
virtual ConstString
|
||||
GetQualifiedTypeName();
|
||||
|
||||
virtual uint32_t
|
||||
CalculateNumChildren();
|
||||
|
||||
|
|
|
@ -78,15 +78,25 @@ public:
|
|||
|
||||
ConstString
|
||||
GetConstTypeName ();
|
||||
|
||||
ConstString
|
||||
GetConstQualifiedTypeName ();
|
||||
|
||||
static ConstString
|
||||
GetConstTypeName (lldb::clang_type_t clang_type);
|
||||
GetConstTypeName (clang::ASTContext *ast,
|
||||
lldb::clang_type_t clang_type);
|
||||
|
||||
static std::string
|
||||
GetTypeNameForQualType (clang::QualType qual_type);
|
||||
static ConstString
|
||||
GetConstQualifiedTypeName (clang::ASTContext *ast,
|
||||
lldb::clang_type_t clang_type);
|
||||
|
||||
static std::string
|
||||
GetTypeNameForOpaqueQualType (lldb::clang_type_t opaque_qual_type);
|
||||
GetTypeNameForQualType (clang::ASTContext *ast,
|
||||
clang::QualType qual_type);
|
||||
|
||||
static std::string
|
||||
GetTypeNameForOpaqueQualType (clang::ASTContext *ast,
|
||||
lldb::clang_type_t opaque_qual_type);
|
||||
|
||||
uint32_t
|
||||
GetClangTypeBitWidth ();
|
||||
|
|
|
@ -147,6 +147,9 @@ public:
|
|||
return m_name;
|
||||
}
|
||||
|
||||
ConstString
|
||||
GetQualifiedName ();
|
||||
|
||||
void
|
||||
DumpValue(ExecutionContext *exe_ctx,
|
||||
Stream *s,
|
||||
|
@ -240,6 +243,12 @@ public:
|
|||
static int
|
||||
Compare(const Type &a, const Type &b);
|
||||
|
||||
// From a fully qualified typename, split the type into the type basename
|
||||
// and the remaining type scope (namespaces/classes).
|
||||
static bool
|
||||
GetTypeScopeAndBasename (const char* name_cstr,
|
||||
std::string &scope,
|
||||
std::string &basename);
|
||||
void
|
||||
SetEncodingType (Type *encoding_type)
|
||||
{
|
||||
|
@ -491,7 +500,7 @@ public:
|
|||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
uint64_t
|
||||
GetBitOffset () const
|
||||
{
|
||||
|
|
|
@ -51,6 +51,17 @@ public:
|
|||
lldb::TypeSP
|
||||
GetTypeAtIndex(uint32_t idx);
|
||||
|
||||
bool
|
||||
RemoveTypeWithUID (lldb::user_id_t uid);
|
||||
|
||||
void
|
||||
RemoveMismatchedTypes (const char *qualified_typename,
|
||||
bool exact_match);
|
||||
|
||||
void
|
||||
RemoveMismatchedTypes (const std::string &type_scope,
|
||||
const std::string &type_basename,
|
||||
bool exact_match);
|
||||
private:
|
||||
typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
|
||||
typedef collection::iterator iterator;
|
||||
|
|
|
@ -425,12 +425,12 @@ SBModule::FindFirstType (const char *name_cstr)
|
|||
SymbolContext sc;
|
||||
TypeList type_list;
|
||||
uint32_t num_matches = 0;
|
||||
const bool exact_match = false;
|
||||
ConstString name(name_cstr);
|
||||
|
||||
num_matches = module_sp->FindTypes (sc,
|
||||
name,
|
||||
NULL,
|
||||
false,
|
||||
exact_match,
|
||||
1,
|
||||
type_list);
|
||||
|
||||
|
@ -451,13 +451,13 @@ SBModule::FindTypes (const char *type)
|
|||
{
|
||||
SymbolContext sc;
|
||||
TypeList type_list;
|
||||
const bool exact_match = false;
|
||||
uint32_t num_matches = 0;
|
||||
ConstString name(type);
|
||||
|
||||
num_matches = module_sp->FindTypes (sc,
|
||||
name,
|
||||
NULL,
|
||||
false,
|
||||
exact_match,
|
||||
UINT32_MAX,
|
||||
type_list);
|
||||
|
||||
|
|
|
@ -1954,14 +1954,15 @@ SBTarget::FindTypes (const char* type)
|
|||
{
|
||||
ModuleList& images = target_sp->GetImages();
|
||||
ConstString name_const(type);
|
||||
bool exact_match = false;
|
||||
SymbolContext sc;
|
||||
TypeList type_list;
|
||||
|
||||
uint32_t num_matches = images.FindTypes(sc,
|
||||
name_const,
|
||||
true,
|
||||
UINT32_MAX,
|
||||
type_list);
|
||||
uint32_t num_matches = images.FindTypes2 (sc,
|
||||
name_const,
|
||||
exact_match,
|
||||
UINT32_MAX,
|
||||
type_list);
|
||||
|
||||
for (size_t idx = 0; idx < num_matches; idx++)
|
||||
{
|
||||
|
|
|
@ -441,7 +441,8 @@ SBType::GetName()
|
|||
if (!IsValid())
|
||||
return "";
|
||||
|
||||
return ClangASTType::GetConstTypeName(m_opaque_sp->GetOpaqueQualType()).GetCString();
|
||||
return ClangASTType::GetConstTypeName(m_opaque_sp->GetASTContext(),
|
||||
m_opaque_sp->GetOpaqueQualType()).GetCString();
|
||||
}
|
||||
|
||||
lldb::TypeClass
|
||||
|
|
|
@ -138,7 +138,8 @@ SBValue::GetTypeName ()
|
|||
const char *name = NULL;
|
||||
lldb::ValueObjectSP value_sp(GetSP());
|
||||
if (value_sp)
|
||||
name = value_sp->GetTypeName().GetCString();
|
||||
//name = value_sp->GetTypeName().GetCString();
|
||||
name = value_sp->GetQualifiedTypeName().GetCString();
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
||||
if (log)
|
||||
{
|
||||
|
|
|
@ -386,7 +386,7 @@ public:
|
|||
{
|
||||
// We are viewing memory as a type
|
||||
SymbolContext sc;
|
||||
const bool append = true;
|
||||
const bool exact_match = false;
|
||||
TypeList type_list;
|
||||
uint32_t reference_count = 0;
|
||||
uint32_t pointer_count = 0;
|
||||
|
@ -458,17 +458,16 @@ public:
|
|||
{
|
||||
sc.module_sp->FindTypes (sc,
|
||||
lookup_type_name,
|
||||
NULL,
|
||||
append,
|
||||
exact_match,
|
||||
1,
|
||||
type_list);
|
||||
}
|
||||
}
|
||||
if (type_list.GetSize() == 0)
|
||||
{
|
||||
target->GetImages().FindTypes (sc,
|
||||
target->GetImages().FindTypes2 (sc,
|
||||
lookup_type_name,
|
||||
append,
|
||||
exact_match,
|
||||
1,
|
||||
type_list);
|
||||
}
|
||||
|
|
|
@ -1585,12 +1585,13 @@ LookupTypeInModule (CommandInterpreter &interpreter,
|
|||
if (module && name_cstr && name_cstr[0])
|
||||
{
|
||||
TypeList type_list;
|
||||
const uint32_t max_num_matches = 1;
|
||||
const uint32_t max_num_matches = UINT32_MAX;
|
||||
uint32_t num_matches = 0;
|
||||
bool name_is_fully_qualified = false;
|
||||
SymbolContext sc;
|
||||
|
||||
ConstString name(name_cstr);
|
||||
num_matches = module->FindTypes(sc, name, NULL, true, max_num_matches, type_list);
|
||||
num_matches = module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches, type_list);
|
||||
|
||||
if (num_matches)
|
||||
{
|
||||
|
|
|
@ -630,7 +630,7 @@ FormatManager::LoadSTLFormatters()
|
|||
std_string_summary_sp);
|
||||
gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"),
|
||||
std_string_summary_sp);
|
||||
gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char, class std::char_traits<char>, class std::allocator<char> >"),
|
||||
gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
|
||||
std_string_summary_sp);
|
||||
|
||||
|
||||
|
@ -676,7 +676,7 @@ FormatManager::LoadLibcxxFormatters()
|
|||
|
||||
libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::string"),
|
||||
std_string_summary_sp);
|
||||
libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::basic_string<char, class std::__1::char_traits<char>, class std::__1::allocator<char> >"),
|
||||
libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"),
|
||||
std_string_summary_sp);
|
||||
|
||||
SyntheticChildren::Flags stl_synth_flags;
|
||||
|
|
|
@ -632,7 +632,12 @@ Module::FindFunctions (const RegularExpression& regex,
|
|||
}
|
||||
|
||||
uint32_t
|
||||
Module::FindTypes_Impl (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types)
|
||||
Module::FindTypes_Impl (const SymbolContext& sc,
|
||||
const ConstString &name,
|
||||
const ClangNamespaceDecl *namespace_decl,
|
||||
bool append,
|
||||
uint32_t max_matches,
|
||||
TypeList& types)
|
||||
{
|
||||
Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
|
||||
if (sc.module_sp.get() == NULL || sc.module_sp.get() == this)
|
||||
|
@ -644,46 +649,59 @@ Module::FindTypes_Impl (const SymbolContext& sc, const ConstString &name, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
// depending on implementation details, type lookup might fail because of
|
||||
// embedded spurious namespace:: prefixes. this call strips them, paying
|
||||
// attention to the fact that a type might have namespace'd type names as
|
||||
// arguments to templates, and those must not be stripped off
|
||||
static const char*
|
||||
StripTypeName(const char* name_cstr)
|
||||
uint32_t
|
||||
Module::FindTypesInNamespace (const SymbolContext& sc,
|
||||
const ConstString &type_name,
|
||||
const ClangNamespaceDecl *namespace_decl,
|
||||
uint32_t max_matches,
|
||||
TypeList& type_list)
|
||||
{
|
||||
// Protect against null c string.
|
||||
if (!name_cstr)
|
||||
return name_cstr;
|
||||
const char* skip_namespace = strstr(name_cstr, "::");
|
||||
const char* template_arg_char = strchr(name_cstr, '<');
|
||||
while (skip_namespace != NULL)
|
||||
{
|
||||
if (template_arg_char != NULL &&
|
||||
skip_namespace > template_arg_char) // but namespace'd template arguments are still good to go
|
||||
break;
|
||||
name_cstr = skip_namespace+2;
|
||||
skip_namespace = strstr(name_cstr, "::");
|
||||
}
|
||||
return name_cstr;
|
||||
const bool append = true;
|
||||
return FindTypes_Impl(sc, type_name, namespace_decl, append, max_matches, type_list);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Module::FindTypes (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types)
|
||||
Module::FindTypes (const SymbolContext& sc,
|
||||
const ConstString &name,
|
||||
bool exact_match,
|
||||
uint32_t max_matches,
|
||||
TypeList& types)
|
||||
{
|
||||
uint32_t retval = FindTypes_Impl(sc, name, namespace_decl, append, max_matches, types);
|
||||
|
||||
if (retval == 0)
|
||||
uint32_t num_matches = 0;
|
||||
const char *type_name_cstr = name.GetCString();
|
||||
std::string type_scope;
|
||||
std::string type_basename;
|
||||
const bool append = true;
|
||||
if (Type::GetTypeScopeAndBasename (type_name_cstr, type_scope, type_basename))
|
||||
{
|
||||
const char *orig_name = name.GetCString();
|
||||
const char *stripped = StripTypeName(orig_name);
|
||||
// Only do this lookup if StripTypeName has stripped the name:
|
||||
if (stripped != orig_name)
|
||||
return FindTypes_Impl(sc, ConstString(stripped), namespace_decl, append, max_matches, types);
|
||||
// Check if "name" starts with "::" which means the qualified type starts
|
||||
// from the root namespace and implies and exact match. The typenames we
|
||||
// get back from clang do not start with "::" so we need to strip this off
|
||||
// in order to get the qualfied names to match
|
||||
|
||||
if (type_scope.size() >= 2 && type_scope[0] == ':' && type_scope[1] == ':')
|
||||
{
|
||||
type_scope.erase(0,2);
|
||||
exact_match = true;
|
||||
}
|
||||
ConstString type_basename_const_str (type_basename.c_str());
|
||||
if (FindTypes_Impl(sc, type_basename_const_str, NULL, append, max_matches, types))
|
||||
{
|
||||
types.RemoveMismatchedTypes (type_scope, type_basename, exact_match);
|
||||
num_matches = types.GetSize();
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
{
|
||||
types.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
return retval;
|
||||
{
|
||||
// The type is not in a namespace/class scope, just search for it by basename
|
||||
num_matches = FindTypes_Impl(sc, name, NULL, append, max_matches, types);
|
||||
}
|
||||
|
||||
return num_matches;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -352,19 +352,16 @@ ModuleList::FindModule (const UUID &uuid)
|
|||
|
||||
|
||||
uint32_t
|
||||
ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types)
|
||||
ModuleList::FindTypes2 (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, uint32_t max_matches, TypeList& types)
|
||||
{
|
||||
Mutex::Locker locker(m_modules_mutex);
|
||||
|
||||
if (!append)
|
||||
types.Clear();
|
||||
|
||||
uint32_t total_matches = 0;
|
||||
collection::const_iterator pos, end = m_modules.end();
|
||||
for (pos = m_modules.begin(); pos != end; ++pos)
|
||||
{
|
||||
if (sc.module_sp.get() == NULL || sc.module_sp.get() == (*pos).get())
|
||||
total_matches += (*pos)->FindTypes (sc, name, NULL, true, max_matches, types);
|
||||
total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types);
|
||||
|
||||
if (total_matches >= max_matches)
|
||||
break;
|
||||
|
|
|
@ -1676,6 +1676,19 @@ ValueObject::GetDeclaration (Declaration &decl)
|
|||
return false;
|
||||
}
|
||||
|
||||
ConstString
|
||||
ValueObject::GetTypeName()
|
||||
{
|
||||
return ClangASTType::GetConstTypeName (GetClangAST(), GetClangType());
|
||||
}
|
||||
|
||||
ConstString
|
||||
ValueObject::GetQualifiedTypeName()
|
||||
{
|
||||
return ClangASTType::GetConstQualifiedTypeName (GetClangAST(), GetClangType());
|
||||
}
|
||||
|
||||
|
||||
LanguageType
|
||||
ValueObject::GetObjectRuntimeLanguage ()
|
||||
{
|
||||
|
@ -2640,13 +2653,10 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
|
|||
else
|
||||
{
|
||||
if (ClangASTType::GetMinimumLanguage(root->GetClangAST(),
|
||||
root->GetClangType()) == eLanguageTypeObjC
|
||||
&&
|
||||
ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(root->GetClangType())) == false
|
||||
&&
|
||||
root->HasSyntheticValue()
|
||||
&&
|
||||
options.m_no_synthetic_children == false)
|
||||
root->GetClangType()) == eLanguageTypeObjC
|
||||
&& ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(root->GetClangType())) == false
|
||||
&& root->HasSyntheticValue()
|
||||
&& options.m_no_synthetic_children == false)
|
||||
{
|
||||
root = root->GetSyntheticValue()->GetChildAtIndex(index, true);
|
||||
}
|
||||
|
@ -3152,7 +3162,8 @@ DumpValueObject_Impl (Stream &s,
|
|||
// Always show the type for the top level items.
|
||||
if (options.m_show_types || (curr_depth == 0 && !options.m_flat_output))
|
||||
{
|
||||
const char* typeName = valobj->GetTypeName().AsCString("<invalid type>");
|
||||
const char* typeName = valobj->GetQualifiedTypeName().AsCString("<invalid type>");
|
||||
//const char* typeName = valobj->GetTypeName().AsCString("<invalid type>");
|
||||
s.Printf("(%s", typeName);
|
||||
// only show dynamic types if the user really wants to see types
|
||||
if (options.m_show_types && options.m_use_dynamic != eNoDynamicValues &&
|
||||
|
|
|
@ -73,7 +73,7 @@ ValueObjectChild::GetTypeName()
|
|||
{
|
||||
if (m_type_name.IsEmpty())
|
||||
{
|
||||
m_type_name = ClangASTType::GetConstTypeName (GetClangType());
|
||||
m_type_name = ClangASTType::GetConstTypeName (GetClangAST(), GetClangType());
|
||||
if (m_type_name)
|
||||
{
|
||||
if (m_bitfield_bit_size > 0)
|
||||
|
@ -91,6 +91,26 @@ ValueObjectChild::GetTypeName()
|
|||
return m_type_name;
|
||||
}
|
||||
|
||||
ConstString
|
||||
ValueObjectChild::GetQualifiedTypeName()
|
||||
{
|
||||
ConstString qualified_name = ClangASTType::GetConstQualifiedTypeName (GetClangAST(), GetClangType());
|
||||
if (qualified_name)
|
||||
{
|
||||
if (m_bitfield_bit_size > 0)
|
||||
{
|
||||
const char *clang_type_name = qualified_name.AsCString();
|
||||
if (clang_type_name)
|
||||
{
|
||||
std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
|
||||
::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, m_bitfield_bit_size);
|
||||
qualified_name.SetCString(&bitfield_type_name.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
return qualified_name;
|
||||
}
|
||||
|
||||
bool
|
||||
ValueObjectChild::UpdateValue ()
|
||||
{
|
||||
|
|
|
@ -316,7 +316,7 @@ ConstString
|
|||
ValueObjectConstResult::GetTypeName()
|
||||
{
|
||||
if (m_type_name.IsEmpty())
|
||||
m_type_name = ClangASTType::GetConstTypeName (GetClangType());
|
||||
m_type_name = ClangASTType::GetConstTypeName (GetClangAST(), GetClangType());
|
||||
return m_type_name;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,12 +66,6 @@ ValueObjectCast::GetClangTypeImpl ()
|
|||
return m_cast_type.GetOpaqueQualType();
|
||||
}
|
||||
|
||||
ConstString
|
||||
ValueObjectCast::GetTypeName()
|
||||
{
|
||||
return ClangASTType::GetConstTypeName (GetClangType());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ValueObjectCast::CalculateNumChildren()
|
||||
{
|
||||
|
@ -172,7 +166,7 @@ ValueObjectDynamicValue::GetTypeName()
|
|||
{
|
||||
const bool success = UpdateValueIfNeeded(false);
|
||||
if (success && m_type_sp)
|
||||
return ClangASTType::GetConstTypeName (GetClangType());
|
||||
return ClangASTType::GetConstTypeName (GetClangAST(), GetClangType());
|
||||
else
|
||||
return m_parent->GetTypeName();
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ ValueObjectMemory::GetTypeName()
|
|||
{
|
||||
if (m_type_sp)
|
||||
return m_type_sp->GetName();
|
||||
return ClangASTType::GetConstTypeName (m_clang_type.GetOpaqueQualType());
|
||||
return ClangASTType::GetConstTypeName (GetClangAST(), m_clang_type.GetOpaqueQualType());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
|
@ -326,7 +326,7 @@ ConstString
|
|||
ValueObjectRegister::GetTypeName()
|
||||
{
|
||||
if (m_type_name.IsEmpty())
|
||||
m_type_name = ClangASTType::GetConstTypeName (GetClangType());
|
||||
m_type_name = ClangASTType::GetConstTypeName (GetClangAST(), GetClangType());
|
||||
return m_type_name;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,8 +67,16 @@ ValueObjectVariable::GetTypeName()
|
|||
Type * var_type = m_variable_sp->GetType();
|
||||
if (var_type)
|
||||
return var_type->GetName();
|
||||
ConstString empty_type_name;
|
||||
return empty_type_name;
|
||||
return ConstString();
|
||||
}
|
||||
|
||||
ConstString
|
||||
ValueObjectVariable::GetQualifiedTypeName()
|
||||
{
|
||||
Type * var_type = m_variable_sp->GetType();
|
||||
if (var_type)
|
||||
return var_type->GetQualifiedName();
|
||||
return ConstString();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
|
@ -206,7 +206,7 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
|
|||
SymbolContext null_sc;
|
||||
ConstString name(tag_decl->getName().str().c_str());
|
||||
|
||||
i->first->FindTypes(null_sc, name, &i->second, true, UINT32_MAX, types);
|
||||
i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types);
|
||||
|
||||
for (uint32_t ti = 0, te = types.GetSize();
|
||||
ti != te && !found;
|
||||
|
@ -244,7 +244,8 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
|
|||
|
||||
ModuleList &module_list = m_target->GetImages();
|
||||
|
||||
module_list.FindTypes(null_sc, name, true, UINT32_MAX, types);
|
||||
bool exact_match = false;
|
||||
module_list.FindTypes2 (null_sc, name, exact_match, UINT32_MAX, types);
|
||||
|
||||
for (uint32_t ti = 0, te = types.GetSize();
|
||||
ti != te && !found;
|
||||
|
@ -592,11 +593,12 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
|
|||
{
|
||||
TypeList types;
|
||||
SymbolContext null_sc;
|
||||
const bool exact_match = false;
|
||||
|
||||
if (module_sp && namespace_decl)
|
||||
module_sp->FindTypes(null_sc, name, &namespace_decl, true, 1, types);
|
||||
module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);
|
||||
else
|
||||
m_target->GetImages().FindTypes(null_sc, name, true, 1, types);
|
||||
m_target->GetImages().FindTypes2(null_sc, name, exact_match, 1, types);
|
||||
|
||||
if (types.GetSize())
|
||||
{
|
||||
|
|
|
@ -113,7 +113,8 @@ ClangFunction::CompileFunction (Stream &errors)
|
|||
// FIXME: How does clang tell us there's no return value? We need to handle that case.
|
||||
unsigned num_errors = 0;
|
||||
|
||||
std::string return_type_str (ClangASTType::GetTypeNameForOpaqueQualType (m_function_return_qual_type));
|
||||
std::string return_type_str (ClangASTType::GetTypeNameForOpaqueQualType (m_clang_ast_context->getASTContext(),
|
||||
m_function_return_qual_type));
|
||||
|
||||
// Cons up the function we're going to wrap our call in, then compile it...
|
||||
// We declare the function "extern "C"" because the compiler might be in C++
|
||||
|
@ -159,7 +160,8 @@ ClangFunction::CompileFunction (Stream &errors)
|
|||
if (trust_function)
|
||||
{
|
||||
lldb::clang_type_t arg_clang_type = m_function_ptr->GetArgumentTypeAtIndex(i);
|
||||
type_name = ClangASTType::GetTypeNameForOpaqueQualType (arg_clang_type);
|
||||
type_name = ClangASTType::GetTypeNameForOpaqueQualType (m_clang_ast_context->getASTContext(),
|
||||
arg_clang_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -167,7 +169,8 @@ ClangFunction::CompileFunction (Stream &errors)
|
|||
lldb::clang_type_t clang_qual_type = arg_value->GetClangType ();
|
||||
if (clang_qual_type != NULL)
|
||||
{
|
||||
type_name = ClangASTType::GetTypeNameForOpaqueQualType (clang_qual_type);
|
||||
type_name = ClangASTType::GetTypeNameForOpaqueQualType (m_clang_ast_context->getASTContext(),
|
||||
clang_qual_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -57,9 +57,6 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
|
|||
// Only a pointer or reference type can have a different dynamic and static type:
|
||||
if (CouldHaveDynamicValue (in_value))
|
||||
{
|
||||
// FIXME: Can we get the Clang Type and ask it if the thing is really virtual? That would avoid false positives,
|
||||
// at the cost of not looking for the dynamic type of objects if DWARF->Clang gets it wrong.
|
||||
|
||||
// First job, pull out the address at 0 offset from the object.
|
||||
AddressType address_type;
|
||||
lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
|
||||
|
@ -107,52 +104,76 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
|
|||
const char *name = symbol->GetMangled().GetDemangledName().AsCString();
|
||||
if (strstr(name, vtable_demangled_prefix) == name)
|
||||
{
|
||||
printf ("0x%16.16llx: static-type = '%s' has vtable symbol '%s'\n",
|
||||
original_ptr,
|
||||
in_value.GetTypeName().GetCString(),
|
||||
name);
|
||||
// We are a C++ class, that's good. Get the class name and look it up:
|
||||
const char *class_name = name + strlen(vtable_demangled_prefix);
|
||||
class_type_or_name.SetName (class_name);
|
||||
const bool exact_match = true;
|
||||
TypeList class_types;
|
||||
uint32_t num_matches = target->GetImages().FindTypes (sc,
|
||||
ConstString(class_name),
|
||||
true,
|
||||
UINT32_MAX,
|
||||
class_types);
|
||||
uint32_t num_matches = target->GetImages().FindTypes2 (sc,
|
||||
ConstString(class_name),
|
||||
exact_match,
|
||||
UINT32_MAX,
|
||||
class_types);
|
||||
if (num_matches == 0)
|
||||
{
|
||||
printf ("0x%16.16llx: is not dynamic\n", original_ptr);
|
||||
return false;
|
||||
}
|
||||
if (num_matches == 1)
|
||||
{
|
||||
lldb::TypeSP type_sp(class_types.GetTypeAtIndex(0));
|
||||
|
||||
printf ("0x%16.16llx: static-type = '%s' has single matching dynamic type: uid={0x%llx}, type-name='%s'\n",
|
||||
original_ptr,
|
||||
in_value.GetTypeName().AsCString(),
|
||||
type_sp->GetID(),
|
||||
type_sp->GetName().GetCString());
|
||||
|
||||
class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
|
||||
}
|
||||
else if (num_matches > 1)
|
||||
{
|
||||
for (size_t i = 0; i < num_matches; i++)
|
||||
{
|
||||
lldb::TypeSP this_type(class_types.GetTypeAtIndex(i));
|
||||
if (this_type)
|
||||
lldb::TypeSP type_sp(class_types.GetTypeAtIndex(i));
|
||||
if (type_sp)
|
||||
{
|
||||
if (ClangASTContext::IsCXXClassType(this_type->GetClangFullType()))
|
||||
{
|
||||
// There can only be one type with a given name,
|
||||
// so we've just found duplicate definitions, and this
|
||||
// one will do as well as any other.
|
||||
// We don't consider something to have a dynamic type if
|
||||
// it is the same as the static type. So compare against
|
||||
// the value we were handed:
|
||||
|
||||
clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
|
||||
clang::ASTContext *this_ast_ctx = this_type->GetClangAST ();
|
||||
if (in_ast_ctx != this_ast_ctx
|
||||
|| !ClangASTContext::AreTypesSame (in_ast_ctx,
|
||||
in_value.GetClangType(),
|
||||
this_type->GetClangFullType()))
|
||||
{
|
||||
class_type_or_name.SetTypeSP (this_type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types: uid={0x%llx}, type-name='%s'\n",
|
||||
original_ptr,
|
||||
in_value.GetTypeName().AsCString(),
|
||||
type_sp->GetID(),
|
||||
type_sp->GetName().GetCString());
|
||||
|
||||
|
||||
// if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType()))
|
||||
// {
|
||||
// // There can only be one type with a given name,
|
||||
// // so we've just found duplicate definitions, and this
|
||||
// // one will do as well as any other.
|
||||
// // We don't consider something to have a dynamic type if
|
||||
// // it is the same as the static type. So compare against
|
||||
// // the value we were handed:
|
||||
//
|
||||
// clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
|
||||
// clang::ASTContext *this_ast_ctx = type_sp->GetClangAST ();
|
||||
// if (in_ast_ctx != this_ast_ctx
|
||||
// || !ClangASTContext::AreTypesSame (in_ast_ctx,
|
||||
// in_value.GetClangType(),
|
||||
// type_sp->GetClangFullType()))
|
||||
// {
|
||||
// class_type_or_name.SetTypeSP (this_type);
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// The offset_to_top is two pointers above the address.
|
||||
Address offset_to_top_address = address_point_address;
|
||||
|
@ -187,7 +208,6 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -349,9 +349,10 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
|
|||
|
||||
TypeList class_types;
|
||||
SymbolContext sc;
|
||||
uint32_t num_matches = target.GetImages().FindTypes (sc,
|
||||
const bool exact_match = true;
|
||||
uint32_t num_matches = target.GetImages().FindTypes2 (sc,
|
||||
class_type_or_name.GetName(),
|
||||
true,
|
||||
exact_match,
|
||||
UINT32_MAX,
|
||||
class_types);
|
||||
if (num_matches == 1)
|
||||
|
|
|
@ -476,12 +476,6 @@ PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info)
|
|||
|
||||
if (IsHost())
|
||||
{
|
||||
if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
|
||||
{
|
||||
const bool is_localhost = true;
|
||||
if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost))
|
||||
return error;
|
||||
}
|
||||
error = Platform::LaunchProcess (launch_info);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1991,7 +1991,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (lldb::clang_type_t clang_type
|
|||
|
||||
if (class_language == eLanguageTypeObjC)
|
||||
{
|
||||
std::string class_str (ClangASTType::GetTypeNameForOpaqueQualType(clang_type));
|
||||
std::string class_str (ClangASTType::GetTypeNameForOpaqueQualType(ast.getASTContext(), clang_type));
|
||||
if (!class_str.empty())
|
||||
{
|
||||
|
||||
|
|
|
@ -1038,10 +1038,10 @@ ClangASTContext::CopyDecl (ASTContext *dst_ast,
|
|||
}
|
||||
|
||||
bool
|
||||
ClangASTContext::AreTypesSame(ASTContext *ast,
|
||||
clang_type_t type1,
|
||||
clang_type_t type2,
|
||||
bool ignore_qualifiers)
|
||||
ClangASTContext::AreTypesSame (ASTContext *ast,
|
||||
clang_type_t type1,
|
||||
clang_type_t type2,
|
||||
bool ignore_qualifiers)
|
||||
{
|
||||
QualType type1_qual = QualType::getFromOpaquePtr(type1);
|
||||
QualType type2_qual = QualType::getFromOpaquePtr(type2);
|
||||
|
@ -3797,7 +3797,7 @@ ClangASTContext::GetChildClangTypeAtIndex
|
|||
// Base classes should be a multiple of 8 bits in size
|
||||
child_byte_offset = bit_offset/8;
|
||||
|
||||
child_name = ClangASTType::GetTypeNameForQualType(base_class->getType());
|
||||
child_name = ClangASTType::GetTypeNameForQualType(ast, base_class->getType());
|
||||
|
||||
uint64_t clang_type_info_bit_size = ast->getTypeSize(base_class->getType());
|
||||
|
||||
|
@ -4662,7 +4662,7 @@ ClangASTContext::GetIndexOfChildWithName
|
|||
if (omit_empty_base_classes && RecordHasFields(base_class_decl) == false)
|
||||
continue;
|
||||
|
||||
std::string base_class_type_name (ClangASTType::GetTypeNameForQualType(base_class->getType()));
|
||||
std::string base_class_type_name (ClangASTType::GetTypeNameForQualType(ast, base_class->getType()));
|
||||
if (base_class_type_name.compare (name) == 0)
|
||||
return child_idx;
|
||||
++child_idx;
|
||||
|
|
|
@ -47,87 +47,64 @@ ClangASTType::~ClangASTType()
|
|||
}
|
||||
|
||||
std::string
|
||||
ClangASTType::GetTypeNameForQualType (clang::QualType qual_type)
|
||||
ClangASTType::GetTypeNameForQualType (clang::ASTContext *ast, clang::QualType qual_type)
|
||||
{
|
||||
std::string type_name;
|
||||
|
||||
clang::PrintingPolicy printing_policy (ast->getPrintingPolicy());
|
||||
printing_policy.SuppressTagKeyword = true;
|
||||
const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
|
||||
if (typedef_type)
|
||||
{
|
||||
const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
|
||||
type_name = typedef_decl->getQualifiedNameAsString();
|
||||
type_name = typedef_decl->getQualifiedNameAsString(printing_policy);
|
||||
}
|
||||
else
|
||||
{
|
||||
type_name = qual_type.getAsString();
|
||||
type_name = qual_type.getAsString(printing_policy);
|
||||
}
|
||||
|
||||
// There is no call to a clang type to get the type name without the
|
||||
// class/struct/union/enum on the front, so lets strip it here
|
||||
const char *type_name_cstr = type_name.c_str();
|
||||
if (type_name_cstr[0] == 'c' &&
|
||||
type_name_cstr[1] == 'l' &&
|
||||
type_name_cstr[2] == 'a' &&
|
||||
type_name_cstr[3] == 's' &&
|
||||
type_name_cstr[4] == 's' &&
|
||||
type_name_cstr[5] == ' ')
|
||||
{
|
||||
type_name.erase (0, 6);
|
||||
}
|
||||
else if (type_name_cstr[0] == 's' &&
|
||||
type_name_cstr[1] == 't' &&
|
||||
type_name_cstr[2] == 'r' &&
|
||||
type_name_cstr[3] == 'u' &&
|
||||
type_name_cstr[4] == 'c' &&
|
||||
type_name_cstr[5] == 't' &&
|
||||
type_name_cstr[6] == ' ')
|
||||
{
|
||||
type_name.erase (0, 7);
|
||||
}
|
||||
else if (type_name_cstr[0] == 'u' &&
|
||||
type_name_cstr[1] == 'n' &&
|
||||
type_name_cstr[2] == 'i' &&
|
||||
type_name_cstr[3] == 'o' &&
|
||||
type_name_cstr[4] == 'n' &&
|
||||
type_name_cstr[5] == ' ')
|
||||
{
|
||||
type_name.erase (0, 6);
|
||||
}
|
||||
else if (type_name_cstr[0] == 'e' &&
|
||||
type_name_cstr[1] == 'n' &&
|
||||
type_name_cstr[2] == 'u' &&
|
||||
type_name_cstr[3] == 'm' &&
|
||||
type_name_cstr[4] == ' ')
|
||||
{
|
||||
type_name.erase (0, 5);
|
||||
}
|
||||
|
||||
return type_name;
|
||||
}
|
||||
|
||||
std::string
|
||||
ClangASTType::GetTypeNameForOpaqueQualType (clang_type_t opaque_qual_type)
|
||||
ClangASTType::GetTypeNameForOpaqueQualType (clang::ASTContext *ast, clang_type_t opaque_qual_type)
|
||||
{
|
||||
return GetTypeNameForQualType (clang::QualType::getFromOpaquePtr(opaque_qual_type));
|
||||
return GetTypeNameForQualType (ast, clang::QualType::getFromOpaquePtr(opaque_qual_type));
|
||||
}
|
||||
|
||||
|
||||
ConstString
|
||||
ClangASTType::GetConstTypeName ()
|
||||
{
|
||||
// TODO: verify if we actually need to complete a type just to get its type name????
|
||||
if (!ClangASTContext::GetCompleteType (this->m_ast, this->m_type))
|
||||
return ConstString("<invalid>");
|
||||
return GetConstTypeName (m_type);
|
||||
return GetConstTypeName (m_ast, m_type);
|
||||
}
|
||||
|
||||
ConstString
|
||||
ClangASTType::GetConstTypeName (clang_type_t clang_type)
|
||||
ClangASTType::GetConstQualifiedTypeName ()
|
||||
{
|
||||
// TODO: verify if we actually need to complete a type just to get its fully qualified type name????
|
||||
if (!ClangASTContext::GetCompleteType (this->m_ast, this->m_type))
|
||||
return ConstString("<invalid>");
|
||||
return GetConstQualifiedTypeName (m_ast, m_type);
|
||||
}
|
||||
|
||||
ConstString
|
||||
ClangASTType::GetConstQualifiedTypeName (clang::ASTContext *ast, clang_type_t opaque_qual_type)
|
||||
{
|
||||
return ConstString (GetTypeNameForQualType (ast, clang::QualType::getFromOpaquePtr(opaque_qual_type)).c_str());
|
||||
}
|
||||
|
||||
|
||||
ConstString
|
||||
ClangASTType::GetConstTypeName (clang::ASTContext *ast, clang_type_t clang_type)
|
||||
{
|
||||
if (!clang_type)
|
||||
return ConstString("<invalid>");
|
||||
|
||||
clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
|
||||
std::string type_name (GetTypeNameForQualType (qual_type));
|
||||
std::string type_name (GetTypeNameForOpaqueQualType(ast, clang_type));
|
||||
ConstString const_type_name;
|
||||
if (type_name.empty())
|
||||
const_type_name.SetCString ("<invalid>");
|
||||
|
|
|
@ -120,8 +120,19 @@ Type::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_name)
|
|||
*s << "id = " << (const UserID&)*this;
|
||||
|
||||
// Call the name accessor to make sure we resolve the type name
|
||||
if (show_name && GetName())
|
||||
*s << ", name = \"" << m_name << '"';
|
||||
if (show_name)
|
||||
{
|
||||
const ConstString &type_name = GetName();
|
||||
if (type_name)
|
||||
{
|
||||
*s << ", name = \"" << type_name << '"';
|
||||
ConstString qualified_type_name (GetQualifiedName());
|
||||
if (qualified_type_name != type_name)
|
||||
{
|
||||
*s << ", qualified = \"" << qualified_type_name << '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the get byte size accesor so we resolve our byte size
|
||||
if (GetByteSize())
|
||||
|
@ -213,7 +224,7 @@ Type::GetName()
|
|||
if (!m_name)
|
||||
{
|
||||
if (ResolveClangType(eResolveStateForward))
|
||||
m_name = ClangASTType::GetConstTypeName (m_clang_type);
|
||||
m_name = ClangASTType::GetConstTypeName (GetClangASTContext ().getASTContext(), m_clang_type);
|
||||
}
|
||||
return m_name;
|
||||
}
|
||||
|
@ -693,6 +704,49 @@ Type::IsRealObjCClass()
|
|||
return false;
|
||||
}
|
||||
|
||||
ConstString
|
||||
Type::GetQualifiedName ()
|
||||
{
|
||||
ConstString qualified_name (ClangASTType::GetTypeNameForOpaqueQualType (GetClangASTContext ().getASTContext(), GetClangForwardType()).c_str());
|
||||
return qualified_name;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Type::GetTypeScopeAndBasename (const char* name_cstr,
|
||||
std::string &scope,
|
||||
std::string &basename)
|
||||
{
|
||||
// Protect against null c string.
|
||||
|
||||
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) // but namespace'd template arguments are still good to go
|
||||
break;
|
||||
basename_cstr = namespace_separator + 2;
|
||||
namespace_separator = strstr(basename_cstr, "::");
|
||||
}
|
||||
if (basename_cstr > name_cstr)
|
||||
{
|
||||
scope.assign (name_cstr, basename_cstr - name_cstr);
|
||||
basename.assign (basename_cstr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TypeAndOrName::TypeAndOrName () : m_type_sp(), m_type_name()
|
||||
{
|
||||
|
||||
|
|
|
@ -135,6 +135,20 @@ TypeList::GetTypeAtIndex(uint32_t idx)
|
|||
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)
|
||||
{
|
||||
|
@ -144,6 +158,147 @@ TypeList::Dump(Stream *s, bool show_context)
|
|||
}
|
||||
}
|
||||
|
||||
// depending on implementation details, type lookup might fail because of
|
||||
// embedded spurious namespace:: prefixes. this call strips them, paying
|
||||
// attention to the fact that a type might have namespace'd type names as
|
||||
// arguments to templates, and those must not be stripped off
|
||||
static bool
|
||||
GetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr)
|
||||
{
|
||||
// Protect against null c string.
|
||||
|
||||
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) // but namespace'd template arguments are still good to go
|
||||
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] == ':')
|
||||
{
|
||||
// The typename passed in started with "::" so make sure we only do exact matches
|
||||
if (exact_ptr)
|
||||
*exact_ptr = true;
|
||||
// Strip the leading "::" as this won't ever show in qualified typenames we get
|
||||
// from clang.
|
||||
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;
|
||||
if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename))
|
||||
{
|
||||
type_basename = qualified_typename;
|
||||
type_scope.clear();
|
||||
}
|
||||
return RemoveMismatchedTypes (type_scope, type_basename, exact_match);
|
||||
}
|
||||
|
||||
void
|
||||
TypeList::RemoveMismatchedTypes (const std::string &type_scope,
|
||||
const std::string &type_basename,
|
||||
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;
|
||||
|
||||
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))
|
||||
{
|
||||
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 lookikng for,
|
||||
// but we need to make sure what comes before the matching
|
||||
// type scope is a namepace 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 *
|
||||
//TypeList::CreateClangPointerType (Type *type)
|
||||
//{
|
||||
|
|
|
@ -23,11 +23,9 @@ public:
|
|||
{
|
||||
|
||||
m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>"));
|
||||
m_impl.Append(ConstString("class std::basic_string<char, class std::char_traits<char>, class std::allocator<char> >").AsCString(), ConstString("basic_string<char>"));
|
||||
|
||||
// these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container
|
||||
m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>"));
|
||||
m_impl.Append(ConstString("class std::basic_string<char, class std::char_traits<char>, class std::allocator<char> >").AsCString(), ConstString("std::asic_string<char>"));
|
||||
|
||||
m_impl.Sort();
|
||||
}
|
||||
|
|
|
@ -130,17 +130,15 @@ ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
|
|||
return TypeSP();
|
||||
|
||||
const SymbolContext null_sc;
|
||||
const ClangNamespaceDecl *null_namespace_decl = NULL;
|
||||
const bool append = false;
|
||||
const bool exact_match = true;
|
||||
const uint32_t max_matches = UINT32_MAX;
|
||||
TypeList types;
|
||||
|
||||
module_sp->FindTypes(null_sc,
|
||||
name,
|
||||
null_namespace_decl,
|
||||
append,
|
||||
max_matches,
|
||||
types);
|
||||
module_sp->FindTypes (null_sc,
|
||||
name,
|
||||
exact_match,
|
||||
max_matches,
|
||||
types);
|
||||
|
||||
if (types.GetSize() == 1)
|
||||
{
|
||||
|
|
|
@ -567,7 +567,19 @@ Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
|
|||
// Take care of the host case so that each subclass can just
|
||||
// call this function to get the host functionality.
|
||||
if (IsHost())
|
||||
{
|
||||
if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
|
||||
launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY);
|
||||
|
||||
if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
|
||||
{
|
||||
const bool is_localhost = true;
|
||||
if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost))
|
||||
return error;
|
||||
}
|
||||
|
||||
error = Host::LaunchProcess (launch_info);
|
||||
}
|
||||
else
|
||||
error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
|
||||
return error;
|
||||
|
|
|
@ -58,7 +58,7 @@ class LibcxxMapDataFormatterTestCase(TestBase):
|
|||
|
||||
self.runCmd("frame variable ii -T")
|
||||
|
||||
self.runCmd("type summary add -x \"std::map<\" --summary-string \"map has ${svar%#} items\" -e")
|
||||
self.runCmd("type summary add -x \"std::__1::map<\" --summary-string \"map has ${svar%#} items\" -e")
|
||||
|
||||
self.expect('frame variable ii',
|
||||
substrs = ['map has 0 items',
|
||||
|
@ -135,9 +135,6 @@ class LibcxxMapDataFormatterTestCase(TestBase):
|
|||
self.runCmd("n")
|
||||
self.runCmd("frame variable si -T")
|
||||
|
||||
#self.runCmd("type summary add std::strint_map strint_map --summary-string \"map has ${svar%#} items\" -e")
|
||||
#self.runCmd("type synth add std::strint_map strint_map -l StdMapSynthProvider")
|
||||
|
||||
self.expect('frame variable si',
|
||||
substrs = ['map has 0 items',
|
||||
'{}'])
|
||||
|
@ -210,9 +207,6 @@ class LibcxxMapDataFormatterTestCase(TestBase):
|
|||
self.runCmd("n")
|
||||
self.runCmd("frame variable is -T")
|
||||
|
||||
#self.runCmd("type summary add std::intstr_map intstr_map --summary-string \"map has ${svar%#} items\" -e")
|
||||
#self.runCmd("type synth add std::intstr_map intstr_map -l StdMapSynthProvider")
|
||||
|
||||
self.expect('frame variable is',
|
||||
substrs = ['map has 0 items',
|
||||
'{}'])
|
||||
|
|
|
@ -135,9 +135,6 @@ class StdMapDataFormatterTestCase(TestBase):
|
|||
self.runCmd("n")
|
||||
self.runCmd("frame variable si -T")
|
||||
|
||||
#self.runCmd("type summary add std::strint_map strint_map --summary-string \"map has ${svar%#} items\" -e")
|
||||
#self.runCmd("type synth add std::strint_map strint_map -l StdMapSynthProvider")
|
||||
|
||||
self.expect('frame variable si',
|
||||
substrs = ['map has 0 items',
|
||||
'{}'])
|
||||
|
@ -210,9 +207,6 @@ class StdMapDataFormatterTestCase(TestBase):
|
|||
self.runCmd("n")
|
||||
self.runCmd("frame variable is -T")
|
||||
|
||||
#self.runCmd("type summary add std::intstr_map intstr_map --summary-string \"map has ${svar%#} items\" -e")
|
||||
#self.runCmd("type synth add std::intstr_map intstr_map -l StdMapSynthProvider")
|
||||
|
||||
self.expect('frame variable is',
|
||||
substrs = ['map has 0 items',
|
||||
'{}'])
|
||||
|
|
|
@ -99,12 +99,12 @@ class SetValuesTestCase(TestBase):
|
|||
# main.c:57
|
||||
# Check that 'frame variable -T' displays the correct data type and value.
|
||||
self.expect("frame variable -T", VARIABLES_DISPLAYED_CORRECTLY,
|
||||
startstr = "(long int) i = 33")
|
||||
startstr = "(long) i = 33")
|
||||
|
||||
# Now set variable 'i' and check that it is correctly displayed.
|
||||
self.runCmd("expression i = 33333")
|
||||
self.expect("frame variable -T", VARIABLES_DISPLAYED_CORRECTLY,
|
||||
startstr = "(long int) i = 33333")
|
||||
startstr = "(long) i = 33333")
|
||||
|
||||
self.runCmd("continue")
|
||||
|
||||
|
|
|
@ -58,8 +58,8 @@ class UnsignedTypesTestCase(TestBase):
|
|||
patterns = ["\((short int|short)\) the_signed_short = 99"],
|
||||
substrs = ["(signed char) the_signed_char = 'c'",
|
||||
"(int) the_signed_int = 99",
|
||||
"(long int) the_signed_long = 99",
|
||||
"(long long int) the_signed_long_long = 99"])
|
||||
"(long) the_signed_long = 99",
|
||||
"(long long) the_signed_long_long = 99"])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -55,8 +55,8 @@ class UnsignedTypesTestCase(TestBase):
|
|||
startstr = "(unsigned char) the_unsigned_char = 'c'",
|
||||
patterns = ["\((short unsigned int|unsigned short)\) the_unsigned_short = 99"],
|
||||
substrs = ["(unsigned int) the_unsigned_int = 99",
|
||||
"(long unsigned int) the_unsigned_long = 99",
|
||||
"(long long unsigned int) the_unsigned_long_long = 99",
|
||||
"(unsigned long) the_unsigned_long = 99",
|
||||
"(unsigned long long) the_unsigned_long_long = 99",
|
||||
"(uint32_t) the_uint32 = 99"])
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue