diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index b304563221e0..c27490144eb8 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -374,6 +374,10 @@ public: ClangASTType GetClangType (); + + // this vends a TypeImpl that is useful at the SB API layer + virtual TypeImpl + GetTypeImpl (); //------------------------------------------------------------------ // Sublasses must implement the functions below. diff --git a/lldb/include/lldb/Core/ValueObjectDynamicValue.h b/lldb/include/lldb/Core/ValueObjectDynamicValue.h index c0f6baade3fb..68f88c96e545 100644 --- a/lldb/include/lldb/Core/ValueObjectDynamicValue.h +++ b/lldb/include/lldb/Core/ValueObjectDynamicValue.h @@ -93,6 +93,9 @@ public: virtual bool SetData (DataExtractor &data, Error &error); + virtual TypeImpl + GetTypeImpl (); + protected: virtual bool UpdateValue (); @@ -116,6 +119,7 @@ protected: TypeAndOrName m_dynamic_type_info; // We can have a type_sp or just a name lldb::ValueObjectSP m_owning_valobj_sp; lldb::DynamicValueType m_use_dynamic; + TypeImpl m_type_impl; private: friend class ValueObject; diff --git a/lldb/include/lldb/DataFormatters/FormatClasses.h b/lldb/include/lldb/DataFormatters/FormatClasses.h index 9e11471546ec..6d9a50e8f2c5 100644 --- a/lldb/include/lldb/DataFormatters/FormatClasses.h +++ b/lldb/include/lldb/DataFormatters/FormatClasses.h @@ -60,7 +60,7 @@ public: if (type) { m_type.m_type_name.assign(type->GetName().GetCString()); - m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type)); + m_type.m_type_pair.SetType(type); } } @@ -71,7 +71,7 @@ public: if (type.IsValid()) { m_type.m_type_name.assign(type.GetConstTypeName().GetCString()); - m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type)); + m_type.m_type_pair.SetType(type); } } @@ -86,16 +86,16 @@ public: lldb::TypeSP GetTypeSP () { - if (m_type.m_typeimpl_sp && m_type.m_typeimpl_sp->IsValid()) - return m_type.m_typeimpl_sp->GetTypeSP(); + if (m_type.m_type_pair.IsValid()) + return m_type.m_type_pair.GetTypeSP(); return lldb::TypeSP(); } ClangASTType GetClangASTType () { - if (m_type.m_typeimpl_sp && m_type.m_typeimpl_sp->IsValid()) - return m_type.m_typeimpl_sp->GetClangASTType(); + if (m_type.m_type_pair.IsValid()) + return m_type.m_type_pair.GetClangASTType(); return ClangASTType(); } @@ -108,12 +108,11 @@ public: private: bool m_is_regex; // this works better than TypeAndOrName because the latter only wraps a TypeSP - // whereas TypeImplSP can also be backed by a ClangASTType which is more commonly - // used in LLDB. moreover, TypeImplSP is also what is currently backing SBType + // whereas TypePair can also be backed by a ClangASTType struct TypeOrName { std::string m_type_name; - lldb::TypeImplSP m_typeimpl_sp; + TypePair m_type_pair; }; TypeOrName m_type; diff --git a/lldb/include/lldb/Symbol/ClangASTType.h b/lldb/include/lldb/Symbol/ClangASTType.h index f0dffe38e194..e5cced340203 100644 --- a/lldb/include/lldb/Symbol/ClangASTType.h +++ b/lldb/include/lldb/Symbol/ClangASTType.h @@ -155,6 +155,12 @@ public: bool IsFunctionType (bool *is_variadic_ptr = NULL) const; + size_t + GetNumberOfFunctionArguments () const; + + ClangASTType + GetFunctionArgumentAtIndex (const size_t index); + bool IsVariadicFunctionType () const; diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index 50b22fe96b9d..920f571fa1e9 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -304,147 +304,236 @@ protected: ResolveClangType (ResolveState clang_type_resolve_state); }; +// these classes are used to back the SBType* objects -/// -/// Sometimes you can find the name of the type corresponding to an object, but we don't have debug -/// information for it. If that is the case, you can return one of these objects, and then if it -/// has a full type, you can use that, but if not at least you can print the name for informational -/// purposes. -/// - -class TypeAndOrName -{ -public: - TypeAndOrName (); - TypeAndOrName (lldb::TypeSP &type_sp); - TypeAndOrName (const char *type_str); - TypeAndOrName (const TypeAndOrName &rhs); - TypeAndOrName (ConstString &type_const_string); - - TypeAndOrName & - operator= (const TypeAndOrName &rhs); - - bool - operator==(const TypeAndOrName &other) const; - - bool - operator!=(const TypeAndOrName &other) const; - - ConstString GetName () const; - - lldb::TypeSP - GetTypeSP () const - { - return m_type_sp; - } - - void - SetName (const ConstString &type_name); - - void - SetName (const char *type_name_cstr); - - void - SetTypeSP (lldb::TypeSP type_sp); - - bool - IsEmpty (); - - bool - HasName (); - - bool - HasTypeSP (); - - void - Clear (); - - operator - bool () - { - return !IsEmpty(); - } - +class TypePair { private: - lldb::TypeSP m_type_sp; - ConstString m_type_name; + ClangASTType clang_type; + lldb::TypeSP type_sp; + +public: + TypePair () : clang_type(), type_sp() {} + TypePair (ClangASTType type) : + clang_type(type), + type_sp() + { + } + + TypePair (lldb::TypeSP type) : + clang_type(), + type_sp(type) + { + clang_type = type_sp->GetClangForwardType(); + } + + bool + IsValid () const + { + return clang_type.IsValid() || (type_sp.get() != nullptr); + } + + explicit operator bool () const + { + return IsValid(); + } + + bool + operator == (const TypePair& rhs) const + { + return clang_type == rhs.clang_type && + type_sp.get() == rhs.type_sp.get(); + } + + bool + operator != (const TypePair& rhs) const + { + return clang_type != rhs.clang_type || + type_sp.get() != rhs.type_sp.get(); + } + + void + Clear () + { + clang_type.Clear(); + type_sp.reset(); + } + + ConstString + GetName () const + { + if (type_sp) + return type_sp->GetName(); + if (clang_type) + return clang_type.GetTypeName(); + return ConstString (); + } + + void + SetType (ClangASTType type) + { + type_sp.reset(); + clang_type = type; + } + + void + SetType (lldb::TypeSP type) + { + type_sp = type; + clang_type = type_sp->GetClangForwardType(); + } + + lldb::TypeSP + GetTypeSP () const + { + return type_sp; + } + + ClangASTType + GetClangASTType () const + { + return clang_type; + } + + ClangASTType + GetPointerType () const + { + if (type_sp) + return type_sp->GetClangLayoutType().GetPointerType(); + return clang_type.GetPointerType(); + } + + ClangASTType + GetPointeeType () const + { + if (type_sp) + return type_sp->GetClangFullType().GetPointeeType(); + return clang_type.GetPointeeType(); + } + + ClangASTType + GetReferenceType () const + { + if (type_sp) + return type_sp->GetClangLayoutType().GetLValueReferenceType(); + return clang_type.GetLValueReferenceType(); + } + + ClangASTType + GetDereferencedType () const + { + if (type_sp) + return type_sp->GetClangFullType().GetNonReferenceType(); + return clang_type.GetNonReferenceType(); + } + + ClangASTType + GetUnqualifiedType () const + { + if (type_sp) + return type_sp->GetClangLayoutType().GetFullyUnqualifiedType(); + return clang_type.GetFullyUnqualifiedType(); + } + + ClangASTType + GetCanonicalType () const + { + if (type_sp) + return type_sp->GetClangFullType().GetCanonicalType(); + return clang_type.GetCanonicalType(); + } + + clang::ASTContext * + GetClangASTContext () const + { + return clang_type.GetASTContext(); + } }; - -// the two classes here are used by the public API as a backend to -// the SBType and SBTypeList classes class TypeImpl { public: - TypeImpl() : - m_clang_ast_type(), - m_type_sp() - { - } + TypeImpl(); - TypeImpl(const TypeImpl& rhs) : - m_clang_ast_type(rhs.m_clang_ast_type), - m_type_sp(rhs.m_type_sp) - { - } + ~TypeImpl () {} - TypeImpl(const lldb_private::ClangASTType& type); + TypeImpl(const TypeImpl& rhs); - TypeImpl(const lldb::TypeSP& type); + TypeImpl (lldb::TypeSP type_sp); + + TypeImpl (ClangASTType clang_type); + + TypeImpl (lldb::TypeSP type_sp, ClangASTType dynamic); + + TypeImpl (ClangASTType clang_type, ClangASTType dynamic); + + TypeImpl (TypePair pair, ClangASTType dynamic); + + void + SetType (lldb::TypeSP type_sp); + + void + SetType (ClangASTType clang_type); + + void + SetType (lldb::TypeSP type_sp, ClangASTType dynamic); + + void + SetType (ClangASTType clang_type, ClangASTType dynamic); + + void + SetType (TypePair pair, ClangASTType dynamic); TypeImpl& operator = (const TypeImpl& rhs); bool - operator == (const TypeImpl& rhs) - { - return m_clang_ast_type == rhs.m_clang_ast_type && m_type_sp.get() == rhs.m_type_sp.get(); - } - - bool - operator != (const TypeImpl& rhs) - { - return m_clang_ast_type != rhs.m_clang_ast_type || m_type_sp.get() != rhs.m_type_sp.get(); - } + operator == (const TypeImpl& rhs) const; bool - IsValid() - { - return m_type_sp.get() != NULL || m_clang_ast_type.IsValid(); - } + operator != (const TypeImpl& rhs) const; - const lldb_private::ClangASTType & - GetClangASTType() const - { - return m_clang_ast_type; - } + bool + IsValid() const; - clang::ASTContext* - GetASTContext(); + explicit operator bool () const; - lldb::clang_type_t - GetOpaqueQualType(); - - lldb::TypeSP - GetTypeSP () - { - return m_type_sp; - } + void Clear(); ConstString - GetName (); - + GetName () const; + + TypeImpl + GetPointerType () const; + + TypeImpl + GetPointeeType () const; + + TypeImpl + GetReferenceType () const; + + TypeImpl + GetDereferencedType () const; + + TypeImpl + GetUnqualifiedType() const; + + TypeImpl + GetCanonicalType() const; + + ClangASTType + GetClangASTType (bool prefer_dynamic); + + clang::ASTContext * + GetClangASTContext (bool prefer_dynamic); + bool GetDescription (lldb_private::Stream &strm, lldb::DescriptionLevel description_level); - void - SetType (const lldb::TypeSP &type_sp); - private: - ClangASTType m_clang_ast_type; - lldb::TypeSP m_type_sp; + TypePair m_static_type; + ClangASTType m_dynamic_type; }; class TypeListImpl @@ -590,6 +679,89 @@ protected: }; +/// +/// Sometimes you can find the name of the type corresponding to an object, but we don't have debug +/// information for it. If that is the case, you can return one of these objects, and then if it +/// has a full type, you can use that, but if not at least you can print the name for informational +/// purposes. +/// + +class TypeAndOrName +{ +public: + TypeAndOrName (); + TypeAndOrName (lldb::TypeSP &type_sp); + TypeAndOrName (const ClangASTType &clang_type); + TypeAndOrName (const char *type_str); + TypeAndOrName (const TypeAndOrName &rhs); + TypeAndOrName (ConstString &type_const_string); + + TypeAndOrName & + operator= (const TypeAndOrName &rhs); + + bool + operator==(const TypeAndOrName &other) const; + + bool + operator!=(const TypeAndOrName &other) const; + + ConstString GetName () const; + + lldb::TypeSP + GetTypeSP () const + { + return m_type_pair.GetTypeSP(); + } + + ClangASTType + GetClangASTType () const + { + return m_type_pair.GetClangASTType(); + } + + void + SetName (const ConstString &type_name); + + void + SetName (const char *type_name_cstr); + + void + SetTypeSP (lldb::TypeSP type_sp); + + void + SetClangASTType (ClangASTType clang_type); + + bool + IsEmpty () const; + + bool + HasName () const; + + bool + HasTypeSP () const; + + bool + HasClangASTType () const; + + bool + HasType () const + { + return HasTypeSP() || HasClangASTType(); + } + + void + Clear (); + + explicit operator bool () + { + return !IsEmpty(); + } + +private: + TypePair m_type_pair; + ConstString m_type_name; +}; + } // namespace lldb_private #endif // liblldb_Type_h_ diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index e06044b09c96..ee59e0e28927 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -227,13 +227,14 @@ class ThreadPlanTracer; class ThreadSpec; class TimeValue; class Type; +class TypeAndOrName; class TypeCategoryMap; class TypeImpl; -class TypeAndOrName; class TypeList; class TypeListImpl; class TypeMemberImpl; class TypeNameSpecifierImpl; +class TypePair; class UUID; class Unwind; class UnwindAssembly; diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index b1f11666590a..cff6e4e2de36 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -1891,7 +1891,7 @@ SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type) { lldb::addr_t address(addr.GetLoadAddress(*this)); lldb::TypeImplSP type_impl_sp (type.GetSP()); - ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType().GetPointerType ()); + ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType(true).GetPointerType ()); if (pointer_ast_type) { lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t))); diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index 9e254779ba18..3055c2752083 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -63,8 +63,10 @@ SBType::operator == (SBType &rhs) if (IsValid() == false) return !rhs.IsValid(); - return (rhs.m_opaque_sp->GetASTContext() == m_opaque_sp->GetASTContext()) && - (rhs.m_opaque_sp->GetOpaqueQualType() == m_opaque_sp->GetOpaqueQualType()); + if (rhs.IsValid() == false) + return false; + + return *m_opaque_sp.get() == *rhs.m_opaque_sp.get(); } bool @@ -72,9 +74,11 @@ SBType::operator != (SBType &rhs) { if (IsValid() == false) return rhs.IsValid(); - - return (rhs.m_opaque_sp->GetASTContext() != m_opaque_sp->GetASTContext()) || - (rhs.m_opaque_sp->GetOpaqueQualType() != m_opaque_sp->GetOpaqueQualType()); + + if (rhs.IsValid() == false) + return true; + + return *m_opaque_sp.get() != *rhs.m_opaque_sp.get(); } lldb::TypeImplSP @@ -136,7 +140,7 @@ SBType::GetByteSize() if (!IsValid()) return 0; - return m_opaque_sp->GetClangASTType().GetByteSize(); + return m_opaque_sp->GetClangASTType(false).GetByteSize(); } @@ -145,7 +149,7 @@ SBType::IsPointerType() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsPointerType(); + return m_opaque_sp->GetClangASTType(true).IsPointerType(); } bool @@ -153,7 +157,7 @@ SBType::IsReferenceType() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsReferenceType(); + return m_opaque_sp->GetClangASTType(true).IsReferenceType(); } SBType @@ -162,7 +166,7 @@ SBType::GetPointerType() if (!IsValid()) return SBType(); - return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointerType())); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointerType()))); } SBType @@ -170,7 +174,7 @@ SBType::GetPointeeType() { if (!IsValid()) return SBType(); - return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointeeType())); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointeeType()))); } SBType @@ -178,7 +182,7 @@ SBType::GetReferenceType() { if (!IsValid()) return SBType(); - return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetLValueReferenceType())); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetReferenceType()))); } SBType @@ -186,7 +190,7 @@ SBType::GetDereferencedType() { if (!IsValid()) return SBType(); - return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetNonReferenceType())); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetDereferencedType()))); } bool @@ -194,7 +198,7 @@ SBType::IsFunctionType () { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsFunctionType(); + return m_opaque_sp->GetClangASTType(true).IsFunctionType(); } bool @@ -202,7 +206,7 @@ SBType::IsPolymorphicClass () { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsPolymorphicClass(); + return m_opaque_sp->GetClangASTType(true).IsPolymorphicClass(); } @@ -212,7 +216,7 @@ SBType::GetFunctionReturnType () { if (IsValid()) { - ClangASTType return_clang_type (m_opaque_sp->GetClangASTType().GetFunctionReturnType()); + ClangASTType return_clang_type (m_opaque_sp->GetClangASTType(true).GetFunctionReturnType()); if (return_clang_type.IsValid()) return SBType(return_clang_type); } @@ -225,13 +229,13 @@ SBType::GetFunctionArgumentTypes () SBTypeList sb_type_list; if (IsValid()) { - QualType qual_type(QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType())); - const FunctionProtoType* func = dyn_cast(qual_type.getTypePtr()); - if (func) + ClangASTType func_type(m_opaque_sp->GetClangASTType(true)); + size_t count = func_type.GetNumberOfFunctionArguments(); + for (size_t i = 0; + i < count; + i++) { - const uint32_t num_args = func->getNumArgs(); - for (uint32_t i=0; iGetASTContext(), func->getArgType(i).getAsOpaquePtr()))); + sb_type_list.Append(SBType(func_type.GetFunctionArgumentAtIndex(i))); } } return sb_type_list; @@ -242,14 +246,14 @@ SBType::GetUnqualifiedType() { if (!IsValid()) return SBType(); - return SBType(m_opaque_sp->GetClangASTType().GetFullyUnqualifiedType()); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetUnqualifiedType()))); } lldb::SBType SBType::GetCanonicalType() { if (IsValid()) - return SBType(m_opaque_sp->GetClangASTType().GetCanonicalType()); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetCanonicalType()))); return SBType(); } @@ -258,7 +262,7 @@ lldb::BasicType SBType::GetBasicType() { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetBasicTypeEnumeration (); + return m_opaque_sp->GetClangASTType(false).GetBasicTypeEnumeration (); return eBasicTypeInvalid; } @@ -266,7 +270,7 @@ SBType SBType::GetBasicType(lldb::BasicType basic_type) { if (IsValid()) - return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetASTContext(), basic_type)); + return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetClangASTContext(false), basic_type)); return SBType(); } @@ -274,7 +278,7 @@ uint32_t SBType::GetNumberOfDirectBaseClasses () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetNumDirectBaseClasses(); + return m_opaque_sp->GetClangASTType(true).GetNumDirectBaseClasses(); return 0; } @@ -282,7 +286,7 @@ uint32_t SBType::GetNumberOfVirtualBaseClasses () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetNumVirtualBaseClasses(); + return m_opaque_sp->GetClangASTType(true).GetNumVirtualBaseClasses(); return 0; } @@ -290,7 +294,7 @@ uint32_t SBType::GetNumberOfFields () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetNumFields(); + return m_opaque_sp->GetClangASTType(false).GetNumFields(); return 0; } @@ -317,7 +321,7 @@ SBType::GetDirectBaseClassAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - ClangASTType this_type (m_opaque_sp->GetClangASTType ()); + ClangASTType this_type (m_opaque_sp->GetClangASTType (true)); if (this_type.IsValid()) { uint32_t bit_offset = 0; @@ -338,7 +342,7 @@ SBType::GetVirtualBaseClassAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - ClangASTType this_type (m_opaque_sp->GetClangASTType ()); + ClangASTType this_type (m_opaque_sp->GetClangASTType (true)); if (this_type.IsValid()) { uint32_t bit_offset = 0; @@ -358,7 +362,7 @@ SBType::GetFieldAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - ClangASTType this_type (m_opaque_sp->GetClangASTType ()); + ClangASTType this_type (m_opaque_sp->GetClangASTType (false)); if (this_type.IsValid()) { uint64_t bit_offset = 0; @@ -391,7 +395,7 @@ SBType::IsTypeComplete() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsCompleteType(); + return m_opaque_sp->GetClangASTType(false).IsCompleteType(); } const char* @@ -399,14 +403,14 @@ SBType::GetName() { if (!IsValid()) return ""; - return m_opaque_sp->GetClangASTType().GetConstTypeName().GetCString(); + return m_opaque_sp->GetName().GetCString(); } lldb::TypeClass SBType::GetTypeClass () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetTypeClass(); + return m_opaque_sp->GetClangASTType(false).GetTypeClass(); return lldb::eTypeClassInvalid; } @@ -414,7 +418,7 @@ uint32_t SBType::GetNumberOfTemplateArguments () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetNumTemplateArguments(); + return m_opaque_sp->GetClangASTType(false).GetNumTemplateArguments(); return 0; } @@ -424,7 +428,7 @@ SBType::GetTemplateArgumentType (uint32_t idx) if (IsValid()) { TemplateArgumentKind kind = eTemplateArgumentKindNull; - ClangASTType template_arg_type = m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind); + ClangASTType template_arg_type = m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind); if (template_arg_type.IsValid()) return SBType(template_arg_type); } @@ -437,7 +441,7 @@ SBType::GetTemplateArgumentKind (uint32_t idx) { TemplateArgumentKind kind = eTemplateArgumentKindNull; if (IsValid()) - m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind); + m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind); return kind; } diff --git a/lldb/source/API/SBTypeNameSpecifier.cpp b/lldb/source/API/SBTypeNameSpecifier.cpp index d417499ecbd3..3d03c6a0c539 100644 --- a/lldb/source/API/SBTypeNameSpecifier.cpp +++ b/lldb/source/API/SBTypeNameSpecifier.cpp @@ -36,7 +36,7 @@ SBTypeNameSpecifier::SBTypeNameSpecifier (SBType type) : m_opaque_sp() { if (type.IsValid()) - m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetClangASTType())); + m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetClangASTType(true))); } SBTypeNameSpecifier::SBTypeNameSpecifier (const lldb::SBTypeNameSpecifier &rhs) : diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index 408d51cc54b5..68cd56f29989 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -473,7 +473,7 @@ SBValue::GetType() TypeImplSP type_sp; if (value_sp) { - type_sp.reset (new TypeImpl(value_sp->GetClangType())); + type_sp.reset (new TypeImpl(value_sp->GetTypeImpl())); sb_type.SetSP(type_sp); } if (log) @@ -671,7 +671,7 @@ SBValue::CreateChildAtOffset (const char *name, uint32_t offset, SBType type) TypeImplSP type_sp (type.GetSP()); if (type.IsValid()) { - sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name); + sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(false), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name); } } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -696,7 +696,7 @@ SBValue::Cast (SBType type) lldb::ValueObjectSP value_sp(GetSP(locker)); TypeImplSP type_sp (type.GetSP()); if (value_sp && type_sp) - sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType()),GetPreferDynamicValue(),GetPreferSyntheticValue()); + sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType(false)),GetPreferDynamicValue(),GetPreferSyntheticValue()); return sb_value; } @@ -761,7 +761,7 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType s lldb::TypeImplSP type_impl_sp (sb_type.GetSP()); if (value_sp && type_impl_sp) { - ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType().GetPointerType ()); + ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType(false).GetPointerType ()); if (pointer_ast_type) { lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t))); @@ -808,7 +808,7 @@ SBValue::CreateValueFromData (const char* name, SBData data, SBType type) ExecutionContext exe_ctx (value_sp->GetExecutionContextRef()); new_value_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - type.m_opaque_sp->GetClangASTType(), + type.m_opaque_sp->GetClangASTType(false), ConstString(name), *data.m_opaque_sp, LLDB_INVALID_ADDRESS); diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index c84bdf60062c..e1f3b8a64700 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -359,6 +359,12 @@ ValueObject::GetClangType () return MaybeCalculateCompleteType(); } +TypeImpl +ValueObject::GetTypeImpl () +{ + return TypeImpl(GetClangType()); +} + DataExtractor & ValueObject::GetDataExtractor () { diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp index 977cc4cd3132..64f9750434d5 100644 --- a/lldb/source/Core/ValueObjectDynamicValue.cpp +++ b/lldb/source/Core/ValueObjectDynamicValue.cpp @@ -52,10 +52,15 @@ ValueObjectDynamicValue::~ValueObjectDynamicValue() ClangASTType ValueObjectDynamicValue::GetClangTypeImpl () { - if (m_dynamic_type_info.HasTypeSP()) - return m_value.GetClangType(); - else - return m_parent->GetClangType(); + const bool success = UpdateValueIfNeeded(false); + if (success) + { + if (m_dynamic_type_info.HasType()) + return m_value.GetClangType(); + else + return m_parent->GetClangType(); + } + return m_parent->GetClangType(); } ConstString @@ -64,7 +69,7 @@ ValueObjectDynamicValue::GetTypeName() const bool success = UpdateValueIfNeeded(false); if (success) { - if (m_dynamic_type_info.HasTypeSP()) + if (m_dynamic_type_info.HasType()) return GetClangType().GetConstTypeName(); if (m_dynamic_type_info.HasName()) return m_dynamic_type_info.GetName(); @@ -72,13 +77,24 @@ ValueObjectDynamicValue::GetTypeName() return m_parent->GetTypeName(); } +TypeImpl +ValueObjectDynamicValue::GetTypeImpl () +{ + const bool success = UpdateValueIfNeeded(false); + if (success) + { + return m_type_impl; + } + return m_parent->GetTypeImpl(); +} + ConstString ValueObjectDynamicValue::GetQualifiedTypeName() { const bool success = UpdateValueIfNeeded(false); if (success) { - if (m_dynamic_type_info.HasTypeSP()) + if (m_dynamic_type_info.HasType()) return GetClangType().GetConstQualifiedTypeName (); if (m_dynamic_type_info.HasName()) return m_dynamic_type_info.GetName(); @@ -90,7 +106,7 @@ size_t ValueObjectDynamicValue::CalculateNumChildren() { const bool success = UpdateValueIfNeeded(false); - if (success && m_dynamic_type_info.HasTypeSP()) + if (success && m_dynamic_type_info.HasType()) return GetClangType().GetNumChildren (true); else return m_parent->GetNumChildren(); @@ -100,7 +116,7 @@ uint64_t ValueObjectDynamicValue::GetByteSize() { const bool success = UpdateValueIfNeeded(false); - if (success && m_dynamic_type_info.HasTypeSP()) + if (success && m_dynamic_type_info.HasType()) return m_value.GetValueByteSize(NULL); else return m_parent->GetByteSize(); @@ -112,6 +128,38 @@ ValueObjectDynamicValue::GetValueType() const return m_parent->GetValueType(); } + +static TypeAndOrName +FixupTypeAndOrName (const TypeAndOrName& type_andor_name, + ValueObject& parent) +{ + TypeAndOrName ret(type_andor_name); + if (type_andor_name.HasType()) + { + // The type will always be the type of the dynamic object. If our parent's type was a pointer, + // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type + // should be okay... + ClangASTType orig_type = type_andor_name.GetClangASTType(); + ClangASTType corrected_type = orig_type; + if (parent.IsPointerType()) + corrected_type = orig_type.GetPointerType (); + else if (parent.IsPointerOrReferenceType()) + corrected_type = orig_type.GetLValueReferenceType (); + ret.SetClangASTType(corrected_type); + } + else /*if (m_dynamic_type_info.HasName())*/ + { + // If we are here we need to adjust our dynamic type name to include the correct & or * symbol + std::string corrected_name (type_andor_name.GetName().GetCString()); + if (parent.IsPointerType()) + corrected_name.append(" *"); + else if (parent.IsPointerOrReferenceType()) + corrected_name.append(" &"); + ret.SetName(corrected_name.c_str()); + } + return ret; +} + bool ValueObjectDynamicValue::UpdateValue () { @@ -176,6 +224,14 @@ ValueObjectDynamicValue::UpdateValue () // don't... m_update_point.SetUpdated(); + + // if the runtime only vended a ClangASTType, then we have an hollow type that we don't want to use + // but we save it for the TypeImpl, which can still use an hollow type for some questions + if (found_dynamic_type && class_type_or_name.HasType() && !class_type_or_name.HasTypeSP()) + { + m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); + class_type_or_name.SetClangASTType(ClangASTType()); + } // If we don't have a dynamic type, then make ourselves just a echo of our parent. // Or we could return false, and make ourselves an echo of our parent? @@ -224,33 +280,10 @@ ValueObjectDynamicValue::UpdateValue () m_value.GetScalar() = load_address; } - ClangASTType corrected_type; - if (m_dynamic_type_info.HasTypeSP()) - { - // The type will always be the type of the dynamic object. If our parent's type was a pointer, - // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type - // should be okay... - ClangASTType orig_type = m_dynamic_type_info.GetTypeSP()->GetClangForwardType(); - corrected_type = orig_type; - if (m_parent->IsPointerType()) - corrected_type = orig_type.GetPointerType (); - else if (m_parent->IsPointerOrReferenceType()) - corrected_type = orig_type.GetLValueReferenceType (); - } - else /*if (m_dynamic_type_info.HasName())*/ - { - // If we are here we need to adjust our dynamic type name to include the correct & or * symbol - std::string type_name_buf (m_dynamic_type_info.GetName().GetCString()); - if (m_parent->IsPointerType()) - type_name_buf.append(" *"); - else if (m_parent->IsPointerOrReferenceType()) - type_name_buf.append(" &"); - corrected_type = m_parent->GetClangType(); - m_dynamic_type_info.SetName(type_name_buf.c_str()); - } + m_dynamic_type_info = FixupTypeAndOrName(m_dynamic_type_info, *m_parent); //m_value.SetContext (Value::eContextTypeClangType, corrected_type); - m_value.SetClangType (corrected_type); + m_value.SetClangType (m_dynamic_type_info.GetClangASTType()); // Our address is the location of the dynamic type stored in memory. It isn't a load address, // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us... diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 9012dd67281a..e16c530329cc 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -393,6 +393,17 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value, objc_class_sp->SetType (type_sp); class_type_or_name.SetTypeSP (type_sp); } + else + { + // try to go for a ClangASTType at least + TypeVendor* vendor = GetTypeVendor(); + if (vendor) + { + std::vector types; + if (vendor->FindTypes(class_name, false, 1, types) && types.size() && types.at(0).IsValid()) + class_type_or_name.SetClangASTType(types.at(0)); + } + } } } } diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index da445d83e79f..b0413edffdde 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -385,6 +385,34 @@ ClangASTType::IsFunctionType (bool *is_variadic_ptr) const return false; } +size_t +ClangASTType::GetNumberOfFunctionArguments () const +{ + if (IsValid()) + { + QualType qual_type (GetCanonicalQualType()); + const FunctionProtoType* func = dyn_cast(qual_type.getTypePtr()); + if (func) + return func->getNumArgs(); + } + return 0; +} + +ClangASTType +ClangASTType::GetFunctionArgumentAtIndex (const size_t index) +{ + if (IsValid()) + { + QualType qual_type (GetCanonicalQualType()); + const FunctionProtoType* func = dyn_cast(qual_type.getTypePtr()); + if (func) + { + if (index < func->getNumArgs()) + return ClangASTType(m_ast, func->getArgType(index).getAsOpaquePtr()); + } + } + return ClangASTType(); +} bool ClangASTType::IsFunctionPointerType () const diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 0af2359e1dad..81aa44fc987e 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -798,12 +798,12 @@ Type::GetTypeScopeAndBasename (const char* &name_cstr, -TypeAndOrName::TypeAndOrName () : m_type_sp(), m_type_name() +TypeAndOrName::TypeAndOrName () : m_type_pair(), m_type_name() { } -TypeAndOrName::TypeAndOrName (TypeSP &in_type_sp) : m_type_sp(in_type_sp) +TypeAndOrName::TypeAndOrName (TypeSP &in_type_sp) : m_type_pair(in_type_sp) { if (in_type_sp) m_type_name = in_type_sp->GetName(); @@ -813,7 +813,7 @@ TypeAndOrName::TypeAndOrName (const char *in_type_str) : m_type_name(in_type_str { } -TypeAndOrName::TypeAndOrName (const TypeAndOrName &rhs) : m_type_sp (rhs.m_type_sp), m_type_name (rhs.m_type_name) +TypeAndOrName::TypeAndOrName (const TypeAndOrName &rhs) : m_type_pair (rhs.m_type_pair), m_type_name (rhs.m_type_name) { } @@ -828,7 +828,7 @@ TypeAndOrName::operator= (const TypeAndOrName &rhs) if (this != &rhs) { m_type_name = rhs.m_type_name; - m_type_sp = rhs.m_type_sp; + m_type_pair = rhs.m_type_pair; } return *this; } @@ -836,7 +836,7 @@ TypeAndOrName::operator= (const TypeAndOrName &rhs) bool TypeAndOrName::operator==(const TypeAndOrName &other) const { - if (m_type_sp != other.m_type_sp) + if (m_type_pair != other.m_type_pair) return false; if (m_type_name != other.m_type_name) return false; @@ -846,7 +846,7 @@ TypeAndOrName::operator==(const TypeAndOrName &other) const bool TypeAndOrName::operator!=(const TypeAndOrName &other) const { - if (m_type_sp != other.m_type_sp) + if (m_type_pair != other.m_type_pair) return true; if (m_type_name != other.m_type_name) return true; @@ -856,8 +856,8 @@ TypeAndOrName::operator!=(const TypeAndOrName &other) const ConstString TypeAndOrName::GetName () const { - if (m_type_sp) - return m_type_sp->GetName(); + if (m_type_pair) + return m_type_pair.GetName(); else return m_type_name; } @@ -877,15 +877,23 @@ TypeAndOrName::SetName (const char *type_name_cstr) void TypeAndOrName::SetTypeSP (lldb::TypeSP type_sp) { - m_type_sp = type_sp; - if (type_sp) - m_type_name = type_sp->GetName(); + m_type_pair.SetType(type_sp); + if (m_type_pair) + m_type_name = m_type_pair.GetName(); +} + +void +TypeAndOrName::SetClangASTType (ClangASTType clang_type) +{ + m_type_pair.SetType(clang_type); + if (m_type_pair) + m_type_name = m_type_pair.GetName(); } bool -TypeAndOrName::IsEmpty() +TypeAndOrName::IsEmpty() const { - if (m_type_name || m_type_sp) + if ((bool)m_type_name || (bool)m_type_pair) return false; else return true; @@ -895,96 +903,247 @@ void TypeAndOrName::Clear () { m_type_name.Clear(); - m_type_sp.reset(); + m_type_pair.Clear(); } bool -TypeAndOrName::HasName () +TypeAndOrName::HasName () const { return (bool)m_type_name; } bool -TypeAndOrName::HasTypeSP () +TypeAndOrName::HasTypeSP () const { - return m_type_sp.get() != NULL; + return m_type_pair.GetTypeSP().get() != nullptr; } -TypeImpl::TypeImpl(const lldb_private::ClangASTType& clang_ast_type) : - m_clang_ast_type(clang_ast_type), - m_type_sp() +bool +TypeAndOrName::HasClangASTType () const +{ + return m_type_pair.GetClangASTType().IsValid(); +} + + +TypeImpl::TypeImpl() : +m_static_type(), +m_dynamic_type() { } -TypeImpl::TypeImpl(const lldb::TypeSP& type) : - m_clang_ast_type(type->GetClangForwardType()), - m_type_sp(type) +TypeImpl::TypeImpl(const TypeImpl& rhs) : +m_static_type(rhs.m_static_type), +m_dynamic_type(rhs.m_dynamic_type) +{ +} + +TypeImpl::TypeImpl (lldb::TypeSP type_sp) : +m_static_type(type_sp), +m_dynamic_type() +{ +} + +TypeImpl::TypeImpl (ClangASTType clang_type) : +m_static_type(clang_type), +m_dynamic_type() +{ +} + +TypeImpl::TypeImpl (lldb::TypeSP type_sp, ClangASTType dynamic) : +m_static_type (type_sp), +m_dynamic_type(dynamic) +{ +} + +TypeImpl::TypeImpl (ClangASTType clang_type, ClangASTType dynamic) : +m_static_type (clang_type), +m_dynamic_type(dynamic) +{ +} + +TypeImpl::TypeImpl (TypePair pair, ClangASTType dynamic) : +m_static_type (pair), +m_dynamic_type(dynamic) { } void -TypeImpl::SetType (const lldb::TypeSP &type_sp) +TypeImpl::SetType (lldb::TypeSP type_sp) { - if (type_sp) - { - m_clang_ast_type = type_sp->GetClangForwardType(); - m_type_sp = type_sp; - } - else - { - m_clang_ast_type.Clear(); - m_type_sp.reset(); - } + m_static_type.SetType(type_sp); +} + +void +TypeImpl::SetType (ClangASTType clang_type) +{ + m_static_type.SetType (clang_type); +} + +void +TypeImpl::SetType (lldb::TypeSP type_sp, ClangASTType dynamic) +{ + m_static_type.SetType (type_sp); + m_dynamic_type = dynamic; +} + +void +TypeImpl::SetType (ClangASTType clang_type, ClangASTType dynamic) +{ + m_static_type.SetType (clang_type); + m_dynamic_type = dynamic; +} + +void +TypeImpl::SetType (TypePair pair, ClangASTType dynamic) +{ + m_static_type = pair; + m_dynamic_type = dynamic; } TypeImpl& TypeImpl::operator = (const TypeImpl& rhs) { - if (*this != rhs) + if (rhs != *this) { - m_clang_ast_type = rhs.m_clang_ast_type; - m_type_sp = rhs.m_type_sp; + m_static_type = rhs.m_static_type; + m_dynamic_type = rhs.m_dynamic_type; } return *this; } -clang::ASTContext* -TypeImpl::GetASTContext() +bool +TypeImpl::operator == (const TypeImpl& rhs) const { - if (!IsValid()) - return NULL; - - return m_clang_ast_type.GetASTContext(); -} - -lldb::clang_type_t -TypeImpl::GetOpaqueQualType() -{ - if (!IsValid()) - return NULL; - - return m_clang_ast_type.GetOpaqueQualType(); + return m_static_type == rhs.m_static_type && + m_dynamic_type == rhs.m_dynamic_type; } bool -TypeImpl::GetDescription (lldb_private::Stream &strm, - lldb::DescriptionLevel description_level) +TypeImpl::operator != (const TypeImpl& rhs) const { - if (m_clang_ast_type.IsValid()) - { - m_clang_ast_type.DumpTypeDescription (&strm); - } - else - { - strm.PutCString ("No value"); - } - return true; + return m_static_type != rhs.m_static_type || + m_dynamic_type != rhs.m_dynamic_type; +} + +bool +TypeImpl::IsValid() const +{ + // just a name is not valid + return m_static_type.IsValid() || m_dynamic_type.IsValid(); +} + +TypeImpl::operator bool () const +{ + return IsValid(); +} + +void +TypeImpl::Clear() +{ + m_static_type.Clear(); + m_dynamic_type.Clear(); } ConstString -TypeImpl::GetName () +TypeImpl::GetName () const { - if (m_clang_ast_type.IsValid()) - return m_clang_ast_type.GetConstTypeName(); - return ConstString(); + if (m_dynamic_type) + return m_dynamic_type.GetTypeName(); + return m_static_type.GetName (); +} + +TypeImpl +TypeImpl::GetPointerType () const +{ + if (m_dynamic_type.IsValid()) + { + return TypeImpl(m_static_type, m_dynamic_type.GetPointerType()); + } + return TypeImpl(m_static_type.GetPointerType()); +} + +TypeImpl +TypeImpl::GetPointeeType () const +{ + if (m_dynamic_type.IsValid()) + { + return TypeImpl(m_static_type, m_dynamic_type.GetPointeeType()); + } + return TypeImpl(m_static_type.GetPointeeType()); +} + +TypeImpl +TypeImpl::GetReferenceType () const +{ + if (m_dynamic_type.IsValid()) + { + return TypeImpl(m_static_type, m_dynamic_type.GetLValueReferenceType()); + } + return TypeImpl(m_static_type.GetReferenceType()); +} + +TypeImpl +TypeImpl::GetDereferencedType () const +{ + if (m_dynamic_type.IsValid()) + { + return TypeImpl(m_static_type, m_dynamic_type.GetNonReferenceType()); + } + return TypeImpl(m_static_type.GetDereferencedType()); +} + +TypeImpl +TypeImpl::GetUnqualifiedType() const +{ + if (m_dynamic_type.IsValid()) + { + return TypeImpl(m_static_type, m_dynamic_type.GetFullyUnqualifiedType()); + } + return TypeImpl(m_static_type.GetUnqualifiedType()); +} + +TypeImpl +TypeImpl::GetCanonicalType() const +{ + if (m_dynamic_type.IsValid()) + { + return TypeImpl(m_static_type, m_dynamic_type.GetCanonicalType()); + } + return TypeImpl(m_static_type.GetCanonicalType()); +} + +ClangASTType +TypeImpl::GetClangASTType (bool prefer_dynamic) +{ + if (prefer_dynamic) + { + if (m_dynamic_type.IsValid()) + return m_dynamic_type; + } + return m_static_type.GetClangASTType(); +} + +clang::ASTContext * +TypeImpl::GetClangASTContext (bool prefer_dynamic) +{ + if (prefer_dynamic) + { + if (m_dynamic_type.IsValid()) + return m_dynamic_type.GetASTContext(); + } + return m_static_type.GetClangASTContext(); +} + +bool +TypeImpl::GetDescription (lldb_private::Stream &strm, + lldb::DescriptionLevel description_level) +{ + if (m_dynamic_type.IsValid()) + { + strm.Printf("Dynamic:\n"); + m_dynamic_type.DumpTypeDescription(&strm); + strm.Printf("\nStatic:\n"); + } + m_static_type.GetClangASTType().DumpTypeDescription(&strm); + return true; } diff --git a/lldb/test/dotest.py b/lldb/test/dotest.py index 96a35b9f1356..bc2b068d5c89 100755 --- a/lldb/test/dotest.py +++ b/lldb/test/dotest.py @@ -97,7 +97,8 @@ validCategories = { 'objc':'Tests related to the Objective-C programming language support', 'pyapi':'Tests related to the Python API', 'basic_process': 'Basic process execution sniff tests.', -'cmdline' : 'Tests related to the LLDB command-line interface' +'cmdline' : 'Tests related to the LLDB command-line interface', +'dyntype' : 'Tests related to dynamic type support' } # The test suite. diff --git a/lldb/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py b/lldb/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py index 935673cb7ad9..30a76928ea8b 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py @@ -178,7 +178,7 @@ class AdvDataFormatterTestCase(TestBase): # if the summary has an error, we still display the value self.expect("frame variable couple --summary-string \"${*var.sp.foo[0-2]\"", - substrs = ['(Couple) couple = (sp = SimpleWithPointers @ 0x', 's = 0x',')']) + substrs = ['(Couple) couple = {','x = 0x','y = 0x','z = 0x','s = 0x']) self.runCmd("type summary add --summary-string \"${*var.sp.x[0-2]} are low bits of integer ${*var.sp.x}. If I pretend it is an array I get ${var.sp.x[0-5]}\" Couple") diff --git a/lldb/test/lang/objc/blocks/TestObjCIvarsInBlocks.py b/lldb/test/lang/objc/blocks/TestObjCIvarsInBlocks.py index 955bd6dd9022..0213c46b435f 100644 --- a/lldb/test/lang/objc/blocks/TestObjCIvarsInBlocks.py +++ b/lldb/test/lang/objc/blocks/TestObjCIvarsInBlocks.py @@ -112,7 +112,7 @@ class TestObjCIvarsInBlocks(TestBase): self.assertTrue (expr, "Successfully got a local variable in a block in a class method.") ret_value_signed = expr.GetValueAsSigned (error) - print 'ret_value_signed = %i' % (ret_value_signed) + # print 'ret_value_signed = %i' % (ret_value_signed) self.assertTrue (ret_value_signed == 5, "The local variable in the block was what we expected.") if __name__ == '__main__': diff --git a/lldb/test/lang/objc/objc-dyn-sbtype/.categories b/lldb/test/lang/objc/objc-dyn-sbtype/.categories new file mode 100644 index 000000000000..9526bab96fbb --- /dev/null +++ b/lldb/test/lang/objc/objc-dyn-sbtype/.categories @@ -0,0 +1 @@ +dyntype diff --git a/lldb/test/lang/objc/objc-dyn-sbtype/Makefile b/lldb/test/lang/objc/objc-dyn-sbtype/Makefile new file mode 100644 index 000000000000..72b89bd59db0 --- /dev/null +++ b/lldb/test/lang/objc/objc-dyn-sbtype/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation -framework Cocoa diff --git a/lldb/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py b/lldb/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py new file mode 100644 index 000000000000..9dae1e45688a --- /dev/null +++ b/lldb/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py @@ -0,0 +1,65 @@ +""" +Test that we are able to properly report a usable dynamic type for NSImage +""" + +import os, time +import unittest2 +import lldb +from lldbtest import * +import lldbutil + +@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") +class ObjCDynamicSBTypeTestCase(TestBase): + + mydir = os.path.join("lang", "objc", "objc-dyn-sbtype") + + @dsym_test + @skipIfi386 + def test_nsimage_dyn_with_dsym(self): + """Test that we are able to properly report a usable dynamic type for NSImage.""" + d = {'EXE': self.exe_name} + self.buildDsym(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.nsimage_dyn(self.exe_name) + + @dwarf_test + @skipIfi386 + def test_nsimage_dyn_with_dwarf(self): + """Test that we are able to properly report a usable dynamic type for NSImage.""" + d = {'EXE': self.exe_name} + self.buildDwarf(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.nsimage_dyn(self.exe_name) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # We'll use the test method name as the exe_name. + self.exe_name = self.testMethodName + # Find the line number to break inside main(). + self.main_source = "main.m" + self.line = line_number(self.main_source, '// Set breakpoint here.') + + def nsimage_dyn(self, exe_name): + """Test that we are able to properly report a usable dynamic type for NSImage.""" + exe = os.path.join(os.getcwd(), exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, self.main_source, self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + image = self.frame().EvaluateExpression("(id)image",lldb.eDynamicCanRunTarget) + self.assertTrue(image.GetTypeName() == "NSImage *", "The SBValue is properly type-named") + image_type = image.GetType() + self.assertTrue(image_type.GetName() == "NSImage *", "The dynamic SBType is for the correct type") + image_pointee_type = image_type.GetPointeeType() + self.assertTrue(image_pointee_type.GetName() == "NSImage", "The dynamic type figures out its pointee type just fine") + self.assertTrue(image_pointee_type.GetDirectBaseClassAtIndex(0).GetName() == "NSObject", "The dynamic type can go back to its base class") + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/lang/objc/objc-dyn-sbtype/main.m b/lldb/test/lang/objc/objc-dyn-sbtype/main.m new file mode 100644 index 000000000000..de757bc40e5a --- /dev/null +++ b/lldb/test/lang/objc/objc-dyn-sbtype/main.m @@ -0,0 +1,13 @@ +#import +#import + +int main (int argc, char const *argv[]) +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + NSSize size = {10,10}; + NSImage *image = [[NSImage alloc] initWithSize:size]; + [pool release]; // Set breakpoint here. + return 0; +} +