Index: include/lldb/Expression/ClangExpressionParser.h =================================================================== --- include/lldb/Expression/ClangExpressionParser.h +++ include/lldb/Expression/ClangExpressionParser.h @@ -149,6 +149,7 @@ class LLDBPreprocessorCallbacks; LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor encounters module imports + std::unique_ptr m_ast_context; }; } Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -30,12 +30,13 @@ #include "lldb/Core/ClangForward.h" #include "lldb/Core/ConstString.h" #include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/TypeSystem.h" namespace lldb_private { class Declaration; -class ClangASTContext +class ClangASTContext : public TypeSystem { public: typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); @@ -53,7 +54,9 @@ clang::ASTContext * getASTContext(); - + + void setASTContext(clang::ASTContext* ast_ctx); + clang::Builtin::Context * getBuiltinContext(); @@ -180,6 +183,16 @@ return ClangASTContext::GetUnknownAnyType(getASTContext()); } + + static clang::DeclContext * + GetDeclContextForType (clang::QualType type); + + static clang::DeclContext * + GetDeclContextForType (const ClangASTType& type) + { + return GetDeclContextForType(GetQualType(type)); + } + uint32_t GetPointerByteSize (); @@ -268,11 +281,6 @@ GetNumBaseClasses (const clang::CXXRecordDecl *cxx_record_decl, bool omit_empty_base_classes); - static uint32_t - GetIndexForRecordBase (const clang::RecordDecl *record_decl, - const clang::CXXBaseSpecifier *base_spec, - bool omit_empty_base_classes); - ClangASTType CreateRecordType (clang::DeclContext *decl_ctx, lldb::AccessType access_type, @@ -361,6 +369,17 @@ bool isForwardDecl, bool isInternal, ClangASTMetadata *metadata = NULL); + + bool + SetTagTypeKind (clang::QualType type, int kind) const; + + bool + SetDefaultAccessForRecordFields (clang::RecordDecl* record_decl, + int default_accessibility, + int *assigned_accessibilities, + size_t num_assigned_accessibilities); + + // Returns a mask containing bits from the ClangASTContext::eTypeXXX enumerations @@ -471,7 +490,538 @@ static ClangASTType GetFloatTypeFromBitSize (clang::ASTContext *ast, size_t bit_size); + + //------------------------------------------------------------------ + // TypeSystem methods + //------------------------------------------------------------------ + + ClangASTContext* + AsClangASTContext() + { + return this; + } + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + bool + IsArrayType (void* type, + ClangASTType *element_type, + uint64_t *size, + bool *is_incomplete); + + bool + IsVectorType (void* type, + ClangASTType *element_type, + uint64_t *size); + + bool + IsAggregateType (void* type); + + bool + IsBeingDefined (void* type); + + bool + IsCharType (void* type); + + bool + IsCompleteType (void* type); + + bool + IsConst(void* type); + + bool + IsCStringType (void* type, uint32_t &length); + + static bool + IsCXXClassType (const ClangASTType& type); + + bool + IsDefined(void* type); + + bool + IsFloatingPointType (void* type, uint32_t &count, bool &is_complex); + + bool + IsFunctionType (void* type, bool *is_variadic_ptr); + + uint32_t + IsHomogeneousAggregate (void* type, ClangASTType* base_type_ptr); + + size_t + GetNumberOfFunctionArguments (void* type); + + ClangASTType + GetFunctionArgumentAtIndex (void* type, const size_t index); + + bool + IsFunctionPointerType (void* type); + + bool + IsIntegerType (void* type, bool &is_signed); + + static bool + IsObjCClassType (const ClangASTType& type); + + static bool + IsObjCClassTypeAndHasIVars (const ClangASTType& type, bool check_superclass); + + static bool + IsObjCObjectOrInterfaceType (const ClangASTType& type); + + static bool + IsObjCObjectPointerType (const ClangASTType& type, ClangASTType *target_type = NULL); + + bool + IsPolymorphicClass (void* type); + + bool + IsPossibleDynamicType (void* type, + ClangASTType *target_type, // Can pass NULL + bool check_cplusplus, + bool check_objc); + + bool + IsRuntimeGeneratedType (void* type); + + bool + IsPointerType (void* type, ClangASTType *pointee_type); + + bool + IsPointerOrReferenceType (void* type, ClangASTType *pointee_type); + + bool + IsReferenceType (void* type, ClangASTType *pointee_type, bool* is_rvalue); + + bool + IsScalarType (void* type); + + bool + IsTypedefType (void* type); + + bool + IsVoidType (void* type); + + static bool + GetCXXClassName (const ClangASTType& type, std::string &class_name); + + static bool + GetObjCClassName (const ClangASTType& type, std::string &class_name); + + + //---------------------------------------------------------------------- + // Type Completion + //---------------------------------------------------------------------- + + bool + GetCompleteType (void* type); + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + + ConstString + GetTypeName (void* type); + + uint32_t + GetTypeInfo (void* type, ClangASTType *pointee_or_element_clang_type); + + lldb::LanguageType + GetMinimumLanguage (void* type); + + lldb::TypeClass + GetTypeClass (void* type); + + unsigned + GetTypeQualifiers(void* type); + + //---------------------------------------------------------------------- + // Creating related types + //---------------------------------------------------------------------- + + static ClangASTType + AddConstModifier (const ClangASTType& type); + + static ClangASTType + AddRestrictModifier (const ClangASTType& type); + + static ClangASTType + AddVolatileModifier (const ClangASTType& type); + + // Using the current type, create a new typedef to that type using "typedef_name" + // as the name and "decl_ctx" as the decl context. + static ClangASTType + CreateTypedefType (const ClangASTType& type, + const char *typedef_name, + clang::DeclContext *decl_ctx); + + ClangASTType + GetArrayElementType (void* type, uint64_t *stride); + + ClangASTType + GetCanonicalType (void* type); + + ClangASTType + GetFullyUnqualifiedType (void* type); + + // Returns -1 if this isn't a function of if the function doesn't have a prototype + // Returns a value >= 0 if there is a prototype. + int + GetFunctionArgumentCount (void* type); + + ClangASTType + GetFunctionArgumentTypeAtIndex (void* type, size_t idx); + + ClangASTType + GetFunctionReturnType (void* type); + + size_t + GetNumMemberFunctions (void* type); + + TypeMemberFunctionImpl + GetMemberFunctionAtIndex (void* type, size_t idx); + + static ClangASTType + GetLValueReferenceType (const ClangASTType& type); + + ClangASTType + GetNonReferenceType (void* type); + + ClangASTType + GetPointeeType (void* type); + + ClangASTType + GetPointerType (void* type); + + static ClangASTType + GetRValueReferenceType (const ClangASTType& type); + + // If the current object represents a typedef type, get the underlying type + ClangASTType + GetTypedefedType (void* type); + + static ClangASTType + RemoveFastQualifiers (const ClangASTType& type); + + //---------------------------------------------------------------------- + // Create related types using the current type's AST + //---------------------------------------------------------------------- + ClangASTType + GetBasicTypeFromAST (void* type, lldb::BasicType basic_type); + + //---------------------------------------------------------------------- + // Exploring the type + //---------------------------------------------------------------------- + + uint64_t + GetByteSize (void *type, ExecutionContextScope *exe_scope) + { + return (GetBitSize (type, exe_scope) + 7) / 8; + } + + uint64_t + GetBitSize (void* type, ExecutionContextScope *exe_scope); + + lldb::Encoding + GetEncoding (void* type, uint64_t &count); + + lldb::Format + GetFormat (void* type); + + size_t + GetTypeBitAlign (void* type); + + uint32_t + GetNumChildren (void* type, bool omit_empty_base_classes); + + lldb::BasicType + GetBasicTypeEnumeration (void* type); + + static lldb::BasicType + GetBasicTypeEnumeration (void* type, const ConstString &name); + + static uint32_t + GetNumDirectBaseClasses (const ClangASTType& type); + + static uint32_t + GetNumVirtualBaseClasses (const ClangASTType& type); + + uint32_t + GetNumFields (void* type); + + static ClangASTType + GetDirectBaseClassAtIndex (const ClangASTType& type, + size_t idx, + uint32_t *bit_offset_ptr); + + static ClangASTType + GetVirtualBaseClassAtIndex (const ClangASTType& type, + size_t idx, + uint32_t *bit_offset_ptr); + + ClangASTType + GetFieldAtIndex (void* type, + size_t idx, + std::string& name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr); + + static uint32_t + GetNumPointeeChildren (clang::QualType type); + + ClangASTType + GetChildClangTypeAtIndex (void* type, + ExecutionContext *exe_ctx, + size_t idx, + bool transparent_pointers, + bool omit_empty_base_classes, + bool ignore_array_bounds, + std::string& child_name, + uint32_t &child_byte_size, + int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, + uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, + bool &child_is_deref_of_parent, + ValueObject *valobj); + + // Lookup a child given a name. This function will match base class names + // and member member names in "clang_type" only, not descendants. + uint32_t + GetIndexOfChildWithName (void* type, + const char *name, + bool omit_empty_base_classes); + + // Lookup a child member given a name. This function will match member names + // only and will descend into "clang_type" children in search for the first + // member in this class, or any base class that matches "name". + // TODO: Return all matches for a given name by returning a vector> + // so we catch all names that match a given child name, not just the first. + size_t + GetIndexOfChildMemberWithName (void* type, + const char *name, + bool omit_empty_base_classes, + std::vector& child_indexes); + + static size_t + GetNumTemplateArguments (const ClangASTType& type); + + static ClangASTType + GetTemplateArgument (const ClangASTType& type, + size_t idx, + lldb::TemplateArgumentKind &kind); + + + //---------------------------------------------------------------------- + // Modifying RecordType + //---------------------------------------------------------------------- + static clang::FieldDecl * + AddFieldToRecordType (const ClangASTType& type, + const char *name, + const ClangASTType &field_type, + lldb::AccessType access, + uint32_t bitfield_bit_size); + + static void + BuildIndirectFields (const ClangASTType& type); + + static void + SetIsPacked (const ClangASTType& type); + + static clang::VarDecl * + AddVariableToRecordType (const ClangASTType& type, + const char *name, + const ClangASTType &var_type, + lldb::AccessType access); + + clang::CXXMethodDecl * + AddMethodToCXXRecordType (void* type, + const char *name, + const ClangASTType &method_type, + lldb::AccessType access, + bool is_virtual, + bool is_static, + bool is_inline, + bool is_explicit, + bool is_attr_used, + bool is_artificial); + + // C++ Base Classes + clang::CXXBaseSpecifier * + CreateBaseClassSpecifier (void* type, + lldb::AccessType access, + bool is_virtual, + bool base_of_class); + + static void + DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, + unsigned num_base_classes); + + bool + SetBaseClassesForClassType (void* type, + clang::CXXBaseSpecifier const * const *base_classes, + unsigned num_base_classes); + + + static bool + SetObjCSuperClass (const ClangASTType& type, + const ClangASTType &superclass_clang_type); + + static bool + AddObjCClassProperty (const ClangASTType& type, + const char *property_name, + const ClangASTType &property_clang_type, + clang::ObjCIvarDecl *ivar_decl, + const char *property_setter_name, + const char *property_getter_name, + uint32_t property_attributes, + ClangASTMetadata *metadata); + + static clang::ObjCMethodDecl * + AddMethodToObjCObjectType (const ClangASTType& type, + const char *name, // the full symbol name as seen in the symbol table (void* type, "-[NString stringWithCString:]") + const ClangASTType &method_clang_type, + lldb::AccessType access, + bool is_artificial); + + bool + SetHasExternalStorage (void* type, bool has_extern); + + + //------------------------------------------------------------------ + // Tag Declarations + //------------------------------------------------------------------ + static bool + StartTagDeclarationDefinition (const ClangASTType &type); + + static bool + CompleteTagDeclarationDefinition (const ClangASTType &type); + + //---------------------------------------------------------------------- + // Modifying Enumeration types + //---------------------------------------------------------------------- + bool + AddEnumerationValueToEnumerationType (void* type, + const ClangASTType &enumerator_qual_type, + const Declaration &decl, + const char *name, + int64_t enum_value, + uint32_t enum_value_bit_size); + + + + ClangASTType + GetEnumerationIntegerType (void* type); + + + //------------------------------------------------------------------ + // Pointers & References + //------------------------------------------------------------------ + + // Call this function using the class type when you want to make a + // member pointer type to pointee_type. + static ClangASTType + CreateMemberPointerType (const ClangASTType& type, const ClangASTType &pointee_type); + + + // Converts "s" to a floating point value and place resulting floating + // point bytes in the "dst" buffer. + size_t + ConvertStringToFloatValue (void* type, + const char *s, + uint8_t *dst, + size_t dst_size); + //---------------------------------------------------------------------- + // Dumping types + //---------------------------------------------------------------------- + void + DumpValue (void* type, + ExecutionContext *exe_ctx, + Stream *s, + lldb::Format format, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool show_types, + bool show_summary, + bool verbose, + uint32_t depth); + + bool + DumpTypeValue (void* type, + Stream *s, + lldb::Format format, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope); + + void + DumpSummary (void* type, + ExecutionContext *exe_ctx, + Stream *s, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size); + + virtual void + DumpTypeDescription (void* type); // Dump to stdout + + void + DumpTypeDescription (void* type, Stream *s); + + static clang::EnumDecl * + GetAsEnumDecl (const ClangASTType& type); + + + static clang::RecordDecl * + GetAsRecordDecl (const ClangASTType& type); + + clang::CXXRecordDecl * + GetAsCXXRecordDecl (void* type); + + static clang::ObjCInterfaceDecl * + GetAsObjCInterfaceDecl (const ClangASTType& type); + + static clang::QualType + GetQualType (const ClangASTType& type) + { + if (type && type.GetTypeSystem()->AsClangASTContext()) + return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType()); + return clang::QualType(); + } + static clang::QualType + GetCanonicalQualType (const ClangASTType& type) + { + if (type && type.GetTypeSystem()->AsClangASTContext()) + return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType()).getCanonicalType(); + return clang::QualType(); + } + protected: + static clang::QualType + GetQualType (void *type) + { + if (type) + return clang::QualType::getFromOpaquePtr(type); + return clang::QualType(); + } + + static clang::QualType + GetCanonicalQualType (void *type) + { + if (type) + return clang::QualType::getFromOpaquePtr(type).getCanonicalType(); + return clang::QualType(); + } + + //------------------------------------------------------------------ // Classes that inherit from ClangASTContext can see and modify these //------------------------------------------------------------------ @@ -492,6 +1042,7 @@ CompleteObjCInterfaceDeclCallback m_callback_objc_decl; void * m_callback_baton; uint32_t m_pointer_byte_size; + bool m_ast_owned; private: //------------------------------------------------------------------ // For ClangASTContext only Index: include/lldb/Symbol/ClangASTType.h =================================================================== --- include/lldb/Symbol/ClangASTType.h +++ include/lldb/Symbol/ClangASTType.h @@ -33,23 +33,18 @@ //---------------------------------------------------------------------- // Constructors and Destructors //---------------------------------------------------------------------- - ClangASTType (clang::ASTContext *ast_context, lldb::clang_type_t type) : - m_type (type), - m_ast (ast_context) - { - } - + ClangASTType (TypeSystem *type_system, void *type); ClangASTType (clang::ASTContext *ast_context, clang::QualType qual_type); ClangASTType (const ClangASTType &rhs) : m_type (rhs.m_type), - m_ast (rhs.m_ast) + m_type_system (rhs.m_type_system) { } ClangASTType () : m_type (0), - m_ast (0) + m_type_system (0) { } @@ -63,7 +58,7 @@ operator= (const ClangASTType &rhs) { m_type = rhs.m_type; - m_ast = rhs.m_ast; + m_type_system = rhs.m_type_system; return *this; } @@ -74,21 +69,21 @@ explicit operator bool () const { - return m_type != NULL && m_ast != NULL; + return m_type != NULL && m_type_system != NULL; } bool operator < (const ClangASTType &rhs) const { - if (m_ast == rhs.m_ast) + if (m_type_system == rhs.m_type_system) return m_type < rhs.m_type; - return m_ast < rhs.m_ast; + return m_type_system < rhs.m_type_system; } bool IsValid () const { - return m_type != NULL && m_ast != NULL; + return m_type != NULL && m_type_system != NULL; } bool @@ -122,9 +117,6 @@ IsCStringType (uint32_t &length) const; bool - IsCXXClassType () const; - - bool IsDefined() const; bool @@ -150,18 +142,6 @@ bool IsIntegerType (bool &is_signed) const; - - bool - IsObjCClassType () const; - - bool - IsObjCClassTypeAndHasIVars (bool check_superclass) const; - - bool - IsObjCObjectOrInterfaceType () const; - - bool - IsObjCObjectPointerType (ClangASTType *target_type = NULL); bool IsPolymorphicClass () const; @@ -202,13 +182,6 @@ bool IsVoidType () const; - bool - GetCXXClassName (std::string &class_name) const; - - bool - GetObjCClassName (std::string &class_name); - - //---------------------------------------------------------------------- // Type Completion //---------------------------------------------------------------------- @@ -227,10 +200,10 @@ // Accessors //---------------------------------------------------------------------- - clang::ASTContext * - GetASTContext() const + TypeSystem * + GetTypeSystem() const { - return m_ast; + return m_type_system; } ConstString @@ -251,7 +224,7 @@ lldb::LanguageType GetMinimumLanguage (); - lldb::clang_type_t + void * GetOpaqueQualType() const { return m_type; @@ -261,12 +234,7 @@ GetTypeClass () const; void - SetClangType (clang::ASTContext *ast, lldb::clang_type_t type) - { - m_ast = ast; - m_type = type; - } - + SetClangType (TypeSystem* type_system, void* type); void SetClangType (clang::ASTContext *ast, clang::QualType qual_type); @@ -276,21 +244,6 @@ //---------------------------------------------------------------------- // Creating related types //---------------------------------------------------------------------- - - ClangASTType - AddConstModifier () const; - - ClangASTType - AddRestrictModifier () const; - - ClangASTType - AddVolatileModifier () const; - - // Using the current type, create a new typedef to that type using "typedef_name" - // as the name and "decl_ctx" as the decl context. - ClangASTType - CreateTypedefType (const char *typedef_name, - clang::DeclContext *decl_ctx) const; ClangASTType GetArrayElementType (uint64_t *stride = nullptr) const; @@ -319,9 +272,6 @@ GetMemberFunctionAtIndex (size_t idx); ClangASTType - GetLValueReferenceType () const; - - ClangASTType GetNonReferenceType () const; ClangASTType @@ -329,16 +279,10 @@ ClangASTType GetPointerType () const; - - ClangASTType - GetRValueReferenceType () const; // If the current object represents a typedef type, get the underlying type ClangASTType GetTypedefedType () const; - - ClangASTType - RemoveFastQualifiers () const; //---------------------------------------------------------------------- // Create related types using the current type's AST @@ -373,25 +317,11 @@ static lldb::BasicType GetBasicTypeEnumeration (const ConstString &name); - - uint32_t - GetNumDirectBaseClasses () const; - - uint32_t - GetNumVirtualBaseClasses () const; uint32_t GetNumFields () const; ClangASTType - GetDirectBaseClassAtIndex (size_t idx, - uint32_t *bit_offset_ptr) const; - - ClangASTType - GetVirtualBaseClassAtIndex (size_t idx, - uint32_t *bit_offset_ptr) const; - - ClangASTType GetFieldAtIndex (size_t idx, std::string& name, uint64_t *bit_offset_ptr, @@ -405,9 +335,6 @@ uint32_t *bitfield_bit_size_ptr = NULL, bool *is_bitfield_ptr = NULL) const; - uint32_t - GetNumPointeeChildren () const; - ClangASTType GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, size_t idx, @@ -439,133 +366,10 @@ bool omit_empty_base_classes, std::vector& child_indexes) const; - size_t - GetNumTemplateArguments () const; - - ClangASTType - GetTemplateArgument (size_t idx, - lldb::TemplateArgumentKind &kind) const; - - - //---------------------------------------------------------------------- - // Modifying RecordType - //---------------------------------------------------------------------- - clang::FieldDecl * - AddFieldToRecordType (const char *name, - const ClangASTType &field_type, - lldb::AccessType access, - uint32_t bitfield_bit_size); - - void - BuildIndirectFields (); - - void - SetIsPacked (); - - clang::VarDecl * - AddVariableToRecordType (const char *name, - const ClangASTType &var_type, - lldb::AccessType access); - - clang::CXXMethodDecl * - AddMethodToCXXRecordType (const char *name, - const ClangASTType &method_type, - lldb::AccessType access, - bool is_virtual, - bool is_static, - bool is_inline, - bool is_explicit, - bool is_attr_used, - bool is_artificial); - - // C++ Base Classes - clang::CXXBaseSpecifier * - CreateBaseClassSpecifier (lldb::AccessType access, - bool is_virtual, - bool base_of_class); - - static void - DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, - unsigned num_base_classes); - - bool - SetBaseClassesForClassType (clang::CXXBaseSpecifier const * const *base_classes, - unsigned num_base_classes); - - - bool - SetObjCSuperClass (const ClangASTType &superclass_clang_type); - - bool - AddObjCClassProperty (const char *property_name, - const ClangASTType &property_clang_type, - clang::ObjCIvarDecl *ivar_decl, - const char *property_setter_name, - const char *property_getter_name, - uint32_t property_attributes, - ClangASTMetadata *metadata); - - clang::ObjCMethodDecl * - AddMethodToObjCObjectType (const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]") - const ClangASTType &method_clang_type, - lldb::AccessType access, - bool is_artificial); - - clang::DeclContext * - GetDeclContextForType () const; - - - bool - SetDefaultAccessForRecordFields (int default_accessibility, - int *assigned_accessibilities, - size_t num_assigned_accessibilities); - - bool - SetHasExternalStorage (bool has_extern); - - - //------------------------------------------------------------------ - // clang::TagType - //------------------------------------------------------------------ - - bool - SetTagTypeKind (int kind) const; - - //------------------------------------------------------------------ - // Tag Declarations - //------------------------------------------------------------------ - bool - StartTagDeclarationDefinition (); - - bool - CompleteTagDeclarationDefinition (); - - //---------------------------------------------------------------------- - // Modifying Enumeration types - //---------------------------------------------------------------------- - bool - AddEnumerationValueToEnumerationType (const ClangASTType &enumerator_qual_type, - const Declaration &decl, - const char *name, - int64_t enum_value, - uint32_t enum_value_bit_size); - - - - ClangASTType - GetEnumerationIntegerType () const; - - //------------------------------------------------------------------ // Pointers & References //------------------------------------------------------------------ - // Call this function using the class type when you want to make a - // member pointer type to pointee_type. - ClangASTType - CreateMemberPointerType (const ClangASTType &pointee_type) const; - - // Converts "s" to a floating point value and place resulting floating // point bytes in the "dst" buffer. size_t @@ -633,45 +437,16 @@ lldb::addr_t addr, AddressType address_type, StreamString &new_value); - - clang::EnumDecl * - GetAsEnumDecl () const; - - clang::RecordDecl * - GetAsRecordDecl () const; - - clang::CXXRecordDecl * - GetAsCXXRecordDecl () const; - - clang::ObjCInterfaceDecl * - GetAsObjCInterfaceDecl () const; - void Clear() { m_type = NULL; - m_ast = NULL; + m_type_system = NULL; } - - clang::QualType - GetQualType () const - { - if (m_type) - return clang::QualType::getFromOpaquePtr(m_type); - return clang::QualType(); - } - clang::QualType - GetCanonicalQualType () const - { - if (m_type) - return clang::QualType::getFromOpaquePtr(m_type).getCanonicalType(); - return clang::QualType(); - } - private: - lldb::clang_type_t m_type; - clang::ASTContext *m_ast; + void* m_type; + TypeSystem *m_type_system; }; Index: include/lldb/Symbol/TaggedASTType.h =================================================================== --- include/lldb/Symbol/TaggedASTType.h +++ include/lldb/Symbol/TaggedASTType.h @@ -25,8 +25,8 @@ { } - TaggedASTType (lldb::clang_type_t type, clang::ASTContext *ast_context) : - ClangASTType(ast_context, type) + TaggedASTType (void *type, TypeSystem * type_system) : + ClangASTType(type_system, type) { } Index: include/lldb/Symbol/Type.h =================================================================== --- include/lldb/Symbol/Type.h +++ include/lldb/Symbol/Type.h @@ -14,6 +14,7 @@ #include "lldb/Core/ClangForward.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/UserID.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/Declaration.h" @@ -443,8 +444,8 @@ GetReferenceType () const { if (type_sp) - return type_sp->GetClangLayoutType().GetLValueReferenceType(); - return clang_type.GetLValueReferenceType(); + return ClangASTContext::GetLValueReferenceType(type_sp->GetClangLayoutType()); + return ClangASTContext::GetLValueReferenceType(clang_type); } ClangASTType @@ -479,10 +480,10 @@ return clang_type.GetCanonicalType(); } - clang::ASTContext * - GetClangASTContext () const + TypeSystem * + GetTypeSystem () const { - return clang_type.GetASTContext(); + return clang_type.GetTypeSystem(); } lldb::ModuleSP @@ -578,8 +579,8 @@ ClangASTType GetClangASTType (bool prefer_dynamic); - clang::ASTContext * - GetClangASTContext (bool prefer_dynamic); + TypeSystem * + GetTypeSystem (bool prefer_dynamic); bool GetDescription (lldb_private::Stream &strm, Index: include/lldb/Symbol/TypeSystem.h =================================================================== --- /dev/null +++ include/lldb/Symbol/TypeSystem.h @@ -0,0 +1,331 @@ +//===-- TypeSystem.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_TypeSystem_h_ +#define liblldb_TypeSystem_h_ + +#include +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "clang/AST/Type.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// Interface for representing the Type Systems in different languages. +//---------------------------------------------------------------------- +class TypeSystem +{ +public: + //---------------------------------------------------------------------- + // Constructors and Destructors + //---------------------------------------------------------------------- + TypeSystem (); + + virtual ~TypeSystem (); + + virtual ClangASTContext * + AsClangASTContext() = 0; + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + virtual bool + IsArrayType (void * type, + ClangASTType *element_type, + uint64_t *size, + bool *is_incomplete) = 0; + + virtual bool + IsAggregateType (void * type) = 0; + + virtual bool + IsCharType (void * type) = 0; + + virtual bool + IsCompleteType (void * type) = 0; + + virtual bool + IsDefined(void * type) = 0; + + virtual bool + IsFloatingPointType (void * type, uint32_t &count, bool &is_complex) = 0; + + virtual bool + IsFunctionType (void * type, bool *is_variadic_ptr) = 0; + + virtual size_t + GetNumberOfFunctionArguments (void * type) = 0; + + virtual ClangASTType + GetFunctionArgumentAtIndex (void * type, const size_t index) = 0; + + virtual bool + IsFunctionPointerType (void * type) = 0; + + virtual bool + IsIntegerType (void * type, bool &is_signed) = 0; + + virtual bool + IsPossibleDynamicType (void * type, + ClangASTType *target_type, // Can pass NULL + bool check_cplusplus, + bool check_objc) = 0; + + virtual bool + IsPointerType (void * type, ClangASTType *pointee_type) = 0; + + virtual bool + IsScalarType (void * type) = 0; + + virtual bool + IsVoidType (void * type) = 0; + + //---------------------------------------------------------------------- + // Type Completion + //---------------------------------------------------------------------- + + virtual bool + GetCompleteType (void * type) = 0; + + //---------------------------------------------------------------------- + // AST related queries + //---------------------------------------------------------------------- + + virtual uint32_t + GetPointerByteSize () = 0; + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + + virtual ConstString + GetTypeName (void * type) = 0; + + virtual uint32_t + GetTypeInfo (void * type, ClangASTType *pointee_or_element_clang_type) = 0; + + virtual lldb::LanguageType + GetMinimumLanguage (void * type) = 0; + + virtual lldb::TypeClass + GetTypeClass (void * type) = 0; + + //---------------------------------------------------------------------- + // Creating related types + //---------------------------------------------------------------------- + + virtual ClangASTType + GetArrayElementType (void * type, uint64_t *stride) = 0; + + virtual ClangASTType + GetCanonicalType (void * type) = 0; + + // Returns -1 if this isn't a function of if the function doesn't have a prototype + // Returns a value >= 0 if there is a prototype. + virtual int + GetFunctionArgumentCount (void * type) = 0; + + virtual ClangASTType + GetFunctionArgumentTypeAtIndex (void * type, size_t idx) = 0; + + virtual ClangASTType + GetFunctionReturnType (void * type) = 0; + + virtual size_t + GetNumMemberFunctions (void * type) = 0; + + virtual TypeMemberFunctionImpl + GetMemberFunctionAtIndex (void * type, size_t idx) = 0; + + virtual ClangASTType + GetPointeeType (void * type) = 0; + + virtual ClangASTType + GetPointerType (void * type) = 0; + + //---------------------------------------------------------------------- + // Exploring the type + //---------------------------------------------------------------------- + + virtual uint64_t + GetBitSize (void * type, ExecutionContextScope *exe_scope) = 0; + + virtual lldb::Encoding + GetEncoding (void * type, uint64_t &count) = 0; + + virtual lldb::Format + GetFormat (void * type) = 0; + + virtual uint32_t + GetNumChildren (void * type, bool omit_empty_base_classes) = 0; + + virtual lldb::BasicType + GetBasicTypeEnumeration (void * type) = 0; + + virtual uint32_t + GetNumFields (void * type) = 0; + + virtual ClangASTType + GetFieldAtIndex (void * type, + size_t idx, + std::string& name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) = 0; + + virtual ClangASTType + GetChildClangTypeAtIndex (void * type, + ExecutionContext *exe_ctx, + size_t idx, + bool transparent_pointers, + bool omit_empty_base_classes, + bool ignore_array_bounds, + std::string& child_name, + uint32_t &child_byte_size, + int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, + uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, + bool &child_is_deref_of_parent, + ValueObject *valobj) = 0; + + // Lookup a child given a name. This function will match base class names + // and member member names in "clang_type" only, not descendants. + virtual uint32_t + GetIndexOfChildWithName (void * type, + const char *name, + bool omit_empty_base_classes) = 0; + + // Lookup a child member given a name. This function will match member names + // only and will descend into "clang_type" children in search for the first + // member in this class, or any base class that matches "name". + // TODO: Return all matches for a given name by returning a vector> + // so we catch all names that match a given child name, not just the first. + virtual size_t + GetIndexOfChildMemberWithName (void * type, + const char *name, + bool omit_empty_base_classes, + std::vector& child_indexes) = 0; + + //---------------------------------------------------------------------- + // Dumping types + //---------------------------------------------------------------------- + virtual void + DumpValue (void * type, + ExecutionContext *exe_ctx, + Stream *s, + lldb::Format format, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool show_types, + bool show_summary, + bool verbose, + uint32_t depth) = 0; + + virtual bool + DumpTypeValue (void * type, + Stream *s, + lldb::Format format, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope) = 0; + + virtual void + DumpTypeDescription (void * type) = 0; // Dump to stdout + + virtual void + DumpTypeDescription (void * type, Stream *s) = 0; + + //---------------------------------------------------------------------- + // TODO: These methods appear unused. Should they be removed? + //---------------------------------------------------------------------- + + virtual bool + IsRuntimeGeneratedType (void * type) = 0; + + virtual void + DumpSummary (void * type, + ExecutionContext *exe_ctx, + Stream *s, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size) = 0; + + // Converts "s" to a floating point value and place resulting floating + // point bytes in the "dst" buffer. + virtual size_t + ConvertStringToFloatValue (void * type, + const char *s, + uint8_t *dst, + size_t dst_size) = 0; + + //---------------------------------------------------------------------- + // TODO: Determine if these methods should move to ClangASTContext. + //---------------------------------------------------------------------- + + virtual bool + IsPointerOrReferenceType (void * type, ClangASTType *pointee_type) = 0; + + virtual unsigned + GetTypeQualifiers(void * type) = 0; + + virtual bool + IsCStringType (void * type, uint32_t &length) = 0; + + virtual size_t + GetTypeBitAlign (void * type) = 0; + + virtual ClangASTType + GetBasicTypeFromAST (void * type, lldb::BasicType basic_type) = 0; + + virtual bool + IsBeingDefined (void * type) = 0; + + virtual bool + IsConst(void * type) = 0; + + virtual uint32_t + IsHomogeneousAggregate (void * type, ClangASTType* base_type_ptr) = 0; + + virtual bool + IsPolymorphicClass (void * type) = 0; + + virtual bool + IsTypedefType (void * type) = 0; + + // If the current object represents a typedef type, get the underlying type + virtual ClangASTType + GetTypedefedType (void * type) = 0; + + virtual bool + IsVectorType (void * type, + ClangASTType *element_type, + uint64_t *size) = 0; + + virtual ClangASTType + GetFullyUnqualifiedType (void * type) = 0; + + virtual ClangASTType + GetNonReferenceType (void * type) = 0; + + virtual bool + IsReferenceType (void * type, ClangASTType *pointee_type, bool* is_rvalue) = 0; +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_TypeSystem_h_ Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -221,6 +221,7 @@ class SyntheticChildren; class SyntheticChildrenFrontEnd; class TypeFilterImpl; +class TypeSystem; #ifndef LLDB_DISABLE_PYTHON class ScriptedSyntheticChildren; #endif Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -798,6 +798,7 @@ 9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703AE117675410086C050 /* SBInstruction.cpp */; }; 9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703B0117675490086C050 /* SBInstructionList.cpp */; }; A36FF33C17D8E94600244D40 /* OptionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A36FF33B17D8E94600244D40 /* OptionParser.cpp */; }; + AEEA34051AC88A7400AB639D /* TypeSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEEA34041AC88A7400AB639D /* TypeSystem.cpp */; }; AF061F87182C97ED00B6A19C /* RegisterContextHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */; }; AF0C112818580CD800C4C45B /* QueueItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0C112718580CD800C4C45B /* QueueItem.cpp */; }; AF0E22F018A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0E22EE18A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp */; }; @@ -2561,6 +2562,8 @@ 9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBreakpointLocation.cpp; path = source/API/SBBreakpointLocation.cpp; sourceTree = ""; }; A36FF33B17D8E94600244D40 /* OptionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptionParser.cpp; sourceTree = ""; }; A36FF33D17D8E98800244D40 /* OptionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionParser.h; path = include/lldb/Host/OptionParser.h; sourceTree = ""; }; + AEEA33F61AC74FE700AB639D /* TypeSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeSystem.h; path = include/lldb/Symbol/TypeSystem.h; sourceTree = ""; }; + AEEA34041AC88A7400AB639D /* TypeSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSystem.cpp; path = source/Symbol/TypeSystem.cpp; sourceTree = ""; }; AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextHistory.cpp; path = Utility/RegisterContextHistory.cpp; sourceTree = ""; }; AF061F86182C97ED00B6A19C /* RegisterContextHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextHistory.h; path = Utility/RegisterContextHistory.h; sourceTree = ""; }; AF061F89182C980000B6A19C /* HistoryThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryThread.h; path = Utility/HistoryThread.h; sourceTree = ""; }; @@ -4176,6 +4179,8 @@ 26BC7F2010F1B8EC00F91463 /* Type.cpp */, 26BC7C6610F1B6E900F91463 /* TypeList.h */, 26BC7F2110F1B8EC00F91463 /* TypeList.cpp */, + AEEA33F61AC74FE700AB639D /* TypeSystem.h */, + AEEA34041AC88A7400AB639D /* TypeSystem.cpp */, 269FF07F12494F8E00225026 /* UnwindPlan.h */, 961FABB91235DE1600F93A47 /* UnwindPlan.cpp */, 269FF08112494FC200225026 /* UnwindTable.h */, @@ -6177,6 +6182,7 @@ 2689009F13353E4200698AC0 /* ProcessGDBRemote.cpp in Sources */, 268900A013353E4200698AC0 /* ProcessGDBRemoteLog.cpp in Sources */, 268900A113353E4200698AC0 /* ThreadGDBRemote.cpp in Sources */, + AEEA34051AC88A7400AB639D /* TypeSystem.cpp in Sources */, AF1729D6182C907200E0AB97 /* HistoryThread.cpp in Sources */, 268900AF13353E5000698AC0 /* UnwindLLDB.cpp in Sources */, 268900B013353E5000698AC0 /* RegisterContextLLDB.cpp in Sources */, Index: lldb.xcodeproj/xcshareddata/xcschemes/Run Testsuite.xcscheme =================================================================== --- lldb.xcodeproj/xcshareddata/xcschemes/Run Testsuite.xcscheme +++ lldb.xcodeproj/xcshareddata/xcschemes/Run Testsuite.xcscheme @@ -50,6 +50,7 @@ debugDocumentVersioning = "YES" allowLocationSimulation = "YES"> @@ -79,7 +80,7 @@ isEnabled = "YES"> @@ -97,7 +98,8 @@ useCustomWorkingDirectory = "NO" buildConfiguration = "Release" debugDocumentVersioning = "YES"> - + Index: source/API/SBType.cpp =================================================================== --- source/API/SBType.cpp +++ source/API/SBType.cpp @@ -30,7 +30,7 @@ } SBType::SBType (const ClangASTType &type) : - m_opaque_sp(new TypeImpl(ClangASTType(type.GetASTContext(), + m_opaque_sp(new TypeImpl(ClangASTType(type.GetTypeSystem(), type.GetOpaqueQualType()))) { } @@ -342,8 +342,13 @@ SBType SBType::GetBasicType(lldb::BasicType basic_type) { - if (IsValid()) - return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetClangASTContext(false), basic_type)); + if (IsValid() && m_opaque_sp->IsValid()) + { + ClangASTContext* ast = m_opaque_sp->GetTypeSystem(false)->AsClangASTContext(); + if (ast) + return SBType (ClangASTContext::GetBasicType (ast->getASTContext(), basic_type)); + } + return SBType(); } @@ -351,7 +356,7 @@ SBType::GetNumberOfDirectBaseClasses () { if (IsValid()) - return m_opaque_sp->GetClangASTType(true).GetNumDirectBaseClasses(); + return ClangASTContext::GetNumDirectBaseClasses(m_opaque_sp->GetClangASTType(true)); return 0; } @@ -359,7 +364,7 @@ SBType::GetNumberOfVirtualBaseClasses () { if (IsValid()) - return m_opaque_sp->GetClangASTType(true).GetNumVirtualBaseClasses(); + return ClangASTContext::GetNumVirtualBaseClasses(m_opaque_sp->GetClangASTType(true)); return 0; } @@ -398,7 +403,7 @@ if (this_type.IsValid()) { uint32_t bit_offset = 0; - ClangASTType base_class_type (this_type.GetDirectBaseClassAtIndex(idx, &bit_offset)); + ClangASTType base_class_type (ClangASTContext::GetDirectBaseClassAtIndex(this_type, idx, &bit_offset)); if (base_class_type.IsValid()) { sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); @@ -419,7 +424,7 @@ if (this_type.IsValid()) { uint32_t bit_offset = 0; - ClangASTType base_class_type (this_type.GetVirtualBaseClassAtIndex(idx, &bit_offset)); + ClangASTType base_class_type (ClangASTContext::GetVirtualBaseClassAtIndex(this_type, idx, &bit_offset)); if (base_class_type.IsValid()) { sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); @@ -435,14 +440,14 @@ SBTypeEnumMemberList sb_enum_member_list; if (IsValid()) { - const clang::EnumDecl *enum_decl = m_opaque_sp->GetClangASTType(true).GetFullyUnqualifiedType().GetAsEnumDecl(); + const clang::EnumDecl *enum_decl = ClangASTContext::GetAsEnumDecl(m_opaque_sp->GetClangASTType(true).GetFullyUnqualifiedType()); if (enum_decl) { clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) { SBTypeEnumMember enum_member; - enum_member.reset(new TypeEnumMemberImpl(*enum_pos, ClangASTType(m_opaque_sp->GetClangASTContext(true), enum_decl->getIntegerType()))); + enum_member.reset(new TypeEnumMemberImpl(*enum_pos, ClangASTType(m_opaque_sp->GetTypeSystem(true), enum_decl->getIntegerType().getAsOpaquePtr()))); sb_enum_member_list.Append(enum_member); } } @@ -528,7 +533,7 @@ SBType::GetNumberOfTemplateArguments () { if (IsValid()) - return m_opaque_sp->GetClangASTType(false).GetNumTemplateArguments(); + return ClangASTContext::GetNumTemplateArguments(m_opaque_sp->GetClangASTType(false)); return 0; } @@ -538,7 +543,7 @@ if (IsValid()) { TemplateArgumentKind kind = eTemplateArgumentKindNull; - ClangASTType template_arg_type = m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind); + ClangASTType template_arg_type = ClangASTContext::GetTemplateArgument(m_opaque_sp->GetClangASTType(false), idx, kind); if (template_arg_type.IsValid()) return SBType(template_arg_type); } @@ -551,7 +556,7 @@ { TemplateArgumentKind kind = eTemplateArgumentKindNull; if (IsValid()) - m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind); + ClangASTContext::GetTemplateArgument(m_opaque_sp->GetClangASTType(false), idx, kind); return kind; } Index: source/Commands/CommandObjectMemory.cpp =================================================================== --- source/Commands/CommandObjectMemory.cpp +++ source/Commands/CommandObjectMemory.cpp @@ -33,6 +33,7 @@ #include "lldb/Interpreter/OptionGroupOutputFile.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/MemoryHistory.h" #include "lldb/Target/Process.h" @@ -532,7 +533,7 @@ clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name)); if (tdecl) { - clang_ast_type.SetClangType(&tdecl->getASTContext(),(const lldb::clang_type_t)tdecl->getTypeForDecl()); + clang_ast_type.SetClangType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),(const lldb::clang_type_t)tdecl->getTypeForDecl()); } } Index: source/Core/ValueObject.cpp =================================================================== --- source/Core/ValueObject.cpp +++ source/Core/ValueObject.cpp @@ -338,11 +338,11 @@ ClangASTType class_type; bool is_pointer_type = false; - if (clang_type.IsObjCObjectPointerType(&class_type)) + if (ClangASTContext::IsObjCObjectPointerType(clang_type, &class_type)) { is_pointer_type = true; } - else if (clang_type.IsObjCObjectOrInterfaceType()) + else if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) { class_type = clang_type; } @@ -2419,7 +2419,7 @@ bool parent_had_base_class = GetParent() && GetParent()->GetBaseClassPath (s); ClangASTType clang_type = GetClangType(); std::string cxx_class_name; - bool this_had_base_class = clang_type.GetCXXClassName (cxx_class_name); + bool this_had_base_class = ClangASTContext::GetCXXClassName (clang_type, cxx_class_name); if (this_had_base_class) { if (parent_had_base_class) Index: source/Core/ValueObjectDynamicValue.cpp =================================================================== --- source/Core/ValueObjectDynamicValue.cpp +++ source/Core/ValueObjectDynamicValue.cpp @@ -154,7 +154,7 @@ if (parent.IsPointerType()) corrected_type = orig_type.GetPointerType (); else if (parent.IsPointerOrReferenceType()) - corrected_type = orig_type.GetLValueReferenceType (); + corrected_type = ClangASTContext::GetLValueReferenceType(orig_type); ret.SetClangASTType(corrected_type); } else /*if (m_dynamic_type_info.HasName())*/ Index: source/Core/ValueObjectMemory.cpp =================================================================== --- source/Core/ValueObjectMemory.cpp +++ source/Core/ValueObjectMemory.cpp @@ -97,7 +97,7 @@ m_clang_type(ast_type) { // Do not attempt to construct one of these objects with no variable! - assert (m_clang_type.GetASTContext()); + assert (m_clang_type.GetTypeSystem()); assert (m_clang_type.GetOpaqueQualType()); TargetSP target_sp (GetTargetSP()); Index: source/DataFormatters/CXXFormatterFunctions.cpp =================================================================== --- source/DataFormatters/CXXFormatterFunctions.cpp +++ source/DataFormatters/CXXFormatterFunctions.cpp @@ -312,7 +312,8 @@ if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS) return false; - clang::ASTContext* ast = valobj.GetClangType().GetASTContext(); + ClangASTContext* lldb_ast = valobj.GetClangType().GetTypeSystem()->AsClangASTContext(); + clang::ASTContext* ast = lldb_ast ? lldb_ast->getASTContext() : nullptr; if (!ast) return false; Index: source/DataFormatters/CoreMedia.cpp =================================================================== --- source/DataFormatters/CoreMedia.cpp +++ source/DataFormatters/CoreMedia.cpp @@ -21,7 +21,9 @@ bool lldb_private::formatters::CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { - ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(valobj.GetClangType().GetASTContext()); + if (!valobj.GetClangType().IsValid()) + return false; + ClangASTContext *ast_ctx = valobj.GetClangType().GetTypeSystem()->AsClangASTContext(); if (!ast_ctx) return false; Index: source/DataFormatters/FormatManager.cpp =================================================================== --- source/DataFormatters/FormatManager.cpp +++ source/DataFormatters/FormatManager.cpp @@ -171,7 +171,7 @@ bool did_strip_typedef, bool root_level) { - clang_type = clang_type.RemoveFastQualifiers(); + clang_type = ClangASTContext::RemoveFastQualifiers(clang_type); ConstString type_name(clang_type.GetConstTypeName()); if (valobj.GetBitfieldBitSize() > 0) { @@ -201,7 +201,7 @@ if (non_ref_type.IsTypedefType()) { ClangASTType deffed_referenced_type = non_ref_type.GetTypedefedType(); - deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType(); + deffed_referenced_type = is_rvalue_ref ? ClangASTContext::GetRValueReferenceType(deffed_referenced_type) : ClangASTContext::GetLValueReferenceType(deffed_referenced_type); GetPossibleMatches(valobj, deffed_referenced_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, Index: source/DataFormatters/LibCxxInitializerList.cpp =================================================================== --- source/DataFormatters/LibCxxInitializerList.cpp +++ source/DataFormatters/LibCxxInitializerList.cpp @@ -101,7 +101,7 @@ m_num_elements = 0; m_children.clear(); lldb::TemplateArgumentKind kind; - m_element_type = m_backend.GetClangType().GetTemplateArgument(0, kind); + m_element_type = ClangASTContext::GetTemplateArgument(m_backend.GetClangType(), 0, kind); if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid()) return false; Index: source/DataFormatters/LibCxxList.cpp =================================================================== --- source/DataFormatters/LibCxxList.cpp +++ source/DataFormatters/LibCxxList.cpp @@ -335,10 +335,10 @@ if (list_type.IsReferenceType()) list_type = list_type.GetNonReferenceType(); - if (list_type.GetNumTemplateArguments() == 0) + if (ClangASTContext::GetNumTemplateArguments(list_type) == 0) return false; lldb::TemplateArgumentKind kind; - m_element_type = list_type.GetTemplateArgument(0, kind); + m_element_type = ClangASTContext::GetTemplateArgument(list_type, 0, kind); m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get(); m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get(); return false; Index: source/DataFormatters/LibCxxMap.cpp =================================================================== --- source/DataFormatters/LibCxxMap.cpp +++ source/DataFormatters/LibCxxMap.cpp @@ -279,7 +279,7 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { - if (m_element_type.GetOpaqueQualType() && m_element_type.GetASTContext()) + if (m_element_type.GetOpaqueQualType() && m_element_type.GetTypeSystem()) return true; m_element_type.Clear(); ValueObjectSP deref; Index: source/DataFormatters/LibStdcpp.cpp =================================================================== --- source/DataFormatters/LibStdcpp.cpp +++ source/DataFormatters/LibStdcpp.cpp @@ -79,10 +79,10 @@ m_pair_address += (is_64bit ? 32 : 16); ClangASTType my_type(valobj_sp->GetClangType()); - if (my_type.GetNumTemplateArguments() >= 1) + if (ClangASTContext::GetNumTemplateArguments(my_type) >= 1) { TemplateArgumentKind kind; - ClangASTType pair_type = my_type.GetTemplateArgument(0, kind); + ClangASTType pair_type = ClangASTContext::GetTemplateArgument(my_type, 0, kind); if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion) return false; m_pair_type = pair_type; Index: source/DataFormatters/NSArray.cpp =================================================================== --- source/DataFormatters/NSArray.cpp +++ source/DataFormatters/NSArray.cpp @@ -528,11 +528,11 @@ m_items (0), m_data_ptr (0) { - if (valobj_sp) + if (valobj_sp && valobj_sp->GetClangType().IsValid()) { - clang::ASTContext *ast = valobj_sp->GetClangType().GetASTContext(); + ClangASTContext *ast = valobj_sp->GetClangType().GetTypeSystem()->AsClangASTContext(); if (ast) - m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy); + m_id_type = ClangASTType(ast->getASTContext(), ast->getASTContext()->ObjCBuiltinIdTy); } } Index: source/DataFormatters/NSDictionary.cpp =================================================================== --- source/DataFormatters/NSDictionary.cpp +++ source/DataFormatters/NSDictionary.cpp @@ -44,11 +44,11 @@ if (clang_type) { - clang_type.StartTagDeclarationDefinition(); + ClangASTContext::StartTagDeclarationDefinition(clang_type); ClangASTType id_clang_type = target_ast_context->GetBasicType (eBasicTypeObjCID); - clang_type.AddFieldToRecordType("key", id_clang_type, lldb::eAccessPublic, 0); - clang_type.AddFieldToRecordType("value", id_clang_type, lldb::eAccessPublic, 0); - clang_type.CompleteTagDeclarationDefinition(); + ClangASTContext::AddFieldToRecordType(clang_type, "key", id_clang_type, lldb::eAccessPublic, 0); + ClangASTContext::AddFieldToRecordType(clang_type, "value", id_clang_type, lldb::eAccessPublic, 0); + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); } } } Index: source/DataFormatters/NSIndexPath.cpp =================================================================== --- source/DataFormatters/NSIndexPath.cpp +++ source/DataFormatters/NSIndexPath.cpp @@ -49,7 +49,10 @@ { m_impl.Clear(); - m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext()); + TypeSystem* type_system = m_backend.GetClangType().GetTypeSystem(); + if (!type_system) + return false; + m_ast_ctx = type_system->AsClangASTContext(); if (!m_ast_ctx) return false; Index: source/DataFormatters/VectorType.cpp =================================================================== --- source/DataFormatters/VectorType.cpp +++ source/DataFormatters/VectorType.cpp @@ -232,7 +232,7 @@ ClangASTType parent_type(m_backend.GetClangType()); ClangASTType element_type; parent_type.IsVectorType(&element_type, nullptr); - m_child_type = ::GetClangTypeForFormat(m_parent_format, element_type, ClangASTContext::GetASTContext(parent_type.GetASTContext())); + m_child_type = ::GetClangTypeForFormat(m_parent_format, element_type, parent_type.GetTypeSystem()->AsClangASTContext()); m_num_children = ::CalculateNumChildren(parent_type, m_child_type); m_item_format = GetItemFormatForFormat(m_parent_format, Index: source/Expression/ASTDumper.cpp =================================================================== --- source/Expression/ASTDumper.cpp +++ source/Expression/ASTDumper.cpp @@ -9,6 +9,7 @@ #include "lldb/Core/Log.h" #include "lldb/Expression/ASTDumper.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTType.h" #include "llvm/Support/raw_ostream.h" @@ -81,7 +82,7 @@ ASTDumper::ASTDumper (const ClangASTType &clang_type) { - m_dump = clang_type.GetQualType().getAsString(); + m_dump = ClangASTContext::GetQualType(clang_type).getAsString(); } Index: source/Expression/ClangASTSource.cpp =================================================================== --- source/Expression/ClangASTSource.cpp +++ source/Expression/ClangASTSource.cpp @@ -277,7 +277,7 @@ if (!clang_type) continue; - const TagType *tag_type = clang_type.GetQualType()->getAs(); + const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs(); if (!tag_type) continue; @@ -316,7 +316,7 @@ if (!clang_type) continue; - const TagType *tag_type = clang_type.GetQualType()->getAs(); + const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs(); if (!tag_type) continue; @@ -1886,9 +1886,13 @@ { ClangASTMetrics::RegisterLLDBImport(); + ClangASTContext* src_ast = src_type.GetTypeSystem()->AsClangASTContext(); + if (!src_ast) + return ClangASTType(); + SetImportInProgress(true); - QualType copied_qual_type = m_ast_importer->CopyType (m_ast_context, src_type.GetASTContext(), src_type.GetQualType()); + QualType copied_qual_type = m_ast_importer->CopyType (m_ast_context, src_ast->getASTContext(), ClangASTContext::GetQualType(src_type)); SetImportInProgress(false); @@ -1908,16 +1912,20 @@ if (!type.IsValid()) return NULL; + ClangASTContext* lldb_ast = type.GetTypeSystem()->AsClangASTContext(); + if (!lldb_ast) + return NULL; + IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); - clang::ASTContext *ast = type.GetASTContext(); + clang::ASTContext *ast = lldb_ast->getASTContext(); clang::NamedDecl *Decl = VarDecl::Create(*ast, const_cast(m_decl_context), SourceLocation(), SourceLocation(), ii, - type.GetQualType(), + ClangASTContext::GetQualType(type), 0, SC_Static); m_decls.push_back(Decl); @@ -1935,12 +1943,16 @@ if (m_function_types.count(type)) return NULL; + + ClangASTContext* lldb_ast = type.GetTypeSystem()->AsClangASTContext(); + if (!lldb_ast) + return NULL; m_function_types.insert(type); - QualType qual_type (type.GetQualType()); + QualType qual_type (ClangASTContext::GetQualType(type)); - clang::ASTContext *ast = type.GetASTContext(); + clang::ASTContext *ast = lldb_ast->getASTContext(); const bool isInlineSpecified = false; const bool hasWrittenPrototype = true; @@ -2031,7 +2043,7 @@ { if (clang_type) { - QualType qual_type = clang_type.GetQualType(); + QualType qual_type = ClangASTContext::GetQualType(clang_type); if (const TypedefType *typedef_type = llvm::dyn_cast(qual_type)) { Index: source/Expression/ClangExpressionDeclMap.cpp =================================================================== --- source/Expression/ClangExpressionDeclMap.cpp +++ source/Expression/ClangExpressionDeclMap.cpp @@ -201,10 +201,10 @@ if (target == NULL) return false; - ASTContext *context(target->GetScratchClangASTContext()->getASTContext()); + ClangASTContext *context(target->GetScratchClangASTContext()); - TypeFromUser user_type(m_ast_importer->DeportType(context, - parser_type.GetASTContext(), + TypeFromUser user_type(m_ast_importer->DeportType(context->getASTContext(), + parser_type.GetTypeSystem()->AsClangASTContext()->getASTContext(), parser_type.GetOpaqueQualType()), context); @@ -241,10 +241,10 @@ if (target == NULL) return false; - ASTContext *context(target->GetScratchClangASTContext()->getASTContext()); + ClangASTContext *context(target->GetScratchClangASTContext()); - TypeFromUser user_type(m_ast_importer->DeportType(context, - parser_type.GetASTContext(), + TypeFromUser user_type(m_ast_importer->DeportType(context->getASTContext(), + parser_type.GetTypeSystem()->AsClangASTContext()->getASTContext(), parser_type.GetOpaqueQualType()), context); @@ -1038,7 +1038,7 @@ QualType class_qual_type(class_decl->getTypeForDecl(), 0); TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(), - &class_decl->getASTContext()); + ClangASTContext::GetASTContext(&class_decl->getASTContext())); if (log) { @@ -1076,7 +1076,7 @@ QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type); TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), - &method_decl->getASTContext()); + ClangASTContext::GetASTContext(&method_decl->getASTContext())); m_struct_vars->m_object_pointer_type = self_user_type; } @@ -1166,7 +1166,7 @@ return; // This is unlikely, but we have seen crashes where this occurred TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(), - &method_decl->getASTContext()); + ClangASTContext::GetASTContext(&method_decl->getASTContext())); if (log) { @@ -1183,7 +1183,7 @@ QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0)); TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), - &method_decl->getASTContext()); + ClangASTContext::GetASTContext(&method_decl->getASTContext())); m_struct_vars->m_object_pointer_type = self_user_type; } @@ -1193,7 +1193,7 @@ QualType class_type = method_decl->getASTContext().getObjCClassType(); TypeFromUser self_user_type(class_type.getAsOpaquePtr(), - &method_decl->getASTContext()); + ClangASTContext::GetASTContext(&method_decl->getASTContext())); m_struct_vars->m_object_pointer_type = self_user_type; } @@ -1222,11 +1222,11 @@ ClangASTType self_clang_type = self_type->GetClangFullType(); - if (self_clang_type.IsObjCClassType()) + if (ClangASTContext::IsObjCClassType(self_clang_type)) { return; } - else if (self_clang_type.IsObjCObjectPointerType()) + else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) { self_clang_type = self_clang_type.GetPointeeType(); @@ -1748,7 +1748,7 @@ if (is_reference) var_decl = context.AddVarDecl(pt); else - var_decl = context.AddVarDecl(pt.GetLValueReferenceType()); + var_decl = context.AddVarDecl(ClangASTContext::GetLValueReferenceType(pt)); std::string decl_name(context.m_decl_name.getAsString()); ConstString entity_name(decl_name.c_str()); @@ -1792,7 +1792,7 @@ return; } - NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType()); + NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::GetLValueReferenceType(parser_type)); pvar_sp->EnableParserVars(GetParserID()); ClangExpressionVariable::ParserVars *parser_vars = pvar_sp->GetParserVars(GetParserID()); @@ -1824,8 +1824,8 @@ ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext(); - TypeFromUser user_type (ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); - TypeFromParser parser_type (ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); + TypeFromUser user_type (ClangASTContext::GetLValueReferenceType(ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType())); + TypeFromParser parser_type (ClangASTContext::GetLValueReferenceType(ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType())); NamedDecl *var_decl = context.AddVarDecl(parser_type); std::string decl_name(context.m_decl_name.getAsString()); @@ -1867,7 +1867,7 @@ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext(); + ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext(); for (size_t index = 0, num_entities = m_found_entities.GetSize(); index < num_entities; @@ -1896,9 +1896,9 @@ } QualType var_type = var_decl->getType(); - TypeFromParser parser_type(var_type.getAsOpaquePtr(), &var_decl->getASTContext()); + TypeFromParser parser_type(var_type.getAsOpaquePtr(), ClangASTContext::GetASTContext(&var_decl->getASTContext())); - lldb::clang_type_t copied_type = m_ast_importer->CopyType(scratch_ast_context, &var_decl->getASTContext(), var_type.getAsOpaquePtr()); + lldb::clang_type_t copied_type = m_ast_importer->CopyType(scratch_ast_context->getASTContext(), &var_decl->getASTContext(), var_type.getAsOpaquePtr()); if (!copied_type) { @@ -2136,15 +2136,17 @@ const bool is_attr_used = true; const bool is_artificial = false; - copied_clang_type.AddMethodToCXXRecordType ("$__lldb_expr", - method_type, - lldb::eAccessPublic, - is_virtual, - is_static, - is_inline, - is_explicit, - is_attr_used, - is_artificial); + ClangASTContext::GetASTContext(m_ast_context)-> + AddMethodToCXXRecordType (copied_clang_type.GetOpaqueQualType(), + "$__lldb_expr", + method_type, + lldb::eAccessPublic, + is_virtual, + is_static, + is_inline, + is_explicit, + is_attr_used, + is_artificial); } return TypeFromParser(copied_clang_type); Index: source/Expression/ClangExpressionParser.cpp =================================================================== --- source/Expression/ClangExpressionParser.cpp +++ source/Expression/ClangExpressionParser.cpp @@ -334,6 +334,8 @@ ast_context->setExternalSource(ast_source); } + m_ast_context.reset(new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str())); + m_ast_context->setASTContext(ast_context.get()); m_compiler->setASTContext(ast_context.release()); std::string module_name("$__lldb_module"); Index: source/Expression/ClangUserExpression.cpp =================================================================== --- source/Expression/ClangUserExpression.cpp +++ source/Expression/ClangUserExpression.cpp @@ -313,11 +313,11 @@ return; } - if (self_clang_type.IsObjCClassType()) + if (ClangASTContext::IsObjCClassType(self_clang_type)) { return; } - else if (self_clang_type.IsObjCObjectPointerType()) + else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) { m_in_objectivec_method = true; m_needs_object_ptr = true; Index: source/Expression/IRForTarget.cpp =================================================================== --- source/Expression/IRForTarget.cpp +++ source/Expression/IRForTarget.cpp @@ -575,14 +575,14 @@ clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), - &result_decl->getASTContext()); + lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); } else if (pointer_objcobjpointertype) { clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), - &result_decl->getASTContext()); + lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); } else { @@ -598,7 +598,7 @@ else { m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), - &result_decl->getASTContext()); + lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); } @@ -1241,7 +1241,7 @@ clang::VarDecl *decl = reinterpret_cast(ptr); lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(), - &decl->getASTContext()); + lldb_private::ClangASTContext::GetASTContext(&decl->getASTContext())); StringRef decl_name (decl->getName()); lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size()); @@ -1539,7 +1539,7 @@ { log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]", name.c_str(), - clang_type.GetQualType().getAsString().c_str(), + lldb_private::ClangASTContext::GetQualType(clang_type).getAsString().c_str(), PrintType(value_type).c_str(), value_size, value_alignment); Index: source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp =================================================================== --- source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -424,7 +424,8 @@ if (!clang_type) return return_valobj_sp; - clang::ASTContext *ast_context = clang_type.GetASTContext(); + ClangASTContext* ast = clang_type.GetTypeSystem()->AsClangASTContext(); + clang::ASTContext *ast_context = ast ? ast->getASTContext() : nullptr; if (!ast_context) return return_valobj_sp; Index: source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp =================================================================== --- source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp +++ source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp @@ -408,10 +408,6 @@ if (!clang_type) return return_valobj_sp; - clang::ASTContext *ast_context = clang_type.GetASTContext(); - if (!ast_context) - return return_valobj_sp; - //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); value.SetClangType (clang_type); Index: source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp =================================================================== --- source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -189,7 +189,7 @@ type_sp = class_types.GetTypeAtIndex(i); if (type_sp) { - if (type_sp->GetClangFullType().IsCXXClassType()) + if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType())) { if (log) log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n", Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -364,7 +364,7 @@ clang::Selector sel = ast_ctx.Selectors.getSelector(is_zero_argument ? 0 : selector_components.size(), selector_components.data()); - clang::QualType ret_type = type_realizer_sp->RealizeType(interface_decl->getASTContext(), m_type_vector[0].c_str(), for_expression).GetQualType(); + clang::QualType ret_type = ClangASTContext::GetQualType(type_realizer_sp->RealizeType(interface_decl->getASTContext(), m_type_vector[0].c_str(), for_expression)); if (ret_type.isNull()) return NULL; @@ -391,7 +391,7 @@ ++ai) { const bool for_expression = true; - clang::QualType arg_type = type_realizer_sp->RealizeType(ast_ctx, m_type_vector[ai].c_str(), for_expression).GetQualType(); + clang::QualType arg_type = ClangASTContext::GetQualType(type_realizer_sp->RealizeType(ast_ctx, m_type_vector[ai].c_str(), for_expression)); if (arg_type.isNull()) return NULL; // well, we just wasted a bunch of time. Wish we could delete the stuff we'd just made! @@ -514,7 +514,7 @@ clang::SourceLocation(), clang::SourceLocation(), &m_ast_ctx.getASTContext()->Idents.get(name), - ivar_type.GetQualType(), + ClangASTContext::GetQualType(ivar_type), type_source_info, // TypeSourceInfo * clang::ObjCIvarDecl::Public, 0, Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -92,7 +92,7 @@ ClangASTType clang_type = value.GetClangType(); if (clang_type) { - if (!clang_type.IsObjCObjectPointerType()) + if (!ClangASTContext::IsObjCObjectPointerType(clang_type)) { strm.Printf ("Value doesn't point to an ObjC object.\n"); return false; Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -139,7 +139,7 @@ ClangASTType union_type(lldb_ctx->CreateRecordType(nullptr, lldb::eAccessPublic, name.c_str(), kind, lldb::eLanguageTypeC)); if (union_type) { - union_type.StartTagDeclarationDefinition(); + ClangASTContext::StartTagDeclarationDefinition(union_type); unsigned int count = 0; for (auto element: elements) @@ -150,13 +150,12 @@ elem_name.Printf("__unnamed_%u",count); element.name = std::string(elem_name.GetData()); } - union_type.AddFieldToRecordType(element.name.c_str(), ClangASTType(&ast_ctx,element.type.getAsOpaquePtr()), lldb::eAccessPublic, element.bitfield); + ClangASTContext::AddFieldToRecordType(union_type, element.name.c_str(), ClangASTType(&ast_ctx, element.type), lldb::eAccessPublic, element.bitfield); ++count; } - - union_type.CompleteTagDeclarationDefinition(); + ClangASTContext::CompleteTagDeclarationDefinition(union_type); } - return union_type.GetQualType(); + return ClangASTContext::GetQualType(union_type); } clang::QualType @@ -171,8 +170,8 @@ ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx); if (!lldb_ctx) return clang::QualType(); - ClangASTType array_type(lldb_ctx->CreateArrayType(ClangASTType(&ast_ctx,element_type.getAsOpaquePtr()), size, false)); - return array_type.GetQualType(); + ClangASTType array_type(lldb_ctx->CreateArrayType(ClangASTType(&ast_ctx, element_type), size, false)); + return ClangASTContext::GetQualType(array_type); } // the runtime can emit these in the form of @"SomeType", giving more specifics @@ -263,7 +262,7 @@ return ast_ctx.getObjCIdType(); #endif - return ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType().GetQualType(); + return ClangASTContext::GetQualType(ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType()); } else { @@ -392,7 +391,7 @@ { StringLexer lexer(name); clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression); - return ClangASTType(&ast_ctx, qual_type.getAsOpaquePtr()); + return ClangASTType(&ast_ctx, qual_type); } return ClangASTType(); } Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1601,11 +1601,11 @@ llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed); template_param_infos.args.push_back (clang::TemplateArgument (*ast, llvm::APSInt(apint), - clang_type.GetQualType())); + ClangASTContext::GetQualType(clang_type))); } else { - template_param_infos.args.push_back (clang::TemplateArgument (clang_type.GetQualType())); + template_param_infos.args.push_back (clang::TemplateArgument (ClangASTContext::GetQualType(clang_type))); } } else @@ -1732,13 +1732,16 @@ bool Finalize() { - return m_class_opaque_type.AddObjCClassProperty (m_property_name, - m_property_opaque_type, - m_ivar_decl, - m_property_setter_name, - m_property_getter_name, - m_property_attributes, - m_metadata_ap.get()); + ClangASTContext* ast = m_class_opaque_type.GetTypeSystem()->AsClangASTContext(); + assert(ast); + return ast->AddObjCClassProperty (m_class_opaque_type, + m_property_name, + m_property_opaque_type, + m_ivar_decl, + m_property_setter_name, + m_property_getter_name, + m_property_attributes, + m_metadata_ap.get()); } private: ClangASTType m_class_opaque_type; @@ -1832,6 +1835,9 @@ uint32_t member_idx = 0; BitfieldInfo last_field_info; ModuleSP module = GetObjectFile()->GetModule(); + ClangASTContext* ast = class_clang_type.GetTypeSystem()->AsClangASTContext(); + if (ast == nullptr) + return 0; for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) { @@ -2020,7 +2026,8 @@ { if (accessibility == eAccessNone) accessibility = eAccessPublic; - class_clang_type.AddVariableToRecordType (name, + ClangASTContext::AddVariableToRecordType (class_clang_type, + name, var_type->GetClangLayoutType(), accessibility); } @@ -2137,10 +2144,12 @@ if (anon_field_info.IsValid()) { - clang::FieldDecl *unnamed_bitfield_decl = class_clang_type.AddFieldToRecordType (NULL, - GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width), - accessibility, - anon_field_info.bit_size); + clang::FieldDecl *unnamed_bitfield_decl = + ClangASTContext::AddFieldToRecordType (class_clang_type, + NULL, + GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width), + accessibility, + anon_field_info.bit_size); layout_info.field_offsets.insert( std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset)); @@ -2187,7 +2196,8 @@ } } - field_decl = class_clang_type.AddFieldToRecordType (name, + field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type, + name, member_clang_type, accessibility, bit_size); @@ -2342,13 +2352,14 @@ assert (base_class_clang_type); if (class_language == eLanguageTypeObjC) { - class_clang_type.SetObjCSuperClass(base_class_clang_type); + ast->SetObjCSuperClass(class_clang_type, base_class_clang_type); } else { - base_classes.push_back (base_class_clang_type.CreateBaseClassSpecifier (accessibility, - is_virtual, - is_base_of_class)); + base_classes.push_back (ast->CreateBaseClassSpecifier (base_class_clang_type.GetOpaqueQualType(), + accessibility, + is_virtual, + is_base_of_class)); if (is_virtual) { @@ -2363,7 +2374,7 @@ else { layout_info.base_offsets.insert( - std::make_pair(base_class_clang_type.GetAsCXXRecordDecl(), + std::make_pair(ast->GetAsCXXRecordDecl(base_class_clang_type.GetOpaqueQualType()), clang::CharUnits::fromQuantity(member_byte_offset))); } } @@ -2484,7 +2495,7 @@ bool SymbolFileDWARF::HasForwardDeclForClangType (const ClangASTType &clang_type) { - ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers(); + ClangASTType clang_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(clang_type); const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType()); return die != NULL; } @@ -2494,7 +2505,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type) { // We have a struct/union/class/enum that needs to be fully resolved. - ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers(); + ClangASTType clang_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(clang_type); const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType()); if (die == NULL) { @@ -2507,9 +2518,16 @@ // are done. m_forward_decl_clang_type_to_die.erase (clang_type_no_qualifiers.GetOpaqueQualType()); + ClangASTContext* ast = clang_type.GetTypeSystem()->AsClangASTContext(); + if (ast == NULL) + { + // Not a clang type + return true; + } + // Disable external storage for this type so we don't get anymore // clang::ExternalASTSource queries for this type. - clang_type.SetHasExternalStorage (false); + ast->SetHasExternalStorage (clang_type.GetOpaqueQualType(), false); DWARFDebugInfo* debug_info = DebugInfo(); @@ -2540,12 +2558,12 @@ if (die->HasChildren()) { LanguageType class_language = eLanguageTypeUnknown; - if (clang_type.IsObjCObjectOrInterfaceType()) + if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) { class_language = eLanguageTypeObjC; // For objective C we don't start the definition when // the class is created. - clang_type.StartTagDeclarationDefinition (); + ClangASTContext::StartTagDeclarationDefinition (clang_type); } int tag_decl_kind = -1; @@ -2652,7 +2670,7 @@ if (class_language != eLanguageTypeObjC) { if (is_a_class && tag_decl_kind != clang::TTK_Class) - clang_type.SetTagTypeKind (clang::TTK_Class); + GetClangASTContext().SetTagTypeKind (ClangASTContext::GetQualType(clang_type), clang::TTK_Class); } // Since DW_TAG_structure_type gets used for both classes @@ -2669,9 +2687,10 @@ { // This is a class and all members that didn't have // their access specified are private. - clang_type.SetDefaultAccessForRecordFields (eAccessPrivate, - &member_accessibilities.front(), - member_accessibilities.size()); + GetClangASTContext().SetDefaultAccessForRecordFields (ast->GetAsRecordDecl(clang_type), + eAccessPrivate, + &member_accessibilities.front(), + member_accessibilities.size()); } if (!base_classes.empty()) @@ -2702,24 +2721,26 @@ // below. Since we provide layout assistance, all ivars in this // class and other classes will be fine, this is the best we can do // short of crashing. - base_class_type.StartTagDeclarationDefinition (); - base_class_type.CompleteTagDeclarationDefinition (); + + ClangASTContext::StartTagDeclarationDefinition (base_class_type); + ClangASTContext::CompleteTagDeclarationDefinition (base_class_type); } } } - clang_type.SetBaseClassesForClassType (&base_classes.front(), - base_classes.size()); + ast->SetBaseClassesForClassType (clang_type.GetOpaqueQualType(), + &base_classes.front(), + base_classes.size()); // Clang will copy each CXXBaseSpecifier in "base_classes" // so we have to free them all. - ClangASTType::DeleteBaseClassSpecifiers (&base_classes.front(), - base_classes.size()); + ClangASTContext::DeleteBaseClassSpecifiers (&base_classes.front(), + base_classes.size()); } } } - clang_type.BuildIndirectFields (); - clang_type.CompleteTagDeclarationDefinition (); + ClangASTContext::BuildIndirectFields (clang_type); + ClangASTContext::CompleteTagDeclarationDefinition (clang_type); if (!layout_info.field_offsets.empty() || !layout_info.base_offsets.empty() || @@ -2730,7 +2751,7 @@ if (layout_info.bit_size == 0) layout_info.bit_size = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, 0) * 8; - clang::CXXRecordDecl *record_decl = clang_type.GetAsCXXRecordDecl(); + clang::CXXRecordDecl *record_decl = ast->GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); if (record_decl) { if (log) @@ -2795,7 +2816,7 @@ return (bool)clang_type; case DW_TAG_enumeration_type: - clang_type.StartTagDeclarationDefinition (); + ClangASTContext::StartTagDeclarationDefinition (clang_type); if (die->HasChildren()) { SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu)); @@ -2803,7 +2824,7 @@ clang_type.IsIntegerType(is_signed); ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), dwarf_cu, die); } - clang_type.CompleteTagDeclarationDefinition (); + ClangASTContext::CompleteTagDeclarationDefinition (clang_type); return (bool)clang_type; default: @@ -4675,12 +4696,17 @@ if (name && name[0] && got_value) { - clang_type.AddEnumerationValueToEnumerationType (clang_type.GetEnumerationIntegerType(), - decl, - name, - enum_value, - enumerator_byte_size * 8); - ++enumerators_added; + ClangASTContext* ast = clang_type.GetTypeSystem()->AsClangASTContext(); + if (ast) + { + ast->AddEnumerationValueToEnumerationType (clang_type.GetOpaqueQualType(), + ast->GetEnumerationIntegerType(clang_type.GetOpaqueQualType()), + decl, + name, + enum_value, + enumerator_byte_size * 8); + ++enumerators_added; + } } } } @@ -4947,7 +4973,7 @@ Type* type = ResolveType (cu, decl_ctx_die); if (type) { - clang::DeclContext *decl_ctx = type->GetClangForwardType().GetDeclContextForType (); + clang::DeclContext *decl_ctx = GetClangASTContext().GetDeclContextForType(type->GetClangForwardType()); if (decl_ctx) { LinkDeclContextToDIE (decl_ctx, decl_ctx_die); @@ -6249,7 +6275,7 @@ } assert (tag_decl_kind != -1); bool clang_type_was_created = false; - clang_type.SetClangType(ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die)); + clang_type.SetClangType(&ast, m_forward_decl_die_to_clang_type.lookup (die)); if (!clang_type) { const DWARFDebugInfoEntry *decl_ctx_die; @@ -6306,7 +6332,7 @@ // Store a forward declaration to this class type in case any // parameters in any class methods need it for the clang // types for function prototypes. - LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die); + LinkDeclContextToDIE(ast.GetDeclContextForType(clang_type), die); type_sp.reset (new Type (MakeUserID(die->GetOffset()), this, type_name_const_str, @@ -6371,12 +6397,12 @@ if (die->HasChildren() == false) { // No children for this struct/union/class, lets finish it - clang_type.StartTagDeclarationDefinition (); - clang_type.CompleteTagDeclarationDefinition (); + ClangASTContext::StartTagDeclarationDefinition (clang_type); + ClangASTContext::CompleteTagDeclarationDefinition (clang_type); if (tag == DW_TAG_structure_type) // this only applies in C { - clang::RecordDecl *record_decl = clang_type.GetAsRecordDecl(); + clang::RecordDecl *record_decl = ClangASTContext::GetAsRecordDecl(clang_type); if (record_decl) m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo())); @@ -6394,7 +6420,7 @@ if (class_language != eLanguageTypeObjC && class_language != eLanguageTypeObjC_plus_plus) - clang_type.StartTagDeclarationDefinition (); + ClangASTContext::StartTagDeclarationDefinition (clang_type); // Leave this as a forward declaration until we need // to know the details of the type. lldb_private::Type @@ -6402,8 +6428,8 @@ // "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition(Type *)" // When the definition needs to be defined. m_forward_decl_die_to_clang_type[die] = clang_type.GetOpaqueQualType(); - m_forward_decl_clang_type_to_die[clang_type.RemoveFastQualifiers().GetOpaqueQualType()] = die; - clang_type.SetHasExternalStorage (true); + m_forward_decl_clang_type_to_die[ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = die; + ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), true); } } @@ -6459,7 +6485,7 @@ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr); ClangASTType enumerator_clang_type; - clang_type.SetClangType (ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die)); + clang_type.SetClangType (&ast, m_forward_decl_die_to_clang_type.lookup (die)); if (!clang_type) { if (encoding_uid != DW_INVALID_OFFSET) @@ -6481,10 +6507,10 @@ } else { - enumerator_clang_type = clang_type.GetEnumerationIntegerType (); + enumerator_clang_type = ast.GetEnumerationIntegerType (clang_type.GetOpaqueQualType()); } - LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die); + LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), die); type_sp.reset( new Type (MakeUserID(die->GetOffset()), this, @@ -6497,7 +6523,7 @@ clang_type, Type::eResolveStateForward)); - clang_type.StartTagDeclarationDefinition (); + ClangASTContext::StartTagDeclarationDefinition (clang_type); if (die->HasChildren()) { SymbolContext cu_sc(GetCompUnitForDWARFCompUnit(dwarf_cu)); @@ -6505,7 +6531,7 @@ enumerator_clang_type.IsIntegerType(is_signed); ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), dwarf_cu, die); } - clang_type.CompleteTagDeclarationDefinition (); + ClangASTContext::CompleteTagDeclarationDefinition (clang_type); } } break; @@ -6695,7 +6721,7 @@ if (complete_objc_class_type_sp) { ClangASTType type_clang_forward_type = complete_objc_class_type_sp->GetClangForwardType(); - if (type_clang_forward_type.IsObjCObjectOrInterfaceType ()) + if (ClangASTContext::IsObjCObjectOrInterfaceType(type_clang_forward_type)) class_opaque_type = type_clang_forward_type; } } @@ -6707,10 +6733,11 @@ if (accessibility == eAccessNone) accessibility = eAccessPublic; - clang::ObjCMethodDecl *objc_method_decl = class_opaque_type.AddMethodToObjCObjectType (type_name_cstr, - clang_type, - accessibility, - is_artificial); + clang::ObjCMethodDecl *objc_method_decl = ast.AddMethodToObjCObjectType (class_opaque_type, + type_name_cstr, + clang_type, + accessibility, + is_artificial); type_handled = objc_method_decl != NULL; if (type_handled) { @@ -6830,7 +6857,7 @@ else { ClangASTType class_opaque_type = class_type->GetClangForwardType(); - if (class_opaque_type.IsCXXClassType ()) + if (ClangASTContext::IsCXXClassType(class_opaque_type)) { if (class_opaque_type.IsBeingDefined ()) { @@ -6858,15 +6885,16 @@ const bool is_attr_used = false; - cxx_method_decl = class_opaque_type.AddMethodToCXXRecordType (type_name_cstr, - clang_type, - accessibility, - is_virtual, - is_static, - is_inline, - is_explicit, - is_attr_used, - is_artificial); + cxx_method_decl = ast.AddMethodToCXXRecordType (class_opaque_type.GetOpaqueQualType(), + type_name_cstr, + clang_type, + accessibility, + is_virtual, + is_static, + is_inline, + is_explicit, + is_attr_used, + is_artificial); type_handled = cxx_method_decl != NULL; @@ -7119,7 +7147,7 @@ ClangASTType pointee_clang_type = pointee_type->GetClangForwardType(); ClangASTType class_clang_type = class_type->GetClangLayoutType(); - clang_type = pointee_clang_type.CreateMemberPointerType(class_clang_type); + clang_type = ClangASTContext::CreateMemberPointerType(pointee_clang_type, class_clang_type); byte_size = clang_type.GetByteSize(nullptr); @@ -8036,7 +8064,7 @@ Type *matching_type = ResolveType (dwarf_cu, die); - clang::QualType qual_type = matching_type->GetClangForwardType().GetQualType(); + clang::QualType qual_type = ClangASTContext::GetQualType(matching_type->GetClangForwardType()); if (const clang::TagType *tag_type = llvm::dyn_cast(qual_type.getTypePtr())) { Index: source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp =================================================================== --- source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp +++ source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp @@ -448,12 +448,13 @@ { ClangASTType uint16 = ast_ctx->GetIntTypeFromBitSize(16, false); ClangASTType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType(nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s", clang::TTK_Struct, lldb::eLanguageTypeC); - dispatch_tsd_indexes_s.StartTagDeclarationDefinition(); - dispatch_tsd_indexes_s.AddFieldToRecordType ("dti_version", uint16, lldb::eAccessPublic, 0); - dispatch_tsd_indexes_s.AddFieldToRecordType ("dti_queue_index", uint16, lldb::eAccessPublic, 0); - dispatch_tsd_indexes_s.AddFieldToRecordType ("dti_voucher_index", uint16, lldb::eAccessPublic, 0); - dispatch_tsd_indexes_s.AddFieldToRecordType ("dti_qos_class_index", uint16, lldb::eAccessPublic, 0); - dispatch_tsd_indexes_s.CompleteTagDeclarationDefinition(); + + ClangASTContext::StartTagDeclarationDefinition(dispatch_tsd_indexes_s); + ClangASTContext::AddFieldToRecordType (dispatch_tsd_indexes_s, "dti_version", uint16, lldb::eAccessPublic, 0); + ClangASTContext::AddFieldToRecordType (dispatch_tsd_indexes_s, "dti_queue_index", uint16, lldb::eAccessPublic, 0); + ClangASTContext::AddFieldToRecordType (dispatch_tsd_indexes_s, "dti_voucher_index", uint16, lldb::eAccessPublic, 0); + ClangASTContext::AddFieldToRecordType (dispatch_tsd_indexes_s, "dti_qos_class_index", uint16, lldb::eAccessPublic, 0); + ClangASTContext::CompleteTagDeclarationDefinition(dispatch_tsd_indexes_s); ProcessStructReader struct_reader (m_process, m_dispatch_tsd_indexes_addr, dispatch_tsd_indexes_s); Index: source/Symbol/CMakeLists.txt =================================================================== --- source/Symbol/CMakeLists.txt +++ source/Symbol/CMakeLists.txt @@ -24,6 +24,7 @@ Symtab.cpp Type.cpp TypeList.cpp + TypeSystem.cpp UnwindPlan.cpp UnwindTable.cpp Variable.cpp Index: source/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -41,6 +41,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" +#include "clang/AST/VTableBuilder.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" @@ -58,14 +59,18 @@ #include #endif +#include "llvm/Support/Signals.h" + #include "lldb/Core/ArchSpec.h" #include "lldb/Core/dwarf.h" #include "lldb/Core/Flags.h" #include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" +#include "lldb/Core/StreamFile.h" #include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Expression/ASTDumper.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/VerifyDecl.h" #include "lldb/Target/ExecutionContext.h" @@ -291,7 +296,8 @@ m_callback_tag_decl (nullptr), m_callback_objc_decl (nullptr), m_callback_baton (nullptr), - m_pointer_byte_size (0) + m_pointer_byte_size (0), + m_ast_owned(false) { if (target_triple && target_triple[0]) @@ -306,6 +312,8 @@ if (m_ast_ap.get()) { GetASTMap().Erase(m_ast_ap.get()); + if (!m_ast_owned) + m_ast_ap.release(); } m_builtins_ap.reset(); @@ -389,13 +397,23 @@ } } - +void +ClangASTContext::setASTContext(clang::ASTContext *ast_ctx) +{ + if (!m_ast_owned) { + m_ast_ap.release(); + } + m_ast_owned = false; + m_ast_ap.reset(ast_ctx); + GetASTMap().Insert(ast_ctx, this); +} ASTContext * ClangASTContext::getASTContext() { if (m_ast_ap.get() == nullptr) { + m_ast_owned = true; m_ast_ap.reset(new ASTContext (*getLanguageOptions(), *getSourceManager(), *getIdentifierTable(), @@ -572,57 +590,56 @@ { if (!ast) return ClangASTType(); - switch (encoding) { case eEncodingInvalid: if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) - return ClangASTType (ast, ast->VoidPtrTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->VoidPtrTy); break; case eEncodingUint: if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedCharTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedShortTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedIntTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return ClangASTType (ast, ast->UnsignedLongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedLongTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return ClangASTType (ast, ast->UnsignedLongLongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedLongLongTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return ClangASTType (ast, ast->UnsignedInt128Ty.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedInt128Ty); break; case eEncodingSint: if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return ClangASTType (ast, ast->CharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->CharTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return ClangASTType (ast, ast->ShortTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->ShortTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return ClangASTType (ast, ast->IntTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->IntTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return ClangASTType (ast, ast->LongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return ClangASTType (ast, ast->LongLongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongLongTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return ClangASTType (ast, ast->Int128Ty.getAsOpaquePtr()); + return ClangASTType (ast, ast->Int128Ty); break; case eEncodingIEEE754: if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->FloatTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->DoubleTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongDoubleTy); break; case eEncodingVector: // Sanity check that bit_size is a multiple of 8's. if (bit_size && !(bit_size & 0x7u)) - return ClangASTType (ast, ast->getExtVectorType (ast->UnsignedCharTy, bit_size/8).getAsOpaquePtr()); + return ClangASTType (ast, ast->getExtVectorType (ast->UnsignedCharTy, bit_size/8)); break; } @@ -827,7 +844,7 @@ } if (clang_type) - return ClangASTType (ast, clang_type); + return ClangASTType (GetASTContext(ast), clang_type); } return ClangASTType(); } @@ -849,18 +866,18 @@ case DW_ATE_address: if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) - return ClangASTType (ast, ast->VoidPtrTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->VoidPtrTy); break; case DW_ATE_boolean: if (QualTypeMatchesBitSize (bit_size, ast, ast->BoolTy)) - return ClangASTType (ast, ast->BoolTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->BoolTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedCharTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedShortTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedIntTy); break; case DW_ATE_lo_user: @@ -870,39 +887,39 @@ if (::strstr(type_name, "complex")) { ClangASTType complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("int", DW_ATE_signed, bit_size/2); - return ClangASTType (ast, ast->getComplexType (complex_int_clang_type.GetQualType()).getAsOpaquePtr()); + return ClangASTType (ast, ast->getComplexType (GetQualType(complex_int_clang_type))); } } break; case DW_ATE_complex_float: if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatComplexTy)) - return ClangASTType (ast, ast->FloatComplexTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->FloatComplexTy); else if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleComplexTy)) - return ClangASTType (ast, ast->DoubleComplexTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->DoubleComplexTy); else if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleComplexTy)) - return ClangASTType (ast, ast->LongDoubleComplexTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongDoubleComplexTy); else { ClangASTType complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("float", DW_ATE_float, bit_size/2); - return ClangASTType (ast, ast->getComplexType (complex_float_clang_type.GetQualType()).getAsOpaquePtr()); + return ClangASTType (ast, ast->getComplexType (GetQualType(complex_float_clang_type))); } break; case DW_ATE_float: if (streq(type_name, "float") && QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->FloatTy); if (streq(type_name, "double") && QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->DoubleTy); if (streq(type_name, "long double") && QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongDoubleTy); // Fall back to not requring a name match if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->FloatTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->DoubleTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongDoubleTy); break; case DW_ATE_signed: @@ -911,57 +928,57 @@ if (streq(type_name, "wchar_t") && QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy) && (getTargetInfo() && TargetInfo::isTypeSigned (getTargetInfo()->getWCharType()))) - return ClangASTType (ast, ast->WCharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->WCharTy); if (streq(type_name, "void") && QualTypeMatchesBitSize (bit_size, ast, ast->VoidTy)) - return ClangASTType (ast, ast->VoidTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->VoidTy); if (strstr(type_name, "long long") && QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return ClangASTType (ast, ast->LongLongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongLongTy); if (strstr(type_name, "long") && QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return ClangASTType (ast, ast->LongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongTy); if (strstr(type_name, "short") && QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return ClangASTType (ast, ast->ShortTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->ShortTy); if (strstr(type_name, "char")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return ClangASTType (ast, ast->CharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->CharTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return ClangASTType (ast, ast->SignedCharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->SignedCharTy); } if (strstr(type_name, "int")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return ClangASTType (ast, ast->IntTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->IntTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return ClangASTType (ast, ast->Int128Ty.getAsOpaquePtr()); + return ClangASTType (ast, ast->Int128Ty); } } // We weren't able to match up a type name, just search by size if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return ClangASTType (ast, ast->CharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->CharTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return ClangASTType (ast, ast->ShortTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->ShortTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return ClangASTType (ast, ast->IntTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->IntTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return ClangASTType (ast, ast->LongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return ClangASTType (ast, ast->LongLongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->LongLongTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return ClangASTType (ast, ast->Int128Ty.getAsOpaquePtr()); + return ClangASTType (ast, ast->Int128Ty); break; case DW_ATE_signed_char: if (ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return ClangASTType (ast, ast->CharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->CharTy); } if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return ClangASTType (ast, ast->SignedCharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->SignedCharTy); break; case DW_ATE_unsigned: @@ -972,62 +989,62 @@ if (QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy)) { if (!(getTargetInfo() && TargetInfo::isTypeSigned (getTargetInfo()->getWCharType()))) - return ClangASTType (ast, ast->WCharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->WCharTy); } } if (strstr(type_name, "long long")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return ClangASTType (ast, ast->UnsignedLongLongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedLongLongTy); } else if (strstr(type_name, "long")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return ClangASTType (ast, ast->UnsignedLongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedLongTy); } else if (strstr(type_name, "short")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedShortTy); } else if (strstr(type_name, "char")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedCharTy); } else if (strstr(type_name, "int")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedIntTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return ClangASTType (ast, ast->UnsignedInt128Ty.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedInt128Ty); } } // We weren't able to match up a type name, just search by size if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedCharTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedShortTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedIntTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return ClangASTType (ast, ast->UnsignedLongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedLongTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return ClangASTType (ast, ast->UnsignedLongLongTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedLongLongTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return ClangASTType (ast, ast->UnsignedInt128Ty.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedInt128Ty); break; case DW_ATE_unsigned_char: if (!ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return ClangASTType (ast, ast->CharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->CharTy); } if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedCharTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnsignedShortTy); break; case DW_ATE_imaginary_float: @@ -1038,11 +1055,11 @@ { if (streq(type_name, "char16_t")) { - return ClangASTType (ast, ast->Char16Ty.getAsOpaquePtr()); + return ClangASTType (ast, ast->Char16Ty); } else if (streq(type_name, "char32_t")) { - return ClangASTType (ast, ast->Char32Ty.getAsOpaquePtr()); + return ClangASTType (ast, ast->Char32Ty); } } break; @@ -1065,7 +1082,7 @@ ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast) { if (ast) - return ClangASTType (ast, ast->UnknownAnyTy.getAsOpaquePtr()); + return ClangASTType (ast, ast->UnknownAnyTy); return ClangASTType(); } @@ -1078,7 +1095,7 @@ if (is_const) char_type.addConst(); - return ClangASTType (ast, ast->getPointerType(char_type).getAsOpaquePtr()); + return ClangASTType (ast, ast->getPointerType(char_type)); } clang::DeclContext * @@ -1092,15 +1109,17 @@ ClangASTType src) { FileSystemOptions file_system_options; - ASTContext *src_ast = src.GetASTContext(); + ClangASTContext *src_ast = src.GetTypeSystem()->AsClangASTContext(); + if (src_ast == nullptr) + return ClangASTType(); FileManager file_manager (file_system_options); ASTImporter importer(*dst_ast, file_manager, - *src_ast, file_manager, + *src_ast->getASTContext(), file_manager, false); - QualType dst (importer.Import(src.GetQualType())); + QualType dst (importer.Import(GetQualType(src))); - return ClangASTType (dst_ast, dst.getAsOpaquePtr()); + return ClangASTType (dst_ast, dst); } @@ -1123,15 +1142,15 @@ ClangASTType type2, bool ignore_qualifiers) { - ASTContext *ast = type1.GetASTContext(); - if (ast != type2.GetASTContext()) + TypeSystem *ast = type1.GetTypeSystem(); + if (!ast->AsClangASTContext() || ast != type2.GetTypeSystem()) return false; if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType()) return true; - QualType type1_qual = type1.GetQualType(); - QualType type2_qual = type2.GetQualType(); + QualType type1_qual = GetQualType(type1); + QualType type2_qual = GetQualType(type2); if (ignore_qualifiers) { @@ -1139,7 +1158,7 @@ type2_qual = type2_qual.getUnqualifiedType(); } - return ast->hasSameType (type1_qual, type2_qual); + return ast->AsClangASTContext()->getASTContext()->hasSameType (type1_qual, type2_qual); } ClangASTType @@ -1161,7 +1180,7 @@ // AST if our AST didn't already exist... ASTContext *ast = &decl->getASTContext(); if (ast) - return ClangASTType (ast, ast->getTagDeclType(decl).getAsOpaquePtr()); + return ClangASTType (ast, ast->getTagDeclType(decl)); return ClangASTType(); } @@ -1173,7 +1192,7 @@ // AST if our AST didn't already exist... ASTContext *ast = &decl->getASTContext(); if (ast) - return ClangASTType (ast, ast->getObjCInterfaceType(decl).getAsOpaquePtr()); + return ClangASTType (ast, ast->getObjCInterfaceType(decl)); return ClangASTType(); } @@ -1230,7 +1249,7 @@ if (decl_ctx) decl_ctx->addDecl (decl); - return ClangASTType(ast, ast->getTagDeclType(decl).getAsOpaquePtr()); + return ClangASTType(ast, ast->getTagDeclType(decl)); } return ClangASTType(); } @@ -1441,7 +1460,7 @@ { ASTContext *ast = getASTContext(); if (ast) - return ClangASTType(ast, ast->getTagDeclType(class_template_specialization_decl).getAsOpaquePtr()); + return ClangASTType(ast, ast->getTagDeclType(class_template_specialization_decl)); } return ClangASTType(); } @@ -1765,7 +1784,7 @@ SourceLocation(), SourceLocation(), DeclarationName (&ast->Idents.get(name)), - function_clang_type.GetQualType(), + GetQualType(function_clang_type), nullptr, (clang::StorageClass)storage, is_inline, @@ -1779,7 +1798,7 @@ SourceLocation(), SourceLocation(), DeclarationName (), - function_clang_type.GetQualType(), + GetQualType(function_clang_type), nullptr, (clang::StorageClass)storage, is_inline, @@ -1807,7 +1826,7 @@ assert (ast != nullptr); std::vector qual_type_args; for (unsigned i=0; igetFunctionType (result_type.GetQualType(), + return ClangASTType (ast, ast->getFunctionType (GetQualType(result_type), qual_type_args, - proto_info).getAsOpaquePtr()); + proto_info)); } ParmVarDecl * @@ -1831,7 +1850,7 @@ SourceLocation(), SourceLocation(), name && name[0] ? &ast->Idents.get(name) : nullptr, - param_type.GetQualType(), + GetQualType(param_type), nullptr, (clang::StorageClass)storage, nullptr); @@ -1859,7 +1878,7 @@ if (is_vector) { - return ClangASTType (ast, ast->getExtVectorType(element_type.GetQualType(), element_count).getAsOpaquePtr()); + return ClangASTType (ast, ast->getExtVectorType(GetQualType(element_type), element_count)); } else { @@ -1867,16 +1886,16 @@ llvm::APInt ap_element_count (64, element_count); if (element_count == 0) { - return ClangASTType (ast, ast->getIncompleteArrayType (element_type.GetQualType(), + return ClangASTType (ast, ast->getIncompleteArrayType (GetQualType(element_type), ArrayType::Normal, - 0).getAsOpaquePtr()); + 0)); } else { - return ClangASTType (ast, ast->getConstantArrayType (element_type.GetQualType(), + return ClangASTType (ast, ast->getConstantArrayType (GetQualType(element_type), ap_element_count, ArrayType::Normal, - 0).getAsOpaquePtr()); + 0)); } } } @@ -1892,34 +1911,34 @@ if ((type = GetTypeForIdentifier(type_name)).IsValid()) return type; type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); - type.StartTagDeclarationDefinition(); + StartTagDeclarationDefinition(type); for (const auto& field : type_fields) - type.AddFieldToRecordType(field.first, field.second, lldb::eAccessPublic, 0); + AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic, 0); if (packed) - type.SetIsPacked(); - type.CompleteTagDeclarationDefinition(); + SetIsPacked(type); + CompleteTagDeclarationDefinition(type); return type; } #pragma mark Enumeration Types ClangASTType -ClangASTContext::CreateEnumerationType +ClangASTContext::CreateEnumerationType ( - const char *name, - DeclContext *decl_ctx, - const Declaration &decl, - const ClangASTType &integer_clang_type -) + const char *name, + DeclContext *decl_ctx, + const Declaration &decl, + const ClangASTType &integer_clang_type + ) { // TODO: Do something intelligent with the Declaration object passed in // like maybe filling in the SourceLocation with it... ASTContext *ast = getASTContext(); - + // TODO: ask about these... -// const bool IsScoped = false; -// const bool IsFixed = false; - + // const bool IsScoped = false; + // const bool IsFixed = false; + EnumDecl *enum_decl = EnumDecl::Create (*ast, decl_ctx, SourceLocation(), @@ -1934,11 +1953,11 @@ if (enum_decl) { // TODO: check if we should be setting the promotion type too? - enum_decl->setIntegerType(integer_clang_type.GetQualType()); + enum_decl->setIntegerType(GetQualType(integer_clang_type)); enum_decl->setAccess(AS_public); // TODO respect what's in the debug info - return ClangASTType (ast, ast->getTagDeclType(enum_decl).getAsOpaquePtr()); + return ClangASTType (ast, ast->getTagDeclType(enum_decl)); } return ClangASTType(); } @@ -1993,42 +2012,42 @@ if (is_signed) { if (bit_size == ast->getTypeSize(ast->SignedCharTy)) - return ClangASTType(ast, ast->SignedCharTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->SignedCharTy); if (bit_size == ast->getTypeSize(ast->ShortTy)) - return ClangASTType(ast, ast->ShortTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->ShortTy); if (bit_size == ast->getTypeSize(ast->IntTy)) - return ClangASTType(ast, ast->IntTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->IntTy); if (bit_size == ast->getTypeSize(ast->LongTy)) - return ClangASTType(ast, ast->LongTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->LongTy); if (bit_size == ast->getTypeSize(ast->LongLongTy)) - return ClangASTType(ast, ast->LongLongTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->LongLongTy); if (bit_size == ast->getTypeSize(ast->Int128Ty)) - return ClangASTType(ast, ast->Int128Ty.getAsOpaquePtr()); + return ClangASTType(ast, ast->Int128Ty); } else { if (bit_size == ast->getTypeSize(ast->UnsignedCharTy)) - return ClangASTType(ast, ast->UnsignedCharTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->UnsignedCharTy); if (bit_size == ast->getTypeSize(ast->UnsignedShortTy)) - return ClangASTType(ast, ast->UnsignedShortTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->UnsignedShortTy); if (bit_size == ast->getTypeSize(ast->UnsignedIntTy)) - return ClangASTType(ast, ast->UnsignedIntTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->UnsignedIntTy); if (bit_size == ast->getTypeSize(ast->UnsignedLongTy)) - return ClangASTType(ast, ast->UnsignedLongTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->UnsignedLongTy); if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy)) - return ClangASTType(ast, ast->UnsignedLongLongTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->UnsignedLongLongTy); if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty)) - return ClangASTType(ast, ast->UnsignedInt128Ty.getAsOpaquePtr()); + return ClangASTType(ast, ast->UnsignedInt128Ty); } } return ClangASTType(); @@ -2049,13 +2068,13 @@ if (ast) { if (bit_size == ast->getTypeSize(ast->FloatTy)) - return ClangASTType(ast, ast->FloatTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->FloatTy); else if (bit_size == ast->getTypeSize(ast->DoubleTy)) - return ClangASTType(ast, ast->DoubleTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->DoubleTy); else if (bit_size == ast->getTypeSize(ast->LongDoubleTy)) - return ClangASTType(ast, ast->LongDoubleTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->LongDoubleTy); else if (bit_size == ast->getTypeSize(ast->HalfTy)) - return ClangASTType(ast, ast->HalfTy.getAsOpaquePtr()); + return ClangASTType(ast, ast->HalfTy); } return ClangASTType(); } @@ -2205,3 +2224,6602 @@ return false; } + +bool +ClangASTContext::SetTagTypeKind (clang::QualType tag_qual_type, int kind) const +{ + const clang::Type *clang_type = tag_qual_type.getTypePtr(); + if (clang_type) + { + const clang::TagType *tag_type = llvm::dyn_cast(clang_type); + if (tag_type) + { + clang::TagDecl *tag_decl = llvm::dyn_cast(tag_type->getDecl()); + if (tag_decl) + { + tag_decl->setTagKind ((clang::TagDecl::TagKind)kind); + return true; + } + } + } + return false; +} + + +bool +ClangASTContext::SetDefaultAccessForRecordFields (clang::RecordDecl* record_decl, + int default_accessibility, + int *assigned_accessibilities, + size_t num_assigned_accessibilities) +{ + if (record_decl) + { + uint32_t field_idx; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), field_end = record_decl->field_end(), field_idx = 0; + field != field_end; + ++field, ++field_idx) + { + // If no accessibility was assigned, assign the correct one + if (field_idx < num_assigned_accessibilities && assigned_accessibilities[field_idx] == clang::AS_none) + field->setAccess ((clang::AccessSpecifier)default_accessibility); + } + return true; + } + return false; +} + +clang::DeclContext * +ClangASTContext::GetDeclContextForType (clang::QualType type) +{ + if (type.isNull()) + return nullptr; + + clang::QualType qual_type = type.getCanonicalType(); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::UnaryTransform: break; + case clang::Type::FunctionNoProto: break; + case clang::Type::FunctionProto: break; + case clang::Type::IncompleteArray: break; + case clang::Type::VariableArray: break; + case clang::Type::ConstantArray: break; + case clang::Type::DependentSizedArray: break; + case clang::Type::ExtVector: break; + case clang::Type::DependentSizedExtVector: break; + case clang::Type::Vector: break; + case clang::Type::Builtin: break; + case clang::Type::BlockPointer: break; + case clang::Type::Pointer: break; + case clang::Type::LValueReference: break; + case clang::Type::RValueReference: break; + case clang::Type::MemberPointer: break; + case clang::Type::Complex: break; + case clang::Type::ObjCObject: break; + case clang::Type::ObjCInterface: return llvm::cast(qual_type.getTypePtr())->getInterface(); + case clang::Type::ObjCObjectPointer: return GetDeclContextForType (llvm::cast(qual_type.getTypePtr())->getPointeeType()); + case clang::Type::Record: return llvm::cast(qual_type)->getDecl(); + case clang::Type::Enum: return llvm::cast(qual_type)->getDecl(); + case clang::Type::Typedef: return GetDeclContextForType (llvm::cast(qual_type)->getDecl()->getUnderlyingType()); + case clang::Type::Elaborated: return GetDeclContextForType (llvm::cast(qual_type)->getNamedType()); + case clang::Type::Paren: return GetDeclContextForType (llvm::cast(qual_type)->desugar()); + case clang::Type::TypeOfExpr: break; + case clang::Type::TypeOf: break; + case clang::Type::Decltype: break; + //case clang::Type::QualifiedName: break; + case clang::Type::TemplateSpecialization: break; + case clang::Type::DependentTemplateSpecialization: break; + case clang::Type::TemplateTypeParm: break; + case clang::Type::SubstTemplateTypeParm: break; + case clang::Type::SubstTemplateTypeParmPack:break; + case clang::Type::PackExpansion: break; + case clang::Type::UnresolvedUsing: break; + case clang::Type::Attributed: break; + case clang::Type::Auto: break; + case clang::Type::InjectedClassName: break; + case clang::Type::DependentName: break; + case clang::Type::Atomic: break; + case clang::Type::Adjusted: break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: break; + } + // No DeclContext in this type... + return nullptr; +} + +static bool +GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool allow_completion = true) +{ + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::ConstantArray: + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: + { + const clang::ArrayType *array_type = llvm::dyn_cast(qual_type.getTypePtr()); + + if (array_type) + return GetCompleteQualType (ast, array_type->getElementType(), allow_completion); + } + break; + + case clang::Type::Record: + case clang::Type::Enum: + { + const clang::TagType *tag_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (tag_type) + { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) + { + if (tag_decl->isCompleteDefinition()) + return true; + + if (!allow_completion) + return false; + + if (tag_decl->hasExternalLexicalStorage()) + { + if (ast) + { + clang::ExternalASTSource *external_ast_source = ast->getExternalSource(); + if (external_ast_source) + { + external_ast_source->CompleteType(tag_decl); + return !tag_type->isIncompleteType(); + } + } + } + return false; + } + } + + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + // We currently can't complete objective C types through the newly added ASTContext + // because it only supports TagDecl objects right now... + if (class_interface_decl) + { + if (class_interface_decl->getDefinition()) + return true; + + if (!allow_completion) + return false; + + if (class_interface_decl->hasExternalLexicalStorage()) + { + if (ast) + { + clang::ExternalASTSource *external_ast_source = ast->getExternalSource(); + if (external_ast_source) + { + external_ast_source->CompleteType (class_interface_decl); + return !objc_class_type->isIncompleteType(); + } + } + } + return false; + } + } + } + break; + + case clang::Type::Typedef: + return GetCompleteQualType (ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType(), allow_completion); + + case clang::Type::Elaborated: + return GetCompleteQualType (ast, llvm::cast(qual_type)->getNamedType(), allow_completion); + + case clang::Type::Paren: + return GetCompleteQualType (ast, llvm::cast(qual_type)->desugar(), allow_completion); + + default: + break; + } + + return true; +} + +static clang::ObjCIvarDecl::AccessControl +ConvertAccessTypeToObjCIvarAccessControl (AccessType access) +{ + switch (access) + { + case eAccessNone: return clang::ObjCIvarDecl::None; + case eAccessPublic: return clang::ObjCIvarDecl::Public; + case eAccessPrivate: return clang::ObjCIvarDecl::Private; + case eAccessProtected: return clang::ObjCIvarDecl::Protected; + case eAccessPackage: return clang::ObjCIvarDecl::Package; + } + return clang::ObjCIvarDecl::None; +} + + +//---------------------------------------------------------------------- +// Tests +//---------------------------------------------------------------------- + +bool +ClangASTContext::IsAggregateType (void* type) +{ + clang::QualType qual_type (GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: + case clang::Type::ConstantArray: + case clang::Type::ExtVector: + case clang::Type::Vector: + case clang::Type::Record: + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + return true; + case clang::Type::Elaborated: + return IsAggregateType(llvm::cast(qual_type)->getNamedType().getAsOpaquePtr()); + case clang::Type::Typedef: + return IsAggregateType(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); + case clang::Type::Paren: + return IsAggregateType(llvm::cast(qual_type)->desugar().getAsOpaquePtr()); + default: + break; + } + // The clang type does have a value + return false; +} + +bool +ClangASTContext::IsArrayType (void* type, + ClangASTType *element_type_ptr, + uint64_t *size, + bool *is_incomplete) +{ + clang::QualType qual_type (GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + default: + break; + + case clang::Type::ConstantArray: + if (element_type_ptr) + element_type_ptr->SetClangType (getASTContext(), llvm::cast(qual_type)->getElementType()); + if (size) + *size = llvm::cast(qual_type)->getSize().getLimitedValue(ULLONG_MAX); + return true; + + case clang::Type::IncompleteArray: + if (element_type_ptr) + element_type_ptr->SetClangType (getASTContext(), llvm::cast(qual_type)->getElementType()); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = true; + return true; + + case clang::Type::VariableArray: + if (element_type_ptr) + element_type_ptr->SetClangType (getASTContext(), llvm::cast(qual_type)->getElementType()); + if (size) + *size = 0; + return true; + + case clang::Type::DependentSizedArray: + if (element_type_ptr) + element_type_ptr->SetClangType (getASTContext(), llvm::cast(qual_type)->getElementType()); + if (size) + *size = 0; + return true; + + case clang::Type::Typedef: + return IsArrayType(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), + element_type_ptr, + size, + is_incomplete); + case clang::Type::Elaborated: + return IsArrayType(llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), + element_type_ptr, + size, + is_incomplete); + case clang::Type::Paren: + return IsArrayType(llvm::cast(qual_type)->desugar().getAsOpaquePtr(), + element_type_ptr, + size, + is_incomplete); + } + if (element_type_ptr) + element_type_ptr->Clear(); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = false; + return 0; +} + +bool +ClangASTContext::IsVectorType (void* type, + ClangASTType *element_type, + uint64_t *size) +{ + clang::QualType qual_type (GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Vector: + { + const clang::VectorType *vector_type = qual_type->getAs(); + if (vector_type) + { + if (size) + *size = vector_type->getNumElements(); + if (element_type) + *element_type = ClangASTType(getASTContext(), vector_type->getElementType()); + } + return true; + } + break; + case clang::Type::ExtVector: + { + const clang::ExtVectorType *ext_vector_type = qual_type->getAs(); + if (ext_vector_type) + { + if (size) + *size = ext_vector_type->getNumElements(); + if (element_type) + *element_type = ClangASTType(getASTContext(), ext_vector_type->getElementType()); + } + return true; + } + default: + break; + } + return false; +} + +bool +ClangASTContext::IsRuntimeGeneratedType (void* type) +{ + clang::DeclContext* decl_ctx = ClangASTContext::GetASTContext(getASTContext())->GetDeclContextForType(GetQualType(type)); + if (!decl_ctx) + return false; + + if (!llvm::isa(decl_ctx)) + return false; + + clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast(decl_ctx); + + ClangASTMetadata* ast_metadata = ClangASTContext::GetMetadata(getASTContext(), result_iface_decl); + if (!ast_metadata) + return false; + return (ast_metadata->GetISAPtr() != 0); +} + +bool +ClangASTContext::IsCharType (void* type) +{ + return GetQualType(type).getUnqualifiedType()->isCharType(); +} + + +bool +ClangASTContext::IsCompleteType (void* type) +{ + const bool allow_completion = false; + return GetCompleteQualType (getASTContext(), GetQualType(type), allow_completion); +} + +bool +ClangASTContext::IsConst(void* type) +{ + return GetQualType(type).isConstQualified(); +} + +bool +ClangASTContext::IsCStringType (void* type, uint32_t &length) +{ + ClangASTType pointee_or_element_clang_type; + length = 0; + Flags type_flags (GetTypeInfo (type, &pointee_or_element_clang_type)); + + if (!pointee_or_element_clang_type.IsValid()) + return false; + + if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer)) + { + if (pointee_or_element_clang_type.IsCharType()) + { + if (type_flags.Test (eTypeIsArray)) + { + // We know the size of the array and it could be a C string + // since it is an array of characters + length = llvm::cast(GetCanonicalQualType(type).getTypePtr())->getSize().getLimitedValue(); + } + return true; + + } + } + return false; +} + +bool +ClangASTContext::IsFunctionType (void* type, bool *is_variadic_ptr) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + + if (qual_type->isFunctionType()) + { + if (is_variadic_ptr) + { + const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (function_proto_type) + *is_variadic_ptr = function_proto_type->isVariadic(); + else + *is_variadic_ptr = false; + } + return true; + } + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + default: + break; + case clang::Type::Typedef: + return IsFunctionType(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), nullptr); + case clang::Type::Elaborated: + return IsFunctionType(llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), nullptr); + case clang::Type::Paren: + return IsFunctionType(llvm::cast(qual_type)->desugar().getAsOpaquePtr(), nullptr); + case clang::Type::LValueReference: + case clang::Type::RValueReference: + { + const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); + if (reference_type) + return IsFunctionType(reference_type->getPointeeType().getAsOpaquePtr(), nullptr); + } + break; + } + } + return false; +} + +// Used to detect "Homogeneous Floating-point Aggregates" +uint32_t +ClangASTContext::IsHomogeneousAggregate (void* type, ClangASTType* base_type_ptr) +{ + if (!type) + return 0; + + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (GetCompleteType (type)) + { + const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + if (cxx_record_decl->getNumBases() || + cxx_record_decl->isDynamicClass()) + return 0; + } + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + if (record_type) + { + const clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl) + { + // We are looking for a structure that contains only floating point types + clang::RecordDecl::field_iterator field_pos, field_end = record_decl->field_end(); + uint32_t num_fields = 0; + bool is_hva = false; + bool is_hfa = false; + clang::QualType base_qual_type; + for (field_pos = record_decl->field_begin(); field_pos != field_end; ++field_pos) + { + clang::QualType field_qual_type = field_pos->getType(); + if (field_qual_type->isFloatingType()) + { + if (field_qual_type->isComplexType()) + return 0; + else + { + if (num_fields == 0) + base_qual_type = field_qual_type; + else + { + if (is_hva) + return 0; + is_hfa = true; + if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) + return 0; + } + } + } + else if (field_qual_type->isVectorType() || field_qual_type->isExtVectorType()) + { + const clang::VectorType *array = field_qual_type.getTypePtr()->getAs(); + if (array && array->getNumElements() <= 4) + { + if (num_fields == 0) + base_qual_type = array->getElementType(); + else + { + if (is_hfa) + return 0; + is_hva = true; + if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) + return 0; + } + } + else + return 0; + } + else + return 0; + ++num_fields; + } + if (base_type_ptr) + *base_type_ptr = ClangASTType (getASTContext(), base_qual_type); + return num_fields; + } + } + } + break; + + case clang::Type::Typedef: + return IsHomogeneousAggregate(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), base_type_ptr); + + case clang::Type::Elaborated: + return IsHomogeneousAggregate(llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), base_type_ptr); + default: + break; + } + return 0; +} + +size_t +ClangASTContext::GetNumberOfFunctionArguments (void* type) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + const clang::FunctionProtoType* func = llvm::dyn_cast(qual_type.getTypePtr()); + if (func) + return func->getNumParams(); + } + return 0; +} + +ClangASTType +ClangASTContext::GetFunctionArgumentAtIndex (void* type, const size_t index) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + const clang::FunctionProtoType* func = llvm::dyn_cast(qual_type.getTypePtr()); + if (func) + { + if (index < func->getNumParams()) + return ClangASTType(getASTContext(), func->getParamType(index)); + } + } + return ClangASTType(); +} + +bool +ClangASTContext::IsFunctionPointerType (void* type) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + + if (qual_type->isFunctionPointerType()) + return true; + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + default: + break; + case clang::Type::Typedef: + return IsFunctionPointerType (llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); + case clang::Type::Elaborated: + return IsFunctionPointerType(llvm::cast(qual_type)->getNamedType().getAsOpaquePtr()); case clang::Type::Paren: + return IsFunctionPointerType(llvm::cast(qual_type)->desugar().getAsOpaquePtr()); + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + { + const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); + if (reference_type) + return IsFunctionPointerType(reference_type->getPointeeType().getAsOpaquePtr()); + } + break; + } + } + return false; + +} + +bool +ClangASTContext::IsIntegerType (void* type, bool &is_signed) +{ + if (!type) + return false; + + clang::QualType qual_type (GetCanonicalQualType(type)); + const clang::BuiltinType *builtin_type = llvm::dyn_cast(qual_type->getCanonicalTypeInternal()); + + if (builtin_type) + { + if (builtin_type->isInteger()) + { + is_signed = builtin_type->isSignedInteger(); + return true; + } + } + + return false; +} + +bool +ClangASTContext::IsPointerType (void* type, ClangASTType *pointee_type) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Builtin: + switch (llvm::cast(qual_type)->getKind()) + { + default: + break; + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + return true; + } + return false; + case clang::Type::ObjCObjectPointer: + if (pointee_type) + pointee_type->SetClangType (getASTContext(), llvm::cast(qual_type)->getPointeeType()); + return true; + case clang::Type::BlockPointer: + if (pointee_type) + pointee_type->SetClangType (getASTContext(), llvm::cast(qual_type)->getPointeeType()); + return true; + case clang::Type::Pointer: + if (pointee_type) + pointee_type->SetClangType (getASTContext(), llvm::cast(qual_type)->getPointeeType()); + return true; + case clang::Type::MemberPointer: + if (pointee_type) + pointee_type->SetClangType (getASTContext(), llvm::cast(qual_type)->getPointeeType()); + return true; + case clang::Type::Typedef: + return IsPointerType(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type); + case clang::Type::Elaborated: + return IsPointerType(llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type); + case clang::Type::Paren: + return IsPointerType(llvm::cast(qual_type)->desugar().getAsOpaquePtr(), pointee_type); + default: + break; + } + } + if (pointee_type) + pointee_type->Clear(); + return false; +} + + +bool +ClangASTContext::IsPointerOrReferenceType (void* type, ClangASTType *pointee_type) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Builtin: + switch (llvm::cast(qual_type)->getKind()) + { + default: + break; + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + return true; + } + return false; + case clang::Type::ObjCObjectPointer: + if (pointee_type) + pointee_type->SetClangType(getASTContext(), llvm::cast(qual_type)->getPointeeType()); + return true; + case clang::Type::BlockPointer: + if (pointee_type) + pointee_type->SetClangType(getASTContext(), llvm::cast(qual_type)->getPointeeType()); + return true; + case clang::Type::Pointer: + if (pointee_type) + pointee_type->SetClangType(getASTContext(), llvm::cast(qual_type)->getPointeeType()); + return true; + case clang::Type::MemberPointer: + if (pointee_type) + pointee_type->SetClangType(getASTContext(), llvm::cast(qual_type)->getPointeeType()); + return true; + case clang::Type::LValueReference: + if (pointee_type) + pointee_type->SetClangType(getASTContext(), llvm::cast(qual_type)->desugar()); + return true; + case clang::Type::RValueReference: + if (pointee_type) + pointee_type->SetClangType(getASTContext(), llvm::cast(qual_type)->desugar()); + return true; + case clang::Type::Typedef: + return IsPointerOrReferenceType(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type); + case clang::Type::Elaborated: + return IsPointerOrReferenceType(llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type); + case clang::Type::Paren: + return IsPointerOrReferenceType(llvm::cast(qual_type)->desugar().getAsOpaquePtr(), pointee_type); + default: + break; + } + } + if (pointee_type) + pointee_type->Clear(); + return false; +} + + +bool +ClangASTContext::IsReferenceType (void* type, ClangASTType *pointee_type, bool* is_rvalue) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + + switch (type_class) + { + case clang::Type::LValueReference: + if (pointee_type) + pointee_type->SetClangType(getASTContext(), llvm::cast(qual_type)->desugar()); + if (is_rvalue) + *is_rvalue = false; + return true; + case clang::Type::RValueReference: + if (pointee_type) + pointee_type->SetClangType(getASTContext(), llvm::cast(qual_type)->desugar()); + if (is_rvalue) + *is_rvalue = true; + return true; + case clang::Type::Typedef: + return IsReferenceType(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type, is_rvalue); + case clang::Type::Elaborated: + return IsReferenceType(llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type, is_rvalue); + case clang::Type::Paren: + return IsReferenceType(llvm::cast(qual_type)->desugar().getAsOpaquePtr(), pointee_type, is_rvalue); + + default: + break; + } + } + if (pointee_type) + pointee_type->Clear(); + return false; +} + +bool +ClangASTContext::IsFloatingPointType (void* type, uint32_t &count, bool &is_complex) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + + if (const clang::BuiltinType *BT = llvm::dyn_cast(qual_type->getCanonicalTypeInternal())) + { + clang::BuiltinType::Kind kind = BT->getKind(); + if (kind >= clang::BuiltinType::Float && kind <= clang::BuiltinType::LongDouble) + { + count = 1; + is_complex = false; + return true; + } + } + else if (const clang::ComplexType *CT = llvm::dyn_cast(qual_type->getCanonicalTypeInternal())) + { + if (IsFloatingPointType (CT->getElementType().getAsOpaquePtr(), count, is_complex)) + { + count = 2; + is_complex = true; + return true; + } + } + else if (const clang::VectorType *VT = llvm::dyn_cast(qual_type->getCanonicalTypeInternal())) + { + if (IsFloatingPointType (VT->getElementType().getAsOpaquePtr(), count, is_complex)) + { + count = VT->getNumElements(); + is_complex = false; + return true; + } + } + } + count = 0; + is_complex = false; + return false; +} + + +bool +ClangASTContext::IsDefined(void* type) +{ + if (!type) + return false; + + clang::QualType qual_type(GetQualType(type)); + const clang::TagType *tag_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (tag_type) + { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) + return tag_decl->isCompleteDefinition(); + return false; + } + else + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + if (class_interface_decl) + return class_interface_decl->getDefinition() != nullptr; + return false; + } + } + return true; +} + +bool +ClangASTContext::IsObjCClassType (const ClangASTType& type) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + + const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast(qual_type); + + if (obj_pointer_type) + return obj_pointer_type->isObjCClassType(); + } + return false; +} + +bool +ClangASTContext::IsObjCObjectOrInterfaceType (const ClangASTType& type) +{ + if (type) + return GetCanonicalQualType(type)->isObjCObjectOrInterfaceType(); + return false; +} + +bool +ClangASTContext::IsPolymorphicClass (void* type) +{ + if (type) + { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (GetCompleteType(type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl) + { + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + if (cxx_record_decl) + return cxx_record_decl->isPolymorphic(); + } + } + break; + + default: + break; + } + } + return false; +} + +bool +ClangASTContext::IsPossibleDynamicType (void* type, ClangASTType *dynamic_pointee_type, + bool check_cplusplus, + bool check_objc) +{ + clang::QualType pointee_qual_type; + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + bool success = false; + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Builtin: + if (check_objc && llvm::cast(qual_type)->getKind() == clang::BuiltinType::ObjCId) + { + if (dynamic_pointee_type) + dynamic_pointee_type->SetClangType(this, type); + return true; + } + break; + + case clang::Type::ObjCObjectPointer: + if (check_objc) + { + if (dynamic_pointee_type) + dynamic_pointee_type->SetClangType(getASTContext(), llvm::cast(qual_type)->getPointeeType()); + return true; + } + break; + + case clang::Type::Pointer: + pointee_qual_type = llvm::cast(qual_type)->getPointeeType(); + success = true; + break; + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + pointee_qual_type = llvm::cast(qual_type)->getPointeeType(); + success = true; + break; + + case clang::Type::Typedef: + return IsPossibleDynamicType(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), + dynamic_pointee_type, + check_cplusplus, + check_objc); + + case clang::Type::Elaborated: + return IsPossibleDynamicType (llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), + dynamic_pointee_type, + check_cplusplus, + check_objc); + + case clang::Type::Paren: + return IsPossibleDynamicType(llvm::cast(qual_type)->desugar().getAsOpaquePtr(), + dynamic_pointee_type, + check_cplusplus, + check_objc); + default: + break; + } + + if (success) + { + // Check to make sure what we are pointing too is a possible dynamic C++ type + // We currently accept any "void *" (in case we have a class that has been + // watered down to an opaque pointer) and virtual C++ classes. + const clang::Type::TypeClass pointee_type_class = pointee_qual_type.getCanonicalType()->getTypeClass(); + switch (pointee_type_class) + { + case clang::Type::Builtin: + switch (llvm::cast(pointee_qual_type)->getKind()) + { + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::Void: + if (dynamic_pointee_type) + dynamic_pointee_type->SetClangType(getASTContext(), pointee_qual_type); + return true; + + case clang::BuiltinType::NullPtr: + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + case clang::BuiltinType::Dependent: + case clang::BuiltinType::Overload: + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCSel: + case clang::BuiltinType::BoundMember: + case clang::BuiltinType::Half: + case clang::BuiltinType::ARCUnbridgedCast: + case clang::BuiltinType::PseudoObject: + case clang::BuiltinType::BuiltinFn: + case clang::BuiltinType::OCLEvent: + case clang::BuiltinType::OCLImage1d: + case clang::BuiltinType::OCLImage1dArray: + case clang::BuiltinType::OCLImage1dBuffer: + case clang::BuiltinType::OCLImage2d: + case clang::BuiltinType::OCLImage2dArray: + case clang::BuiltinType::OCLImage3d: + case clang::BuiltinType::OCLSampler: + break; + } + break; + + case clang::Type::Record: + if (check_cplusplus) + { + clang::CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + bool is_complete = cxx_record_decl->isCompleteDefinition(); + + if (is_complete) + success = cxx_record_decl->isDynamicClass(); + else + { + ClangASTMetadata *metadata = ClangASTContext::GetMetadata (getASTContext(), cxx_record_decl); + if (metadata) + success = metadata->GetIsDynamicCXXType(); + else + { + is_complete = ClangASTType(getASTContext(), pointee_qual_type).GetCompleteType(); + if (is_complete) + success = cxx_record_decl->isDynamicClass(); + else + success = false; + } + } + + if (success) + { + if (dynamic_pointee_type) + dynamic_pointee_type->SetClangType(getASTContext(), pointee_qual_type); + return true; + } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (check_objc) + { + if (dynamic_pointee_type) + dynamic_pointee_type->SetClangType(getASTContext(), pointee_qual_type); + return true; + } + break; + + default: + break; + } + } + } + if (dynamic_pointee_type) + dynamic_pointee_type->Clear(); + return false; +} + + +bool +ClangASTContext::IsScalarType (void* type) +{ + if (!type) + return false; + + return (GetTypeInfo (type, nullptr) & eTypeIsScalar) != 0; +} + +bool +ClangASTContext::IsTypedefType (void* type) +{ + if (!type) + return false; + return GetQualType(type)->getTypeClass() == clang::Type::Typedef; +} + +bool +ClangASTContext::IsVoidType (void* type) +{ + if (!type) + return false; + return GetCanonicalQualType(type)->isVoidType(); +} + +bool +ClangASTContext::GetCXXClassName (const ClangASTType& type, std::string &class_name) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + + clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + class_name.assign (cxx_record_decl->getIdentifier()->getNameStart()); + return true; + } + } + class_name.clear(); + return false; +} + + +bool +ClangASTContext::IsCXXClassType (const ClangASTType& type) +{ + if (!type) + return false; + + clang::QualType qual_type (GetCanonicalQualType(type)); + if (qual_type->getAsCXXRecordDecl() != nullptr) + return true; + return false; +} + +bool +ClangASTContext::IsBeingDefined (void* type) +{ + if (!type) + return false; + clang::QualType qual_type (GetCanonicalQualType(type)); + const clang::TagType *tag_type = llvm::dyn_cast(qual_type); + if (tag_type) + return tag_type->isBeingDefined(); + return false; +} + +bool +ClangASTContext::IsObjCObjectPointerType (const ClangASTType& type, ClangASTType *class_type_ptr) +{ + if (!type) + return false; + + clang::QualType qual_type (GetCanonicalQualType(type)); + + if (qual_type->isObjCObjectPointerType()) + { + if (class_type_ptr) + { + if (!qual_type->isObjCClassType() && + !qual_type->isObjCIdType()) + { + const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast(qual_type); + if (obj_pointer_type == nullptr) + class_type_ptr->Clear(); + else + class_type_ptr->SetClangType (type.GetTypeSystem(), clang::QualType(obj_pointer_type->getInterfaceType(), 0).getAsOpaquePtr()); + } + } + return true; + } + if (class_type_ptr) + class_type_ptr->Clear(); + return false; +} + +bool +ClangASTContext::GetObjCClassName (const ClangASTType& type, std::string &class_name) +{ + if (!type) + return false; + + clang::QualType qual_type (GetCanonicalQualType(type)); + + const clang::ObjCObjectType *object_type = llvm::dyn_cast(qual_type); + if (object_type) + { + const clang::ObjCInterfaceDecl *interface = object_type->getInterface(); + if (interface) + { + class_name = interface->getNameAsString(); + return true; + } + } + return false; +} + + +//---------------------------------------------------------------------- +// Type Completion +//---------------------------------------------------------------------- + +bool +ClangASTContext::GetCompleteType (void* type) +{ + if (!type) + return false; + const bool allow_completion = true; + return GetCompleteQualType (getASTContext(), GetQualType(type), allow_completion); +} + +ConstString +ClangASTContext::GetTypeName (void* type) +{ + std::string type_name; + if (type) + { + clang::PrintingPolicy printing_policy (getASTContext()->getPrintingPolicy()); + clang::QualType qual_type(GetQualType(type)); + printing_policy.SuppressTagKeyword = true; + printing_policy.LangOpts.WChar = true; + const clang::TypedefType *typedef_type = qual_type->getAs(); + if (typedef_type) + { + const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); + type_name = typedef_decl->getQualifiedNameAsString(); + } + else + { + type_name = qual_type.getAsString(printing_policy); + } + } + return ConstString(type_name); +} + +uint32_t +ClangASTContext::GetTypeInfo (void* type, ClangASTType *pointee_or_element_clang_type) +{ + if (!type) + return 0; + + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->Clear(); + + clang::QualType qual_type (GetQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Builtin: + { + const clang::BuiltinType *builtin_type = llvm::dyn_cast(qual_type->getCanonicalTypeInternal()); + + uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue; + switch (builtin_type->getKind()) + { + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetClangType(getASTContext(), getASTContext()->ObjCBuiltinClassTy); + builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; + break; + + case clang::BuiltinType::ObjCSel: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetClangType(getASTContext(), getASTContext()->CharTy); + builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; + break; + + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + builtin_type_flags |= eTypeIsScalar; + if (builtin_type->isInteger()) + { + builtin_type_flags |= eTypeIsInteger; + if (builtin_type->isSignedInteger()) + builtin_type_flags |= eTypeIsSigned; + } + else if (builtin_type->isFloatingPoint()) + builtin_type_flags |= eTypeIsFloat; + break; + default: + break; + } + return builtin_type_flags; + } + + case clang::Type::BlockPointer: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetClangType(getASTContext(), qual_type->getPointeeType()); + return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock; + + case clang::Type::Complex: + { + uint32_t complex_type_flags = eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex; + const clang::ComplexType *complex_type = llvm::dyn_cast(qual_type->getCanonicalTypeInternal()); + if (complex_type) + { + clang::QualType complex_element_type (complex_type->getElementType()); + if (complex_element_type->isIntegerType()) + complex_type_flags |= eTypeIsFloat; + else if (complex_element_type->isFloatingType()) + complex_type_flags |= eTypeIsInteger; + } + return complex_type_flags; + } + break; + + case clang::Type::ConstantArray: + case clang::Type::DependentSizedArray: + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetClangType(getASTContext(), llvm::cast(qual_type.getTypePtr())->getElementType()); + return eTypeHasChildren | eTypeIsArray; + + case clang::Type::DependentName: return 0; + case clang::Type::DependentSizedExtVector: return eTypeHasChildren | eTypeIsVector; + case clang::Type::DependentTemplateSpecialization: return eTypeIsTemplate; + case clang::Type::Decltype: return 0; + + case clang::Type::Enum: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetClangType(getASTContext(), llvm::cast(qual_type)->getDecl()->getIntegerType()); + return eTypeIsEnumeration | eTypeHasValue; + + case clang::Type::Elaborated: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getNamedType()).GetTypeInfo (pointee_or_element_clang_type); + case clang::Type::Paren: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()).GetTypeInfo (pointee_or_element_clang_type); + + case clang::Type::FunctionProto: return eTypeIsFuncPrototype | eTypeHasValue; + case clang::Type::FunctionNoProto: return eTypeIsFuncPrototype | eTypeHasValue; + case clang::Type::InjectedClassName: return 0; + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetClangType(getASTContext(), llvm::cast(qual_type.getTypePtr())->getPointeeType()); + return eTypeHasChildren | eTypeIsReference | eTypeHasValue; + + case clang::Type::MemberPointer: return eTypeIsPointer | eTypeIsMember | eTypeHasValue; + + case clang::Type::ObjCObjectPointer: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetClangType(getASTContext(), qual_type->getPointeeType()); + return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer | eTypeHasValue; + + case clang::Type::ObjCObject: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; + case clang::Type::ObjCInterface: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; + + case clang::Type::Pointer: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetClangType(getASTContext(), qual_type->getPointeeType()); + return eTypeHasChildren | eTypeIsPointer | eTypeHasValue; + + case clang::Type::Record: + if (qual_type->getAsCXXRecordDecl()) + return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus; + else + return eTypeHasChildren | eTypeIsStructUnion; + break; + case clang::Type::SubstTemplateTypeParm: return eTypeIsTemplate; + case clang::Type::TemplateTypeParm: return eTypeIsTemplate; + case clang::Type::TemplateSpecialization: return eTypeIsTemplate; + + case clang::Type::Typedef: + return eTypeIsTypedef | ClangASTType (getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetTypeInfo (pointee_or_element_clang_type); + case clang::Type::TypeOfExpr: return 0; + case clang::Type::TypeOf: return 0; + case clang::Type::UnresolvedUsing: return 0; + + case clang::Type::ExtVector: + case clang::Type::Vector: + { + uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector; + const clang::VectorType *vector_type = llvm::dyn_cast(qual_type->getCanonicalTypeInternal()); + if (vector_type) + { + if (vector_type->isIntegerType()) + vector_type_flags |= eTypeIsFloat; + else if (vector_type->isFloatingType()) + vector_type_flags |= eTypeIsInteger; + } + return vector_type_flags; + } + default: return 0; + } + return 0; +} + + + +lldb::LanguageType +ClangASTContext::GetMinimumLanguage (void* type) +{ + if (!type) + return lldb::eLanguageTypeC; + + // If the type is a reference, then resolve it to what it refers to first: + clang::QualType qual_type (GetCanonicalQualType(type).getNonReferenceType()); + if (qual_type->isAnyPointerType()) + { + if (qual_type->isObjCObjectPointerType()) + return lldb::eLanguageTypeObjC; + + clang::QualType pointee_type (qual_type->getPointeeType()); + if (pointee_type->getPointeeCXXRecordDecl() != nullptr) + return lldb::eLanguageTypeC_plus_plus; + if (pointee_type->isObjCObjectOrInterfaceType()) + return lldb::eLanguageTypeObjC; + if (pointee_type->isObjCClassType()) + return lldb::eLanguageTypeObjC; + if (pointee_type.getTypePtr() == getASTContext()->ObjCBuiltinIdTy.getTypePtr()) + return lldb::eLanguageTypeObjC; + } + else + { + if (qual_type->isObjCObjectOrInterfaceType()) + return lldb::eLanguageTypeObjC; + if (qual_type->getAsCXXRecordDecl()) + return lldb::eLanguageTypeC_plus_plus; + switch (qual_type->getTypeClass()) + { + default: + break; + case clang::Type::Builtin: + switch (llvm::cast(qual_type)->getKind()) + { + default: + case clang::BuiltinType::Void: + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + break; + + case clang::BuiltinType::NullPtr: + return eLanguageTypeC_plus_plus; + + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCSel: + return eLanguageTypeObjC; + + case clang::BuiltinType::Dependent: + case clang::BuiltinType::Overload: + case clang::BuiltinType::BoundMember: + case clang::BuiltinType::UnknownAny: + break; + } + break; + case clang::Type::Typedef: + return ClangASTType(getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetMinimumLanguage(); + } + } + return lldb::eLanguageTypeC; +} + +lldb::TypeClass +ClangASTContext::GetTypeClass (void* type) +{ + if (!type) + return lldb::eTypeClassInvalid; + + clang::QualType qual_type(GetQualType(type)); + + switch (qual_type->getTypeClass()) + { + case clang::Type::UnaryTransform: break; + case clang::Type::FunctionNoProto: return lldb::eTypeClassFunction; + case clang::Type::FunctionProto: return lldb::eTypeClassFunction; + case clang::Type::IncompleteArray: return lldb::eTypeClassArray; + case clang::Type::VariableArray: return lldb::eTypeClassArray; + case clang::Type::ConstantArray: return lldb::eTypeClassArray; + case clang::Type::DependentSizedArray: return lldb::eTypeClassArray; + case clang::Type::DependentSizedExtVector: return lldb::eTypeClassVector; + case clang::Type::ExtVector: return lldb::eTypeClassVector; + case clang::Type::Vector: return lldb::eTypeClassVector; + case clang::Type::Builtin: return lldb::eTypeClassBuiltin; + case clang::Type::ObjCObjectPointer: return lldb::eTypeClassObjCObjectPointer; + case clang::Type::BlockPointer: return lldb::eTypeClassBlockPointer; + case clang::Type::Pointer: return lldb::eTypeClassPointer; + case clang::Type::LValueReference: return lldb::eTypeClassReference; + case clang::Type::RValueReference: return lldb::eTypeClassReference; + case clang::Type::MemberPointer: return lldb::eTypeClassMemberPointer; + case clang::Type::Complex: + if (qual_type->isComplexType()) + return lldb::eTypeClassComplexFloat; + else + return lldb::eTypeClassComplexInteger; + case clang::Type::ObjCObject: return lldb::eTypeClassObjCObject; + case clang::Type::ObjCInterface: return lldb::eTypeClassObjCInterface; + case clang::Type::Record: + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl->isUnion()) + return lldb::eTypeClassUnion; + else if (record_decl->isStruct()) + return lldb::eTypeClassStruct; + else + return lldb::eTypeClassClass; + } + break; + case clang::Type::Enum: return lldb::eTypeClassEnumeration; + case clang::Type::Typedef: return lldb::eTypeClassTypedef; + case clang::Type::UnresolvedUsing: break; + case clang::Type::Paren: + return ClangASTType(getASTContext(), llvm::cast(qual_type)->desugar()).GetTypeClass(); + case clang::Type::Elaborated: + return ClangASTType(getASTContext(), llvm::cast(qual_type)->getNamedType()).GetTypeClass(); + + case clang::Type::Attributed: break; + case clang::Type::TemplateTypeParm: break; + case clang::Type::SubstTemplateTypeParm: break; + case clang::Type::SubstTemplateTypeParmPack:break; + case clang::Type::Auto: break; + case clang::Type::InjectedClassName: break; + case clang::Type::DependentName: break; + case clang::Type::DependentTemplateSpecialization: break; + case clang::Type::PackExpansion: break; + + case clang::Type::TypeOfExpr: break; + case clang::Type::TypeOf: break; + case clang::Type::Decltype: break; + case clang::Type::TemplateSpecialization: break; + case clang::Type::Atomic: break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: break; + case clang::Type::Adjusted: break; + } + // We don't know hot to display this type... + return lldb::eTypeClassOther; + +} + +unsigned +ClangASTContext::GetTypeQualifiers(void* type) +{ + if (type) + return GetQualType(type).getQualifiers().getCVRQualifiers(); + return 0; +} + +//---------------------------------------------------------------------- +// Creating related types +//---------------------------------------------------------------------- + +ClangASTType +ClangASTContext::AddConstModifier (const ClangASTType& type) +{ + if (type && type.GetTypeSystem()->AsClangASTContext()) + { + clang::QualType result(GetQualType(type)); + result.addConst(); + return ClangASTType (type.GetTypeSystem(), result.getAsOpaquePtr()); + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::AddRestrictModifier (const ClangASTType& type) +{ + if (type && type.GetTypeSystem()->AsClangASTContext()) + { + clang::QualType result(GetQualType(type)); + result.getQualifiers().setRestrict (true); + return ClangASTType (type.GetTypeSystem(), result.getAsOpaquePtr()); + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::AddVolatileModifier (const ClangASTType& type) +{ + if (type && type.GetTypeSystem()->AsClangASTContext()) + { + clang::QualType result(GetQualType(type)); + result.getQualifiers().setVolatile (true); + return ClangASTType (type.GetTypeSystem(), result.getAsOpaquePtr()); + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::GetArrayElementType (void* type, uint64_t *stride) +{ + if (type) + { + clang::QualType qual_type(GetCanonicalQualType(type)); + + const clang::Type *array_eletype = qual_type.getTypePtr()->getArrayElementTypeNoTypeQual(); + + if (!array_eletype) + return ClangASTType(); + + ClangASTType element_type (getASTContext(), array_eletype->getCanonicalTypeUnqualified()); + + // TODO: the real stride will be >= this value.. find the real one! + if (stride) + *stride = element_type.GetByteSize(nullptr); + + return element_type; + + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::GetCanonicalType (void* type) +{ + if (type) + return ClangASTType (getASTContext(), GetCanonicalQualType(type)); + return ClangASTType(); +} + +static clang::QualType +GetFullyUnqualifiedType_Impl (clang::ASTContext *ast, clang::QualType qual_type) +{ + if (qual_type->isPointerType()) + qual_type = ast->getPointerType(GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType())); + else + qual_type = qual_type.getUnqualifiedType(); + qual_type.removeLocalConst(); + qual_type.removeLocalRestrict(); + qual_type.removeLocalVolatile(); + return qual_type; +} + +ClangASTType +ClangASTContext::GetFullyUnqualifiedType (void* type) +{ + if (type) + return ClangASTType(getASTContext(), GetFullyUnqualifiedType_Impl(getASTContext(), GetQualType(type))); + return ClangASTType(); +} + + +int +ClangASTContext::GetFunctionArgumentCount (void* type) +{ + if (type) + { + const clang::FunctionProtoType* func = llvm::dyn_cast(GetCanonicalQualType(type)); + if (func) + return func->getNumParams(); + } + return -1; +} + +ClangASTType +ClangASTContext::GetFunctionArgumentTypeAtIndex (void* type, size_t idx) +{ + if (type) + { + const clang::FunctionProtoType* func = llvm::dyn_cast(GetCanonicalQualType(type)); + if (func) + { + const uint32_t num_args = func->getNumParams(); + if (idx < num_args) + return ClangASTType(getASTContext(), func->getParamType(idx)); + } + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::GetFunctionReturnType (void* type) +{ + if (type) + { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::FunctionProtoType* func = llvm::dyn_cast(qual_type.getTypePtr()); + if (func) + return ClangASTType(getASTContext(), func->getReturnType()); + } + return ClangASTType(); +} + +size_t +ClangASTContext::GetNumMemberFunctions (void* type) +{ + size_t num_functions = 0; + if (type) + { + clang::QualType qual_type(GetCanonicalQualType(type)); + switch (qual_type->getTypeClass()) { + case clang::Type::Record: + if (GetCompleteQualType (getASTContext(), qual_type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + if (cxx_record_decl) + num_functions = std::distance(cxx_record_decl->method_begin(), cxx_record_decl->method_end()); + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType(type)) + { + const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + if (class_interface_decl) + num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + if (class_interface_decl) + num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); + } + } + break; + + + case clang::Type::Typedef: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumMemberFunctions(); + + case clang::Type::Elaborated: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getNamedType()).GetNumMemberFunctions(); + + case clang::Type::Paren: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()).GetNumMemberFunctions(); + + default: + break; + } + } + return num_functions; +} + +TypeMemberFunctionImpl +ClangASTContext::GetMemberFunctionAtIndex (void* type, size_t idx) +{ + std::string name(""); + MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown); + ClangASTType clang_type{}; + clang::ObjCMethodDecl *method_decl(nullptr); + if (type) + { + clang::QualType qual_type(GetCanonicalQualType(type)); + switch (qual_type->getTypeClass()) { + case clang::Type::Record: + if (GetCompleteQualType (getASTContext(), qual_type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + if (cxx_record_decl) + { + auto method_iter = cxx_record_decl->method_begin(); + auto method_end = cxx_record_decl->method_end(); + if (idx < static_cast(std::distance(method_iter, method_end))) + { + std::advance(method_iter, idx); + auto method_decl = method_iter->getCanonicalDecl(); + if (method_decl) + { + if (!method_decl->getName().empty()) + name.assign(method_decl->getName().data()); + else + name.clear(); + if (method_decl->isStatic()) + kind = lldb::eMemberFunctionKindStaticMethod; + else if (llvm::isa(method_decl)) + kind = lldb::eMemberFunctionKindConstructor; + else if (llvm::isa(method_decl)) + kind = lldb::eMemberFunctionKindDestructor; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + clang_type = ClangASTType(getASTContext(),method_decl->getType()); + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType(type)) + { + const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + if (class_interface_decl) + { + auto method_iter = class_interface_decl->meth_begin(); + auto method_end = class_interface_decl->meth_end(); + if (idx < static_cast(std::distance(method_iter, method_end))) + { + std::advance(method_iter, idx); + method_decl = method_iter->getCanonicalDecl(); + if (method_decl) + { + name = method_decl->getSelector().getAsString(); + if (method_decl->isClassMethod()) + kind = lldb::eMemberFunctionKindStaticMethod; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + } + } + } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + if (class_interface_decl) + { + auto method_iter = class_interface_decl->meth_begin(); + auto method_end = class_interface_decl->meth_end(); + if (idx < static_cast(std::distance(method_iter, method_end))) + { + std::advance(method_iter, idx); + method_decl = method_iter->getCanonicalDecl(); + if (method_decl) + { + name = method_decl->getSelector().getAsString(); + if (method_decl->isClassMethod()) + kind = lldb::eMemberFunctionKindStaticMethod; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + } + } + } + } + } + break; + + case clang::Type::Typedef: + return GetMemberFunctionAtIndex(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx); + + case clang::Type::Elaborated: + return GetMemberFunctionAtIndex(llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), idx); + + case clang::Type::Paren: + return GetMemberFunctionAtIndex(llvm::cast(qual_type)->desugar().getAsOpaquePtr(), idx); + + default: + break; + } + } + + if (kind == eMemberFunctionKindUnknown) + return TypeMemberFunctionImpl(); + if (method_decl) + return TypeMemberFunctionImpl(method_decl, name, kind); + if (type) + return TypeMemberFunctionImpl(clang_type, name, kind); + + return TypeMemberFunctionImpl(); +} + +ClangASTType +ClangASTContext::GetLValueReferenceType (const ClangASTType& type) +{ + if (type) + { + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (ast) + return ClangASTType(ast->getASTContext(), ast->getASTContext()->getLValueReferenceType(GetQualType(type))); + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::GetRValueReferenceType (const ClangASTType& type) +{ + if (type) + { + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (ast) + return ClangASTType(ast->getASTContext(), ast->getASTContext()->getRValueReferenceType(GetQualType(type))); + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::GetNonReferenceType (void* type) +{ + if (type) + return ClangASTType(getASTContext(), GetQualType(type).getNonReferenceType()); + return ClangASTType(); +} + +ClangASTType +ClangASTContext::CreateTypedefType (const ClangASTType& type, + const char *typedef_name, + clang::DeclContext *decl_ctx) +{ + if (type && typedef_name && typedef_name[0]) + { + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return ClangASTType(); + clang::ASTContext* clang_ast = ast->getASTContext(); + clang::QualType qual_type (GetQualType(type)); + if (decl_ctx == nullptr) + decl_ctx = ast->getASTContext()->getTranslationUnitDecl(); + clang::TypedefDecl *decl = clang::TypedefDecl::Create (*clang_ast, + decl_ctx, + clang::SourceLocation(), + clang::SourceLocation(), + &clang_ast->Idents.get(typedef_name), + clang_ast->getTrivialTypeSourceInfo(qual_type)); + + decl->setAccess(clang::AS_public); // TODO respect proper access specifier + + // Get a uniqued clang::QualType for the typedef decl type + return ClangASTType (clang_ast, clang_ast->getTypedefType (decl)); + } + return ClangASTType(); + +} + +ClangASTType +ClangASTContext::GetPointeeType (void* type) +{ + if (type) + { + clang::QualType qual_type(GetQualType(type)); + return ClangASTType (getASTContext(), qual_type.getTypePtr()->getPointeeType()); + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::GetPointerType (void* type) +{ + if (type) + { + clang::QualType qual_type (GetQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + return ClangASTType(getASTContext(), getASTContext()->getObjCObjectPointerType(qual_type)); + + default: + return ClangASTType(getASTContext(), getASTContext()->getPointerType(qual_type)); + } + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::GetTypedefedType (void* type) +{ + if (type) + { + const clang::TypedefType *typedef_type = llvm::dyn_cast(GetQualType(type)); + if (typedef_type) + return ClangASTType (getASTContext(), typedef_type->getDecl()->getUnderlyingType()); + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::RemoveFastQualifiers (const ClangASTType& type) +{ + if (type && type.GetTypeSystem()->AsClangASTContext()) + { + clang::QualType qual_type(GetQualType(type)); + qual_type.getQualifiers().removeFastQualifiers(); + return ClangASTType (type.GetTypeSystem(), qual_type.getAsOpaquePtr()); + } + return type; +} + + +//---------------------------------------------------------------------- +// Create related types using the current type's AST +//---------------------------------------------------------------------- + +ClangASTType +ClangASTContext::GetBasicTypeFromAST (void* type, lldb::BasicType basic_type) +{ + if (type) + return ClangASTContext::GetBasicType(getASTContext(), basic_type); + return ClangASTType(); +} +//---------------------------------------------------------------------- +// Exploring the type +//---------------------------------------------------------------------- + +uint64_t +ClangASTContext::GetBitSize (void* type, ExecutionContextScope *exe_scope) +{ + if (GetCompleteType (type)) + { + clang::QualType qual_type(GetCanonicalQualType(type)); + switch (qual_type->getTypeClass()) + { + case clang::Type::ObjCInterface: + case clang::Type::ObjCObject: + { + ExecutionContext exe_ctx (exe_scope); + Process *process = exe_ctx.GetProcessPtr(); + if (process) + { + ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); + if (objc_runtime) + { + uint64_t bit_size = 0; + if (objc_runtime->GetTypeBitSize(ClangASTType(getASTContext(), qual_type), bit_size)) + return bit_size; + } + } + else + { + static bool g_printed = false; + if (!g_printed) + { + StreamString s; + DumpTypeDescription(&s); + + llvm::outs() << "warning: trying to determine the size of type "; + llvm::outs() << s.GetString() << "\n"; + llvm::outs() << "without a valid ExecutionContext. this is not reliable. please file a bug against LLDB.\n"; + llvm::outs() << "backtrace:\n"; + llvm::sys::PrintStackTrace(llvm::outs()); + llvm::outs() << "\n"; + g_printed = true; + } + } + } + // fallthrough + default: + const uint32_t bit_size = getASTContext()->getTypeSize (qual_type); + if (bit_size == 0) + { + if (qual_type->isIncompleteArrayType()) + return getASTContext()->getTypeSize (qual_type->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified()); + } + if (qual_type->isObjCObjectOrInterfaceType()) + return bit_size + getASTContext()->getTypeSize(getASTContext()->ObjCBuiltinClassTy); + return bit_size; + } + } + return 0; +} + +size_t +ClangASTContext::GetTypeBitAlign (void* type) +{ + if (GetCompleteType(type)) + return getASTContext()->getTypeAlign(GetQualType(type)); + return 0; +} + + +lldb::Encoding +ClangASTContext::GetEncoding (void* type, uint64_t &count) +{ + if (!type) + return lldb::eEncodingInvalid; + + count = 1; + clang::QualType qual_type(GetCanonicalQualType(type)); + + switch (qual_type->getTypeClass()) + { + case clang::Type::UnaryTransform: + break; + + case clang::Type::FunctionNoProto: + case clang::Type::FunctionProto: + break; + + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: + break; + + case clang::Type::ConstantArray: + break; + + case clang::Type::ExtVector: + case clang::Type::Vector: + // TODO: Set this to more than one??? + break; + + case clang::Type::Builtin: + switch (llvm::cast(qual_type)->getKind()) + { + default: assert(0 && "Unknown builtin type!"); + case clang::BuiltinType::Void: + break; + + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: return lldb::eEncodingSint; + + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: return lldb::eEncodingUint; + + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: return lldb::eEncodingIEEE754; + + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCSel: return lldb::eEncodingUint; + + case clang::BuiltinType::NullPtr: return lldb::eEncodingUint; + + case clang::BuiltinType::Kind::ARCUnbridgedCast: + case clang::BuiltinType::Kind::BoundMember: + case clang::BuiltinType::Kind::BuiltinFn: + case clang::BuiltinType::Kind::Dependent: + case clang::BuiltinType::Kind::Half: + case clang::BuiltinType::Kind::OCLEvent: + case clang::BuiltinType::Kind::OCLImage1d: + case clang::BuiltinType::Kind::OCLImage1dArray: + case clang::BuiltinType::Kind::OCLImage1dBuffer: + case clang::BuiltinType::Kind::OCLImage2d: + case clang::BuiltinType::Kind::OCLImage2dArray: + case clang::BuiltinType::Kind::OCLImage3d: + case clang::BuiltinType::Kind::OCLSampler: + case clang::BuiltinType::Kind::Overload: + case clang::BuiltinType::Kind::PseudoObject: + case clang::BuiltinType::Kind::UnknownAny: + break; + } + break; + // All pointer types are represented as unsigned integer encodings. + // We may nee to add a eEncodingPointer if we ever need to know the + // difference + case clang::Type::ObjCObjectPointer: + case clang::Type::BlockPointer: + case clang::Type::Pointer: + case clang::Type::LValueReference: + case clang::Type::RValueReference: + case clang::Type::MemberPointer: return lldb::eEncodingUint; + case clang::Type::Complex: + { + lldb::Encoding encoding = lldb::eEncodingIEEE754; + if (qual_type->isComplexType()) + encoding = lldb::eEncodingIEEE754; + else + { + const clang::ComplexType *complex_type = qual_type->getAsComplexIntegerType(); + if (complex_type) + encoding = ClangASTType(getASTContext(), complex_type->getElementType()).GetEncoding(count); + else + encoding = lldb::eEncodingSint; + } + count = 2; + return encoding; + } + + case clang::Type::ObjCInterface: break; + case clang::Type::Record: break; + case clang::Type::Enum: return lldb::eEncodingSint; + case clang::Type::Typedef: + return ClangASTType(getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetEncoding(count); + + case clang::Type::Elaborated: + return ClangASTType(getASTContext(), llvm::cast(qual_type)->getNamedType()).GetEncoding(count); + + case clang::Type::Paren: + return ClangASTType(getASTContext(), llvm::cast(qual_type)->desugar()).GetEncoding(count); + + case clang::Type::DependentSizedArray: + case clang::Type::DependentSizedExtVector: + case clang::Type::UnresolvedUsing: + case clang::Type::Attributed: + case clang::Type::TemplateTypeParm: + case clang::Type::SubstTemplateTypeParm: + case clang::Type::SubstTemplateTypeParmPack: + case clang::Type::Auto: + case clang::Type::InjectedClassName: + case clang::Type::DependentName: + case clang::Type::DependentTemplateSpecialization: + case clang::Type::PackExpansion: + case clang::Type::ObjCObject: + + case clang::Type::TypeOfExpr: + case clang::Type::TypeOf: + case clang::Type::Decltype: + case clang::Type::TemplateSpecialization: + case clang::Type::Atomic: + case clang::Type::Adjusted: + break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: + break; + } + count = 0; + return lldb::eEncodingInvalid; +} + +lldb::Format +ClangASTContext::GetFormat (void* type) +{ + if (!type) + return lldb::eFormatDefault; + + clang::QualType qual_type(GetCanonicalQualType(type)); + + switch (qual_type->getTypeClass()) + { + case clang::Type::UnaryTransform: + break; + + case clang::Type::FunctionNoProto: + case clang::Type::FunctionProto: + break; + + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: + break; + + case clang::Type::ConstantArray: + return lldb::eFormatVoid; // no value + + case clang::Type::ExtVector: + case clang::Type::Vector: + break; + + case clang::Type::Builtin: + switch (llvm::cast(qual_type)->getKind()) + { + //default: assert(0 && "Unknown builtin type!"); + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::Void: + case clang::BuiltinType::BoundMember: + break; + + case clang::BuiltinType::Bool: return lldb::eFormatBoolean; + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: return lldb::eFormatChar; + case clang::BuiltinType::Char16: return lldb::eFormatUnicode16; + case clang::BuiltinType::Char32: return lldb::eFormatUnicode32; + case clang::BuiltinType::UShort: return lldb::eFormatUnsigned; + case clang::BuiltinType::Short: return lldb::eFormatDecimal; + case clang::BuiltinType::UInt: return lldb::eFormatUnsigned; + case clang::BuiltinType::Int: return lldb::eFormatDecimal; + case clang::BuiltinType::ULong: return lldb::eFormatUnsigned; + case clang::BuiltinType::Long: return lldb::eFormatDecimal; + case clang::BuiltinType::ULongLong: return lldb::eFormatUnsigned; + case clang::BuiltinType::LongLong: return lldb::eFormatDecimal; + case clang::BuiltinType::UInt128: return lldb::eFormatUnsigned; + case clang::BuiltinType::Int128: return lldb::eFormatDecimal; + case clang::BuiltinType::Float: return lldb::eFormatFloat; + case clang::BuiltinType::Double: return lldb::eFormatFloat; + case clang::BuiltinType::LongDouble: return lldb::eFormatFloat; + case clang::BuiltinType::NullPtr: + case clang::BuiltinType::Overload: + case clang::BuiltinType::Dependent: + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCSel: + case clang::BuiltinType::Half: + case clang::BuiltinType::ARCUnbridgedCast: + case clang::BuiltinType::PseudoObject: + case clang::BuiltinType::BuiltinFn: + case clang::BuiltinType::OCLEvent: + case clang::BuiltinType::OCLImage1d: + case clang::BuiltinType::OCLImage1dArray: + case clang::BuiltinType::OCLImage1dBuffer: + case clang::BuiltinType::OCLImage2d: + case clang::BuiltinType::OCLImage2dArray: + case clang::BuiltinType::OCLImage3d: + case clang::BuiltinType::OCLSampler: + return lldb::eFormatHex; + } + break; + case clang::Type::ObjCObjectPointer: return lldb::eFormatHex; + case clang::Type::BlockPointer: return lldb::eFormatHex; + case clang::Type::Pointer: return lldb::eFormatHex; + case clang::Type::LValueReference: + case clang::Type::RValueReference: return lldb::eFormatHex; + case clang::Type::MemberPointer: break; + case clang::Type::Complex: + { + if (qual_type->isComplexType()) + return lldb::eFormatComplex; + else + return lldb::eFormatComplexInteger; + } + case clang::Type::ObjCInterface: break; + case clang::Type::Record: break; + case clang::Type::Enum: return lldb::eFormatEnum; + case clang::Type::Typedef: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetFormat(); + case clang::Type::Auto: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()).GetFormat(); + case clang::Type::Paren: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()).GetFormat(); + case clang::Type::Elaborated: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getNamedType()).GetFormat(); + case clang::Type::DependentSizedArray: + case clang::Type::DependentSizedExtVector: + case clang::Type::UnresolvedUsing: + case clang::Type::Attributed: + case clang::Type::TemplateTypeParm: + case clang::Type::SubstTemplateTypeParm: + case clang::Type::SubstTemplateTypeParmPack: + case clang::Type::InjectedClassName: + case clang::Type::DependentName: + case clang::Type::DependentTemplateSpecialization: + case clang::Type::PackExpansion: + case clang::Type::ObjCObject: + + case clang::Type::TypeOfExpr: + case clang::Type::TypeOf: + case clang::Type::Decltype: + case clang::Type::TemplateSpecialization: + case clang::Type::Atomic: + case clang::Type::Adjusted: + break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: + break; + } + // We don't know hot to display this type... + return lldb::eFormatBytes; +} + +static bool +ObjCDeclHasIVars (clang::ObjCInterfaceDecl *class_interface_decl, bool check_superclass) +{ + while (class_interface_decl) + { + if (class_interface_decl->ivar_size() > 0) + return true; + + if (check_superclass) + class_interface_decl = class_interface_decl->getSuperClass(); + else + break; + } + return false; +} + +uint32_t +ClangASTContext::GetNumChildren (void* type, bool omit_empty_base_classes) +{ + if (!type) + return 0; + + uint32_t num_children = 0; + clang::QualType qual_type(GetQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Builtin: + switch (llvm::cast(qual_type)->getKind()) + { + case clang::BuiltinType::ObjCId: // child is Class + case clang::BuiltinType::ObjCClass: // child is Class + num_children = 1; + break; + + default: + break; + } + break; + + case clang::Type::Complex: return 0; + + case clang::Type::Record: + if (GetCompleteQualType (getASTContext(), qual_type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + if (cxx_record_decl) + { + if (omit_empty_base_classes) + { + // Check each base classes to see if it or any of its + // base classes contain any fields. This can help + // limit the noise in variable views by not having to + // show base classes that contain no members. + clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; + ++base_class) + { + const clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); + + // Skip empty base classes + if (ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + + num_children++; + } + } + else + { + // Include all base classes + num_children += cxx_record_decl->getNumBases(); + } + + } + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field) + ++num_children; + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteQualType (getASTContext(), qual_type)) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + assert (objc_class_type); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + + if (class_interface_decl) + { + + clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); + if (superclass_interface_decl) + { + if (omit_empty_base_classes) + { + if (ObjCDeclHasIVars (superclass_interface_decl, true)) + ++num_children; + } + else + ++num_children; + } + + num_children += class_interface_decl->ivar_size(); + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + { + const clang::ObjCObjectPointerType *pointer_type = llvm::cast(qual_type.getTypePtr()); + clang::QualType pointee_type = pointer_type->getPointeeType(); + uint32_t num_pointee_children = ClangASTType (getASTContext(),pointee_type).GetNumChildren (omit_empty_base_classes); + // If this type points to a simple type, then it has 1 child + if (num_pointee_children == 0) + num_children = 1; + else + num_children = num_pointee_children; + } + break; + + case clang::Type::Vector: + case clang::Type::ExtVector: + num_children = llvm::cast(qual_type.getTypePtr())->getNumElements(); + break; + + case clang::Type::ConstantArray: + num_children = llvm::cast(qual_type.getTypePtr())->getSize().getLimitedValue(); + break; + + case clang::Type::Pointer: + { + const clang::PointerType *pointer_type = llvm::cast(qual_type.getTypePtr()); + clang::QualType pointee_type (pointer_type->getPointeeType()); + uint32_t num_pointee_children = ClangASTType (getASTContext(),pointee_type).GetNumChildren (omit_empty_base_classes); + if (num_pointee_children == 0) + { + // We have a pointer to a pointee type that claims it has no children. + // We will want to look at + num_children = GetNumPointeeChildren (pointee_type); + } + else + num_children = num_pointee_children; + } + break; + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + { + const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); + clang::QualType pointee_type = reference_type->getPointeeType(); + uint32_t num_pointee_children = ClangASTType (getASTContext(), pointee_type).GetNumChildren (omit_empty_base_classes); + // If this type points to a simple type, then it has 1 child + if (num_pointee_children == 0) + num_children = 1; + else + num_children = num_pointee_children; + } + break; + + + case clang::Type::Typedef: + num_children = ClangASTType (getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumChildren (omit_empty_base_classes); + break; + + case clang::Type::Elaborated: + num_children = ClangASTType (getASTContext(), llvm::cast(qual_type)->getNamedType()).GetNumChildren (omit_empty_base_classes); + break; + + case clang::Type::Paren: + num_children = ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()).GetNumChildren (omit_empty_base_classes); + break; + default: + break; + } + return num_children; +} + +lldb::BasicType +ClangASTContext::GetBasicTypeEnumeration (void* type) +{ + if (type) + { + clang::QualType qual_type(GetQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + if (type_class == clang::Type::Builtin) + { + switch (llvm::cast(qual_type)->getKind()) + { + case clang::BuiltinType::Void: return eBasicTypeVoid; + case clang::BuiltinType::Bool: return eBasicTypeBool; + case clang::BuiltinType::Char_S: return eBasicTypeSignedChar; + case clang::BuiltinType::Char_U: return eBasicTypeUnsignedChar; + case clang::BuiltinType::Char16: return eBasicTypeChar16; + case clang::BuiltinType::Char32: return eBasicTypeChar32; + case clang::BuiltinType::UChar: return eBasicTypeUnsignedChar; + case clang::BuiltinType::SChar: return eBasicTypeSignedChar; + case clang::BuiltinType::WChar_S: return eBasicTypeSignedWChar; + case clang::BuiltinType::WChar_U: return eBasicTypeUnsignedWChar; + case clang::BuiltinType::Short: return eBasicTypeShort; + case clang::BuiltinType::UShort: return eBasicTypeUnsignedShort; + case clang::BuiltinType::Int: return eBasicTypeInt; + case clang::BuiltinType::UInt: return eBasicTypeUnsignedInt; + case clang::BuiltinType::Long: return eBasicTypeLong; + case clang::BuiltinType::ULong: return eBasicTypeUnsignedLong; + case clang::BuiltinType::LongLong: return eBasicTypeLongLong; + case clang::BuiltinType::ULongLong: return eBasicTypeUnsignedLongLong; + case clang::BuiltinType::Int128: return eBasicTypeInt128; + case clang::BuiltinType::UInt128: return eBasicTypeUnsignedInt128; + + case clang::BuiltinType::Half: return eBasicTypeHalf; + case clang::BuiltinType::Float: return eBasicTypeFloat; + case clang::BuiltinType::Double: return eBasicTypeDouble; + case clang::BuiltinType::LongDouble:return eBasicTypeLongDouble; + + case clang::BuiltinType::NullPtr: return eBasicTypeNullPtr; + case clang::BuiltinType::ObjCId: return eBasicTypeObjCID; + case clang::BuiltinType::ObjCClass: return eBasicTypeObjCClass; + case clang::BuiltinType::ObjCSel: return eBasicTypeObjCSel; + case clang::BuiltinType::Dependent: + case clang::BuiltinType::Overload: + case clang::BuiltinType::BoundMember: + case clang::BuiltinType::PseudoObject: + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::BuiltinFn: + case clang::BuiltinType::ARCUnbridgedCast: + case clang::BuiltinType::OCLEvent: + case clang::BuiltinType::OCLImage1d: + case clang::BuiltinType::OCLImage1dArray: + case clang::BuiltinType::OCLImage1dBuffer: + case clang::BuiltinType::OCLImage2d: + case clang::BuiltinType::OCLImage2dArray: + case clang::BuiltinType::OCLImage3d: + case clang::BuiltinType::OCLSampler: + return eBasicTypeOther; + } + } + } + return eBasicTypeInvalid; +} + + +#pragma mark Aggregate Types + +uint32_t +ClangASTContext::GetNumDirectBaseClasses (const ClangASTType& type) +{ + if (!type) + return 0; + ClangASTContext *ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return 0; + + uint32_t count = 0; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + count = cxx_record_decl->getNumBases(); + } + break; + + case clang::Type::ObjCObjectPointer: + count = GetNumDirectBaseClasses(ast->GetPointeeType(type.GetOpaqueQualType())); + break; + + case clang::Type::ObjCObject: + if (ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + + if (class_interface_decl && class_interface_decl->getSuperClass()) + count = 1; + } + } + break; + case clang::Type::ObjCInterface: + if (ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::ObjCInterfaceType *objc_interface_type = qual_type->getAs(); + if (objc_interface_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface(); + + if (class_interface_decl && class_interface_decl->getSuperClass()) + count = 1; + } + } + break; + + + case clang::Type::Typedef: + count = GetNumDirectBaseClasses(ClangASTType (ast->getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType())); + break; + + case clang::Type::Elaborated: + count = GetNumDirectBaseClasses(ClangASTType (ast->getASTContext(), llvm::cast(qual_type)->getNamedType())); + break; + + case clang::Type::Paren: + return GetNumDirectBaseClasses(ClangASTType (ast->getASTContext(), llvm::cast(qual_type)->desugar())); + + default: + break; + } + return count; +} + +uint32_t +ClangASTContext::GetNumVirtualBaseClasses (const ClangASTType& type) +{ + if (!type) + return 0; + ClangASTContext *ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return 0; + + uint32_t count = 0; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + count = cxx_record_decl->getNumVBases(); + } + break; + + case clang::Type::Typedef: + count = GetNumVirtualBaseClasses(ClangASTType (ast->getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType())); + break; + + case clang::Type::Elaborated: + count = GetNumVirtualBaseClasses(ClangASTType (ast->getASTContext(), llvm::cast(qual_type)->getNamedType())); + break; + + case clang::Type::Paren: + count = GetNumVirtualBaseClasses(ClangASTType (ast->getASTContext(), llvm::cast(qual_type)->desugar())); + break; + + default: + break; + } + return count; +} + +uint32_t +ClangASTContext::GetNumFields (void* type) +{ + if (!type) + return 0; + + uint32_t count = 0; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (GetCompleteType(type)) + { + const clang::RecordType *record_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (record_type) + { + clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl) + { + uint32_t field_idx = 0; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field) + ++field_idx; + count = field_idx; + } + } + } + break; + + case clang::Type::Typedef: + count = ClangASTType (getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumFields(); + break; + + case clang::Type::Elaborated: + count = ClangASTType (getASTContext(), llvm::cast(qual_type)->getNamedType()).GetNumFields(); + break; + + case clang::Type::Paren: + count = ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()).GetNumFields(); + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType(type)) + { + const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + + if (class_interface_decl) + count = class_interface_decl->ivar_size(); + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + + if (class_interface_decl) + count = class_interface_decl->ivar_size(); + } + } + break; + + default: + break; + } + return count; +} + +ClangASTType +ClangASTContext::GetDirectBaseClassAtIndex (const ClangASTType& type, size_t idx, uint32_t *bit_offset_ptr) +{ + if (!type) + return ClangASTType(); + ClangASTContext *ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return ClangASTType(); + + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + uint32_t curr_idx = 0; + clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; + ++base_class, ++curr_idx) + { + if (curr_idx == idx) + { + if (bit_offset_ptr) + { + const clang::ASTRecordLayout &record_layout = ast->getASTContext()->getASTRecordLayout(cxx_record_decl); + const clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); + if (base_class->isVirtual()) + *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; + else + *bit_offset_ptr = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; + } + return ClangASTType (ast, base_class->getType().getAsOpaquePtr()); + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + return GetDirectBaseClassAtIndex(ast->GetPointeeType(type.GetOpaqueQualType()), idx, bit_offset_ptr); + + case clang::Type::ObjCObject: + if (idx == 0 && ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + + if (class_interface_decl) + { + clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); + if (superclass_interface_decl) + { + if (bit_offset_ptr) + *bit_offset_ptr = 0; + return ClangASTType (ast->getASTContext(), ast->getASTContext()->getObjCInterfaceType(superclass_interface_decl)); + } + } + } + } + break; + case clang::Type::ObjCInterface: + if (idx == 0 && ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::ObjCObjectType *objc_interface_type = qual_type->getAs(); + if (objc_interface_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface(); + + if (class_interface_decl) + { + clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); + if (superclass_interface_decl) + { + if (bit_offset_ptr) + *bit_offset_ptr = 0; + return ClangASTType (ast->getASTContext(), ast->getASTContext()->getObjCInterfaceType(superclass_interface_decl)); + } + } + } + } + break; + + + case clang::Type::Typedef: + return GetDirectBaseClassAtIndex (ClangASTType (ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), idx, bit_offset_ptr); + + case clang::Type::Elaborated: + return GetDirectBaseClassAtIndex (ClangASTType (ast, llvm::cast(qual_type)->getNamedType().getAsOpaquePtr()), idx, bit_offset_ptr); + + case clang::Type::Paren: + return GetDirectBaseClassAtIndex (ClangASTType (ast, llvm::cast(qual_type)->desugar().getAsOpaquePtr()), idx, bit_offset_ptr); + + default: + break; + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::GetVirtualBaseClassAtIndex (const ClangASTType& type, size_t idx, uint32_t *bit_offset_ptr) +{ + if (!type) + return ClangASTType(); + ClangASTContext *ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return ClangASTType(); + + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + uint32_t curr_idx = 0; + clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->vbases_begin(), base_class_end = cxx_record_decl->vbases_end(); + base_class != base_class_end; + ++base_class, ++curr_idx) + { + if (curr_idx == idx) + { + if (bit_offset_ptr) + { + const clang::ASTRecordLayout &record_layout = ast->getASTContext()->getASTRecordLayout(cxx_record_decl); + const clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); + *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; + + } + return ClangASTType (ast, base_class->getType().getAsOpaquePtr()); + } + } + } + } + break; + + case clang::Type::Typedef: + return GetVirtualBaseClassAtIndex (ClangASTType (ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), idx, bit_offset_ptr); + + case clang::Type::Elaborated: + return GetVirtualBaseClassAtIndex (ClangASTType (ast, llvm::cast(qual_type)->getNamedType().getAsOpaquePtr()), idx, bit_offset_ptr); + + case clang::Type::Paren: + return GetVirtualBaseClassAtIndex (ClangASTType (ast, llvm::cast(qual_type)->desugar().getAsOpaquePtr()), idx, bit_offset_ptr); + + default: + break; + } + return ClangASTType(); +} + +static clang_type_t +GetObjCFieldAtIndex (clang::ASTContext *ast, + clang::ObjCInterfaceDecl *class_interface_decl, + size_t idx, + std::string& name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) +{ + if (class_interface_decl) + { + if (idx < (class_interface_decl->ivar_size())) + { + clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); + uint32_t ivar_idx = 0; + + for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++ivar_idx) + { + if (ivar_idx == idx) + { + const clang::ObjCIvarDecl* ivar_decl = *ivar_pos; + + clang::QualType ivar_qual_type(ivar_decl->getType()); + + name.assign(ivar_decl->getNameAsString()); + + if (bit_offset_ptr) + { + const clang::ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl); + *bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx); + } + + const bool is_bitfield = ivar_pos->isBitField(); + + if (bitfield_bit_size_ptr) + { + *bitfield_bit_size_ptr = 0; + + if (is_bitfield && ast) + { + clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth(); + llvm::APSInt bitfield_apsint; + if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast)) + { + *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); + } + } + } + if (is_bitfield_ptr) + *is_bitfield_ptr = is_bitfield; + + return ivar_qual_type.getAsOpaquePtr(); + } + } + } + } + return nullptr; +} + +ClangASTType +ClangASTContext::GetFieldAtIndex (void* type, size_t idx, + std::string& name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) +{ + if (!type) + return ClangASTType(); + + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (GetCompleteType(type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + uint32_t field_idx = 0; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx) + { + if (idx == field_idx) + { + // Print the member type if requested + // Print the member name and equal sign + name.assign(field->getNameAsString()); + + // Figure out the type byte size (field_type_info.first) and + // alignment (field_type_info.second) from the AST context. + if (bit_offset_ptr) + { + const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(record_decl); + *bit_offset_ptr = record_layout.getFieldOffset (field_idx); + } + + const bool is_bitfield = field->isBitField(); + + if (bitfield_bit_size_ptr) + { + *bitfield_bit_size_ptr = 0; + + if (is_bitfield) + { + clang::Expr *bitfield_bit_size_expr = field->getBitWidth(); + llvm::APSInt bitfield_apsint; + if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *getASTContext())) + { + *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); + } + } + } + if (is_bitfield_ptr) + *is_bitfield_ptr = is_bitfield; + + return ClangASTType (getASTContext(), field->getType()); + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType(type)) + { + const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + return ClangASTType (this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + assert (objc_class_type); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + return ClangASTType (this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); + } + } + break; + + + case clang::Type::Typedef: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()). + GetFieldAtIndex (idx, + name, + bit_offset_ptr, + bitfield_bit_size_ptr, + is_bitfield_ptr); + + case clang::Type::Elaborated: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getNamedType()). + GetFieldAtIndex (idx, + name, + bit_offset_ptr, + bitfield_bit_size_ptr, + is_bitfield_ptr); + + case clang::Type::Paren: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()). + GetFieldAtIndex (idx, + name, + bit_offset_ptr, + bitfield_bit_size_ptr, + is_bitfield_ptr); + + default: + break; + } + return ClangASTType(); +} + +// If a pointer to a pointee type (the clang_type arg) says that it has no +// children, then we either need to trust it, or override it and return a +// different result. For example, an "int *" has one child that is an integer, +// but a function pointer doesn't have any children. Likewise if a Record type +// claims it has no children, then there really is nothing to show. +uint32_t +ClangASTContext::GetNumPointeeChildren (clang::QualType type) +{ + if (type.isNull()) + return 0; + + clang::QualType qual_type(type.getCanonicalType()); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Builtin: + switch (llvm::cast(qual_type)->getKind()) + { + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::Void: + case clang::BuiltinType::NullPtr: + case clang::BuiltinType::OCLEvent: + case clang::BuiltinType::OCLImage1d: + case clang::BuiltinType::OCLImage1dArray: + case clang::BuiltinType::OCLImage1dBuffer: + case clang::BuiltinType::OCLImage2d: + case clang::BuiltinType::OCLImage2dArray: + case clang::BuiltinType::OCLImage3d: + case clang::BuiltinType::OCLSampler: + return 0; + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + case clang::BuiltinType::Dependent: + case clang::BuiltinType::Overload: + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCSel: + case clang::BuiltinType::BoundMember: + case clang::BuiltinType::Half: + case clang::BuiltinType::ARCUnbridgedCast: + case clang::BuiltinType::PseudoObject: + case clang::BuiltinType::BuiltinFn: + return 1; + } + break; + + case clang::Type::Complex: return 1; + case clang::Type::Pointer: return 1; + case clang::Type::BlockPointer: return 0; // If block pointers don't have debug info, then no children for them + case clang::Type::LValueReference: return 1; + case clang::Type::RValueReference: return 1; + case clang::Type::MemberPointer: return 0; + case clang::Type::ConstantArray: return 0; + case clang::Type::IncompleteArray: return 0; + case clang::Type::VariableArray: return 0; + case clang::Type::DependentSizedArray: return 0; + case clang::Type::DependentSizedExtVector: return 0; + case clang::Type::Vector: return 0; + case clang::Type::ExtVector: return 0; + case clang::Type::FunctionProto: return 0; // When we function pointers, they have no children... + case clang::Type::FunctionNoProto: return 0; // When we function pointers, they have no children... + case clang::Type::UnresolvedUsing: return 0; + case clang::Type::Paren: return GetNumPointeeChildren (llvm::cast(qual_type)->desugar()); + case clang::Type::Typedef: return GetNumPointeeChildren (llvm::cast(qual_type)->getDecl()->getUnderlyingType()); + case clang::Type::Elaborated: return GetNumPointeeChildren (llvm::cast(qual_type)->getNamedType()); + case clang::Type::TypeOfExpr: return 0; + case clang::Type::TypeOf: return 0; + case clang::Type::Decltype: return 0; + case clang::Type::Record: return 0; + case clang::Type::Enum: return 1; + case clang::Type::TemplateTypeParm: return 1; + case clang::Type::SubstTemplateTypeParm: return 1; + case clang::Type::TemplateSpecialization: return 1; + case clang::Type::InjectedClassName: return 0; + case clang::Type::DependentName: return 1; + case clang::Type::DependentTemplateSpecialization: return 1; + case clang::Type::ObjCObject: return 0; + case clang::Type::ObjCInterface: return 0; + case clang::Type::ObjCObjectPointer: return 1; + default: + break; + } + return 0; +} + + +ClangASTType +ClangASTContext::GetChildClangTypeAtIndex (void* type, ExecutionContext *exe_ctx, + size_t idx, + bool transparent_pointers, + bool omit_empty_base_classes, + bool ignore_array_bounds, + std::string& child_name, + uint32_t &child_byte_size, + int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, + uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, + bool &child_is_deref_of_parent, + ValueObject *valobj) +{ + if (!type) + return ClangASTType(); + + clang::QualType parent_qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass(); + child_bitfield_bit_size = 0; + child_bitfield_bit_offset = 0; + child_is_base_class = false; + + const bool idx_is_valid = idx < GetNumChildren (type, omit_empty_base_classes); + uint32_t bit_offset; + switch (parent_type_class) + { + case clang::Type::Builtin: + if (idx_is_valid) + { + switch (llvm::cast(parent_qual_type)->getKind()) + { + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + child_name = "isa"; + child_byte_size = getASTContext()->getTypeSize(getASTContext()->ObjCBuiltinClassTy) / CHAR_BIT; + return ClangASTType (getASTContext(), getASTContext()->ObjCBuiltinClassTy); + + default: + break; + } + } + break; + + case clang::Type::Record: + if (idx_is_valid && GetCompleteType(type)) + { + const clang::RecordType *record_type = llvm::cast(parent_qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(record_decl); + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + if (cxx_record_decl) + { + // We might have base classes to print out first + clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; + ++base_class) + { + const clang::CXXRecordDecl *base_class_decl = nullptr; + + // Skip empty base classes + if (omit_empty_base_classes) + { + base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); + if (ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + } + + if (idx == child_idx) + { + if (base_class_decl == nullptr) + base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); + + + if (base_class->isVirtual()) + { + bool handled = false; + if (valobj) + { + Error err; + AddressType addr_type = eAddressTypeInvalid; + lldb::addr_t vtable_ptr_addr = valobj->GetCPPVTableAddress(addr_type); + + if (vtable_ptr_addr != LLDB_INVALID_ADDRESS && addr_type == eAddressTypeLoad) + { + + ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process) + { + clang::VTableContextBase *vtable_ctx = getASTContext()->getVTableContext(); + if (vtable_ctx) + { + if (vtable_ctx->isMicrosoft()) + { + clang::MicrosoftVTableContext *msoft_vtable_ctx = static_cast(vtable_ctx); + + if (vtable_ptr_addr) + { + const lldb::addr_t vbtable_ptr_addr = vtable_ptr_addr + record_layout.getVBPtrOffset().getQuantity(); + + const lldb::addr_t vbtable_ptr = process->ReadPointerFromMemory(vbtable_ptr_addr, err); + if (vbtable_ptr != LLDB_INVALID_ADDRESS) + { + // Get the index into the virtual base table. The index is the index in uint32_t from vbtable_ptr + const unsigned vbtable_index = msoft_vtable_ctx->getVBTableIndex(cxx_record_decl, base_class_decl); + const lldb::addr_t base_offset_addr = vbtable_ptr + vbtable_index * 4; + const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err); + if (base_offset != UINT32_MAX) + { + handled = true; + bit_offset = base_offset * 8; + } + } + } + } + else + { + clang::ItaniumVTableContext *itanium_vtable_ctx = static_cast(vtable_ctx); + if (vtable_ptr_addr) + { + const lldb::addr_t vtable_ptr = process->ReadPointerFromMemory(vtable_ptr_addr, err); + if (vtable_ptr != LLDB_INVALID_ADDRESS) + { + clang::CharUnits base_offset_offset = itanium_vtable_ctx->getVirtualBaseOffsetOffset(cxx_record_decl, base_class_decl); + const lldb::addr_t base_offset_addr = vtable_ptr + base_offset_offset.getQuantity(); + const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err); + if (base_offset != UINT32_MAX) + { + handled = true; + bit_offset = base_offset * 8; + } + } + } + } + } + } + } + + } + if (!handled) + bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; + } + else + bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; + + // Base classes should be a multiple of 8 bits in size + child_byte_offset = bit_offset/8; + ClangASTType base_class_clang_type(getASTContext(), base_class->getType()); + child_name = base_class_clang_type.GetTypeName().AsCString(""); + uint64_t base_class_clang_type_bit_size = base_class_clang_type.GetBitSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + + // Base classes bit sizes should be a multiple of 8 bits in size + assert (base_class_clang_type_bit_size % 8 == 0); + child_byte_size = base_class_clang_type_bit_size / 8; + child_is_base_class = true; + return base_class_clang_type; + } + // We don't increment the child index in the for loop since we might + // be skipping empty base classes + ++child_idx; + } + } + // Make sure index is in range... + uint32_t field_idx = 0; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx) + { + if (idx == child_idx) + { + // Print the member type if requested + // Print the member name and equal sign + child_name.assign(field->getNameAsString().c_str()); + + // Figure out the type byte size (field_type_info.first) and + // alignment (field_type_info.second) from the AST context. + ClangASTType field_clang_type (getASTContext(), field->getType()); + assert(field_idx < record_layout.getFieldCount()); + child_byte_size = field_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + + // Figure out the field offset within the current struct/union/class type + bit_offset = record_layout.getFieldOffset (field_idx); + child_byte_offset = bit_offset / 8; + if (ClangASTContext::FieldIsBitfield (getASTContext(), *field, child_bitfield_bit_size)) + child_bitfield_bit_offset = bit_offset % 8; + + return field_clang_type; + } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (idx_is_valid && GetCompleteType(type)) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(parent_qual_type.getTypePtr()); + assert (objc_class_type); + if (objc_class_type) + { + uint32_t child_idx = 0; + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + + if (class_interface_decl) + { + + const clang::ASTRecordLayout &interface_layout = getASTContext()->getASTObjCInterfaceLayout(class_interface_decl); + clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); + if (superclass_interface_decl) + { + if (omit_empty_base_classes) + { + ClangASTType base_class_clang_type (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl)); + if (base_class_clang_type.GetNumChildren(omit_empty_base_classes) > 0) + { + if (idx == 0) + { + clang::QualType ivar_qual_type(getASTContext()->getObjCInterfaceType(superclass_interface_decl)); + + + child_name.assign(superclass_interface_decl->getNameAsString().c_str()); + + clang::TypeInfo ivar_type_info = getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr()); + + child_byte_size = ivar_type_info.Width / 8; + child_byte_offset = 0; + child_is_base_class = true; + + return ClangASTType (getASTContext(), ivar_qual_type); + } + + ++child_idx; + } + } + else + ++child_idx; + } + + const uint32_t superclass_idx = child_idx; + + if (idx < (child_idx + class_interface_decl->ivar_size())) + { + clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); + + for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos) + { + if (child_idx == idx) + { + clang::ObjCIvarDecl* ivar_decl = *ivar_pos; + + clang::QualType ivar_qual_type(ivar_decl->getType()); + + child_name.assign(ivar_decl->getNameAsString().c_str()); + + clang::TypeInfo ivar_type_info = getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr()); + + child_byte_size = ivar_type_info.Width / 8; + + // Figure out the field offset within the current struct/union/class type + // For ObjC objects, we can't trust the bit offset we get from the Clang AST, since + // that doesn't account for the space taken up by unbacked properties, or from + // the changing size of base classes that are newer than this class. + // So if we have a process around that we can ask about this object, do so. + child_byte_offset = LLDB_INVALID_IVAR_OFFSET; + Process *process = nullptr; + if (exe_ctx) + process = exe_ctx->GetProcessPtr(); + if (process) + { + ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); + if (objc_runtime != nullptr) + { + ClangASTType parent_ast_type (getASTContext(), parent_qual_type); + child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str()); + } + } + + // Setting this to UINT32_MAX to make sure we don't compute it twice... + bit_offset = UINT32_MAX; + + if (child_byte_offset == static_cast(LLDB_INVALID_IVAR_OFFSET)) + { + bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); + child_byte_offset = bit_offset / 8; + } + + // Note, the ObjC Ivar Byte offset is just that, it doesn't account for the bit offset + // of a bitfield within its containing object. So regardless of where we get the byte + // offset from, we still need to get the bit offset for bitfields from the layout. + + if (ClangASTContext::FieldIsBitfield (getASTContext(), ivar_decl, child_bitfield_bit_size)) + { + if (bit_offset == UINT32_MAX) + bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); + + child_bitfield_bit_offset = bit_offset % 8; + } + return ClangASTType (getASTContext(), ivar_qual_type); + } + ++child_idx; + } + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + if (idx_is_valid) + { + ClangASTType pointee_clang_type (GetPointeeType(type)); + + if (transparent_pointers && pointee_clang_type.IsAggregateType()) + { + child_is_deref_of_parent = false; + bool tmp_child_is_deref_of_parent = false; + return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx, + idx, + transparent_pointers, + omit_empty_base_classes, + ignore_array_bounds, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + tmp_child_is_deref_of_parent, + valobj); + } + else + { + child_is_deref_of_parent = true; + const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; + if (parent_name) + { + child_name.assign(1, '*'); + child_name += parent_name; + } + + // We have a pointer to an simple type + if (idx == 0 && pointee_clang_type.GetCompleteType()) + { + child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = 0; + return pointee_clang_type; + } + } + } + break; + + case clang::Type::Vector: + case clang::Type::ExtVector: + if (idx_is_valid) + { + const clang::VectorType *array = llvm::cast(parent_qual_type.getTypePtr()); + if (array) + { + ClangASTType element_type (getASTContext(), array->getElementType()); + if (element_type.GetCompleteType()) + { + char element_name[64]; + ::snprintf (element_name, sizeof (element_name), "[%" PRIu64 "]", static_cast(idx)); + child_name.assign(element_name); + child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; + return element_type; + } + } + } + break; + + case clang::Type::ConstantArray: + case clang::Type::IncompleteArray: + if (ignore_array_bounds || idx_is_valid) + { + const clang::ArrayType *array = GetQualType(type)->getAsArrayTypeUnsafe(); + if (array) + { + ClangASTType element_type (getASTContext(), array->getElementType()); + if (element_type.GetCompleteType()) + { + char element_name[64]; + ::snprintf (element_name, sizeof (element_name), "[%" PRIu64 "]", static_cast(idx)); + child_name.assign(element_name); + child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; + return element_type; + } + } + } + break; + + + case clang::Type::Pointer: + if (idx_is_valid) + { + ClangASTType pointee_clang_type (GetPointeeType(type)); + + // Don't dereference "void *" pointers + if (pointee_clang_type.IsVoidType()) + return ClangASTType(); + + if (transparent_pointers && pointee_clang_type.IsAggregateType ()) + { + child_is_deref_of_parent = false; + bool tmp_child_is_deref_of_parent = false; + return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx, + idx, + transparent_pointers, + omit_empty_base_classes, + ignore_array_bounds, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + tmp_child_is_deref_of_parent, + valobj); + } + else + { + child_is_deref_of_parent = true; + + const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; + if (parent_name) + { + child_name.assign(1, '*'); + child_name += parent_name; + } + + // We have a pointer to an simple type + if (idx == 0) + { + child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = 0; + return pointee_clang_type; + } + } + } + break; + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + if (idx_is_valid) + { + const clang::ReferenceType *reference_type = llvm::cast(parent_qual_type.getTypePtr()); + ClangASTType pointee_clang_type (getASTContext(), reference_type->getPointeeType()); + if (transparent_pointers && pointee_clang_type.IsAggregateType ()) + { + child_is_deref_of_parent = false; + bool tmp_child_is_deref_of_parent = false; + return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx, + idx, + transparent_pointers, + omit_empty_base_classes, + ignore_array_bounds, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + tmp_child_is_deref_of_parent, + valobj); + } + else + { + const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; + if (parent_name) + { + child_name.assign(1, '&'); + child_name += parent_name; + } + + // We have a pointer to an simple type + if (idx == 0) + { + child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = 0; + return pointee_clang_type; + } + } + } + break; + + case clang::Type::Typedef: + { + ClangASTType typedefed_clang_type (getASTContext(), llvm::cast(parent_qual_type)->getDecl()->getUnderlyingType()); + return typedefed_clang_type.GetChildClangTypeAtIndex (exe_ctx, + idx, + transparent_pointers, + omit_empty_base_classes, + ignore_array_bounds, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent, + valobj); + } + break; + + case clang::Type::Elaborated: + { + ClangASTType elaborated_clang_type (getASTContext(), llvm::cast(parent_qual_type)->getNamedType()); + return elaborated_clang_type.GetChildClangTypeAtIndex (exe_ctx, + idx, + transparent_pointers, + omit_empty_base_classes, + ignore_array_bounds, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent, + valobj); + } + + case clang::Type::Paren: + { + ClangASTType paren_clang_type (getASTContext(), llvm::cast(parent_qual_type)->desugar()); + return paren_clang_type.GetChildClangTypeAtIndex (exe_ctx, + idx, + transparent_pointers, + omit_empty_base_classes, + ignore_array_bounds, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent, + valobj); + } + + + default: + break; + } + return ClangASTType(); +} + +static uint32_t +GetIndexForRecordBase +( + const clang::RecordDecl *record_decl, + const clang::CXXBaseSpecifier *base_spec, + bool omit_empty_base_classes + ) +{ + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + + // const char *super_name = record_decl->getNameAsCString(); + // const char *base_name = base_spec->getType()->getAs()->getDecl()->getNameAsCString(); + // printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name); + // + if (cxx_record_decl) + { + clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; + ++base_class) + { + if (omit_empty_base_classes) + { + if (BaseSpecifierIsEmpty (base_class)) + continue; + } + + // printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", super_name, base_name, + // child_idx, + // base_class->getType()->getAs()->getDecl()->getNameAsCString()); + // + // + if (base_class == base_spec) + return child_idx; + ++child_idx; + } + } + + return UINT32_MAX; +} + + +static uint32_t +GetIndexForRecordChild (const clang::RecordDecl *record_decl, + clang::NamedDecl *canonical_decl, + bool omit_empty_base_classes) +{ + uint32_t child_idx = ClangASTContext::GetNumBaseClasses (llvm::dyn_cast(record_decl), + omit_empty_base_classes); + + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), field_end = record_decl->field_end(); + field != field_end; + ++field, ++child_idx) + { + if (field->getCanonicalDecl() == canonical_decl) + return child_idx; + } + + return UINT32_MAX; +} + +// Look for a child member (doesn't include base classes, but it does include +// their members) in the type hierarchy. Returns an index path into "clang_type" +// on how to reach the appropriate member. +// +// class A +// { +// public: +// int m_a; +// int m_b; +// }; +// +// class B +// { +// }; +// +// class C : +// public B, +// public A +// { +// }; +// +// If we have a clang type that describes "class C", and we wanted to looked +// "m_b" in it: +// +// With omit_empty_base_classes == false we would get an integer array back with: +// { 1, 1 } +// The first index 1 is the child index for "class A" within class C +// The second index 1 is the child index for "m_b" within class A +// +// With omit_empty_base_classes == true we would get an integer array back with: +// { 0, 1 } +// The first index 0 is the child index for "class A" within class C (since class B doesn't have any members it doesn't count) +// The second index 1 is the child index for "m_b" within class A + +size_t +ClangASTContext::GetIndexOfChildMemberWithName (void* type, const char *name, + bool omit_empty_base_classes, + std::vector& child_indexes) +{ + if (type && name && name[0]) + { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (GetCompleteType(type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + + assert(record_decl); + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + + // Try and find a field that matches NAME + clang::RecordDecl::field_iterator field, field_end; + llvm::StringRef name_sref(name); + for (field = record_decl->field_begin(), field_end = record_decl->field_end(); + field != field_end; + ++field, ++child_idx) + { + llvm::StringRef field_name = field->getName(); + if (field_name.empty()) + { + ClangASTType field_type(getASTContext(),field->getType()); + child_indexes.push_back(child_idx); + if (field_type.GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes)) + return child_indexes.size(); + child_indexes.pop_back(); + + } + else if (field_name.equals (name_sref)) + { + // We have to add on the number of base classes to this index! + child_indexes.push_back (child_idx + ClangASTContext::GetNumBaseClasses (cxx_record_decl, omit_empty_base_classes)); + return child_indexes.size(); + } + } + + if (cxx_record_decl) + { + const clang::RecordDecl *parent_record_decl = cxx_record_decl; + + //printf ("parent = %s\n", parent_record_decl->getNameAsCString()); + + //const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl(); + // Didn't find things easily, lets let clang do its thang... + clang::IdentifierInfo & ident_ref = getASTContext()->Idents.get(name_sref); + clang::DeclarationName decl_name(&ident_ref); + + clang::CXXBasePaths paths; + if (cxx_record_decl->lookupInBases(clang::CXXRecordDecl::FindOrdinaryMember, + decl_name.getAsOpaquePtr(), + paths)) + { + clang::CXXBasePaths::const_paths_iterator path, path_end = paths.end(); + for (path = paths.begin(); path != path_end; ++path) + { + const size_t num_path_elements = path->size(); + for (size_t e=0; e(elem.Base->getType()->getAs()->getDecl()); + } + } + for (clang::NamedDecl *path_decl : path->Decls) + { + child_idx = GetIndexForRecordChild (parent_record_decl, path_decl, omit_empty_base_classes); + if (child_idx == UINT32_MAX) + { + child_indexes.clear(); + return 0; + } + else + { + child_indexes.push_back (child_idx); + } + } + } + return child_indexes.size(); + } + } + + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) + { + llvm::StringRef name_sref(name); + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + assert (objc_class_type); + if (objc_class_type) + { + uint32_t child_idx = 0; + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + + if (class_interface_decl) + { + clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); + clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); + + for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx) + { + const clang::ObjCIvarDecl* ivar_decl = *ivar_pos; + + if (ivar_decl->getName().equals (name_sref)) + { + if ((!omit_empty_base_classes && superclass_interface_decl) || + ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true))) + ++child_idx; + + child_indexes.push_back (child_idx); + return child_indexes.size(); + } + } + + if (superclass_interface_decl) + { + // The super class index is always zero for ObjC classes, + // so we push it onto the child indexes in case we find + // an ivar in our superclass... + child_indexes.push_back (0); + + ClangASTType superclass_clang_type (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl)); + if (superclass_clang_type.GetIndexOfChildMemberWithName (name, + omit_empty_base_classes, + child_indexes)) + { + // We did find an ivar in a superclass so just + // return the results! + return child_indexes.size(); + } + + // We didn't find an ivar matching "name" in our + // superclass, pop the superclass zero index that + // we pushed on above. + child_indexes.pop_back(); + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + { + ClangASTType objc_object_clang_type (getASTContext(), llvm::cast(qual_type.getTypePtr())->getPointeeType()); + return objc_object_clang_type.GetIndexOfChildMemberWithName (name, + omit_empty_base_classes, + child_indexes); + } + break; + + + case clang::Type::ConstantArray: + { + // const clang::ConstantArrayType *array = llvm::cast(parent_qual_type.getTypePtr()); + // const uint64_t element_count = array->getSize().getLimitedValue(); + // + // if (idx < element_count) + // { + // std::pair field_type_info = ast->getTypeInfo(array->getElementType()); + // + // char element_name[32]; + // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx); + // + // child_name.assign(element_name); + // assert(field_type_info.first % 8 == 0); + // child_byte_size = field_type_info.first / 8; + // child_byte_offset = idx * child_byte_size; + // return array->getElementType().getAsOpaquePtr(); + // } + } + break; + + // case clang::Type::MemberPointerType: + // { + // MemberPointerType *mem_ptr_type = llvm::cast(qual_type.getTypePtr()); + // clang::QualType pointee_type = mem_ptr_type->getPointeeType(); + // + // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) + // { + // return GetIndexOfChildWithName (ast, + // mem_ptr_type->getPointeeType().getAsOpaquePtr(), + // name); + // } + // } + // break; + // + case clang::Type::LValueReference: + case clang::Type::RValueReference: + { + const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); + clang::QualType pointee_type(reference_type->getPointeeType()); + ClangASTType pointee_clang_type (getASTContext(), pointee_type); + + if (pointee_clang_type.IsAggregateType ()) + { + return pointee_clang_type.GetIndexOfChildMemberWithName (name, + omit_empty_base_classes, + child_indexes); + } + } + break; + + case clang::Type::Pointer: + { + ClangASTType pointee_clang_type (GetPointeeType(type)); + + if (pointee_clang_type.IsAggregateType ()) + { + return pointee_clang_type.GetIndexOfChildMemberWithName (name, + omit_empty_base_classes, + child_indexes); + } + } + break; + + case clang::Type::Typedef: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildMemberWithName (name, + omit_empty_base_classes, + child_indexes); + + case clang::Type::Elaborated: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getNamedType()).GetIndexOfChildMemberWithName (name, + omit_empty_base_classes, + child_indexes); + + case clang::Type::Paren: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()).GetIndexOfChildMemberWithName (name, + omit_empty_base_classes, + child_indexes); + + default: + break; + } + } + return 0; +} + + +// Get the index of the child of "clang_type" whose name matches. This function +// doesn't descend into the children, but only looks one level deep and name +// matches can include base class names. + +uint32_t +ClangASTContext::GetIndexOfChildWithName (void* type, const char *name, bool omit_empty_base_classes) +{ + if (type && name && name[0]) + { + clang::QualType qual_type(GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + + switch (type_class) + { + case clang::Type::Record: + if (GetCompleteType(type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + + assert(record_decl); + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + + if (cxx_record_decl) + { + clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; + ++base_class) + { + // Skip empty base classes + clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); + if (omit_empty_base_classes && ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + + ClangASTType base_class_clang_type (getASTContext(), base_class->getType()); + std::string base_class_type_name (base_class_clang_type.GetTypeName().AsCString("")); + if (base_class_type_name.compare (name) == 0) + return child_idx; + ++child_idx; + } + } + + // Try and find a field that matches NAME + clang::RecordDecl::field_iterator field, field_end; + llvm::StringRef name_sref(name); + for (field = record_decl->field_begin(), field_end = record_decl->field_end(); + field != field_end; + ++field, ++child_idx) + { + if (field->getName().equals (name_sref)) + return child_idx; + } + + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) + { + llvm::StringRef name_sref(name); + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + assert (objc_class_type); + if (objc_class_type) + { + uint32_t child_idx = 0; + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + + if (class_interface_decl) + { + clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); + clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); + + for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx) + { + const clang::ObjCIvarDecl* ivar_decl = *ivar_pos; + + if (ivar_decl->getName().equals (name_sref)) + { + if ((!omit_empty_base_classes && superclass_interface_decl) || + ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true))) + ++child_idx; + + return child_idx; + } + } + + if (superclass_interface_decl) + { + if (superclass_interface_decl->getName().equals (name_sref)) + return 0; + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + { + ClangASTType pointee_clang_type (getASTContext(), llvm::cast(qual_type.getTypePtr())->getPointeeType()); + return pointee_clang_type.GetIndexOfChildWithName (name, omit_empty_base_classes); + } + break; + + case clang::Type::ConstantArray: + { + // const clang::ConstantArrayType *array = llvm::cast(parent_qual_type.getTypePtr()); + // const uint64_t element_count = array->getSize().getLimitedValue(); + // + // if (idx < element_count) + // { + // std::pair field_type_info = ast->getTypeInfo(array->getElementType()); + // + // char element_name[32]; + // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx); + // + // child_name.assign(element_name); + // assert(field_type_info.first % 8 == 0); + // child_byte_size = field_type_info.first / 8; + // child_byte_offset = idx * child_byte_size; + // return array->getElementType().getAsOpaquePtr(); + // } + } + break; + + // case clang::Type::MemberPointerType: + // { + // MemberPointerType *mem_ptr_type = llvm::cast(qual_type.getTypePtr()); + // clang::QualType pointee_type = mem_ptr_type->getPointeeType(); + // + // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) + // { + // return GetIndexOfChildWithName (ast, + // mem_ptr_type->getPointeeType().getAsOpaquePtr(), + // name); + // } + // } + // break; + // + case clang::Type::LValueReference: + case clang::Type::RValueReference: + { + const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); + ClangASTType pointee_type (getASTContext(), reference_type->getPointeeType()); + + if (pointee_type.IsAggregateType ()) + { + return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes); + } + } + break; + + case clang::Type::Pointer: + { + const clang::PointerType *pointer_type = llvm::cast(qual_type.getTypePtr()); + ClangASTType pointee_type (getASTContext(), pointer_type->getPointeeType()); + + if (pointee_type.IsAggregateType ()) + { + return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes); + } + else + { + // if (parent_name) + // { + // child_name.assign(1, '*'); + // child_name += parent_name; + // } + // + // // We have a pointer to an simple type + // if (idx == 0) + // { + // std::pair clang_type_info = ast->getTypeInfo(pointee_type); + // assert(clang_type_info.first % 8 == 0); + // child_byte_size = clang_type_info.first / 8; + // child_byte_offset = 0; + // return pointee_type.getAsOpaquePtr(); + // } + } + } + break; + + case clang::Type::Elaborated: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getNamedType()).GetIndexOfChildWithName (name, omit_empty_base_classes); + + case clang::Type::Paren: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()).GetIndexOfChildWithName (name, omit_empty_base_classes); + + case clang::Type::Typedef: + return ClangASTType (getASTContext(), llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildWithName (name, omit_empty_base_classes); + + default: + break; + } + } + return UINT32_MAX; +} + + +size_t +ClangASTContext::GetNumTemplateArguments (const ClangASTType& type) +{ + if (!type) + return 0; + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (ast) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast(cxx_record_decl); + if (template_decl) + return template_decl->getTemplateArgs().size(); + } + } + break; + + case clang::Type::Typedef: + return GetNumTemplateArguments(ClangASTType (ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr())); + + case clang::Type::Elaborated: + return GetNumTemplateArguments(ClangASTType (ast, llvm::cast(qual_type)->getNamedType().getAsOpaquePtr())); + + case clang::Type::Paren: + return GetNumTemplateArguments(ClangASTType (ast, llvm::cast(qual_type)->desugar().getAsOpaquePtr())); + + default: + break; + } + } + return 0; +} + +ClangASTType +ClangASTContext::GetTemplateArgument (const ClangASTType& type, size_t arg_idx, lldb::TemplateArgumentKind &kind) +{ + if (!type) + return ClangASTType(); + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (ast) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (ast->GetCompleteType(type.GetOpaqueQualType())) + { + const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast(cxx_record_decl); + if (template_decl && arg_idx < template_decl->getTemplateArgs().size()) + { + const clang::TemplateArgument &template_arg = template_decl->getTemplateArgs()[arg_idx]; + switch (template_arg.getKind()) + { + case clang::TemplateArgument::Null: + kind = eTemplateArgumentKindNull; + return ClangASTType(); + + case clang::TemplateArgument::Type: + kind = eTemplateArgumentKindType; + return ClangASTType(ast, template_arg.getAsType().getAsOpaquePtr()); + + case clang::TemplateArgument::Declaration: + kind = eTemplateArgumentKindDeclaration; + return ClangASTType(); + + case clang::TemplateArgument::Integral: + kind = eTemplateArgumentKindIntegral; + return ClangASTType(ast, template_arg.getIntegralType().getAsOpaquePtr()); + + case clang::TemplateArgument::Template: + kind = eTemplateArgumentKindTemplate; + return ClangASTType(); + + case clang::TemplateArgument::TemplateExpansion: + kind = eTemplateArgumentKindTemplateExpansion; + return ClangASTType(); + + case clang::TemplateArgument::Expression: + kind = eTemplateArgumentKindExpression; + return ClangASTType(); + + case clang::TemplateArgument::Pack: + kind = eTemplateArgumentKindPack; + return ClangASTType(); + + default: + assert (!"Unhandled clang::TemplateArgument::ArgKind"); + break; + } + } + } + } + break; + + case clang::Type::Typedef: + return GetTemplateArgument(ClangASTType (ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), arg_idx, kind); + + case clang::Type::Elaborated: + return GetTemplateArgument(ClangASTType (ast, llvm::cast(qual_type)->getNamedType().getAsOpaquePtr()), arg_idx, kind); + + case clang::Type::Paren: + return GetTemplateArgument(ClangASTType (ast, llvm::cast(qual_type)->desugar().getAsOpaquePtr()), arg_idx, kind); + + default: + break; + } + } + kind = eTemplateArgumentKindNull; + return ClangASTType (); +} + +static bool +IsOperator (const char *name, clang::OverloadedOperatorKind &op_kind) +{ + if (name == nullptr || name[0] == '\0') + return false; + +#define OPERATOR_PREFIX "operator" +#define OPERATOR_PREFIX_LENGTH (sizeof (OPERATOR_PREFIX) - 1) + + const char *post_op_name = nullptr; + + bool no_space = true; + + if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH)) + return false; + + post_op_name = name + OPERATOR_PREFIX_LENGTH; + + if (post_op_name[0] == ' ') + { + post_op_name++; + no_space = false; + } + +#undef OPERATOR_PREFIX +#undef OPERATOR_PREFIX_LENGTH + + // This is an operator, set the overloaded operator kind to invalid + // in case this is a conversion operator... + op_kind = clang::NUM_OVERLOADED_OPERATORS; + + switch (post_op_name[0]) + { + default: + if (no_space) + return false; + break; + case 'n': + if (no_space) + return false; + if (strcmp (post_op_name, "new") == 0) + op_kind = clang::OO_New; + else if (strcmp (post_op_name, "new[]") == 0) + op_kind = clang::OO_Array_New; + break; + + case 'd': + if (no_space) + return false; + if (strcmp (post_op_name, "delete") == 0) + op_kind = clang::OO_Delete; + else if (strcmp (post_op_name, "delete[]") == 0) + op_kind = clang::OO_Array_Delete; + break; + + case '+': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Plus; + else if (post_op_name[2] == '\0') + { + if (post_op_name[1] == '=') + op_kind = clang::OO_PlusEqual; + else if (post_op_name[1] == '+') + op_kind = clang::OO_PlusPlus; + } + break; + + case '-': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Minus; + else if (post_op_name[2] == '\0') + { + switch (post_op_name[1]) + { + case '=': op_kind = clang::OO_MinusEqual; break; + case '-': op_kind = clang::OO_MinusMinus; break; + case '>': op_kind = clang::OO_Arrow; break; + } + } + else if (post_op_name[3] == '\0') + { + if (post_op_name[2] == '*') + op_kind = clang::OO_ArrowStar; break; + } + break; + + case '*': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Star; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_StarEqual; + break; + + case '/': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Slash; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_SlashEqual; + break; + + case '%': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Percent; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_PercentEqual; + break; + + + case '^': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Caret; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_CaretEqual; + break; + + case '&': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Amp; + else if (post_op_name[2] == '\0') + { + switch (post_op_name[1]) + { + case '=': op_kind = clang::OO_AmpEqual; break; + case '&': op_kind = clang::OO_AmpAmp; break; + } + } + break; + + case '|': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Pipe; + else if (post_op_name[2] == '\0') + { + switch (post_op_name[1]) + { + case '=': op_kind = clang::OO_PipeEqual; break; + case '|': op_kind = clang::OO_PipePipe; break; + } + } + break; + + case '~': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Tilde; + break; + + case '!': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Exclaim; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_ExclaimEqual; + break; + + case '=': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Equal; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_EqualEqual; + break; + + case '<': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Less; + else if (post_op_name[2] == '\0') + { + switch (post_op_name[1]) + { + case '<': op_kind = clang::OO_LessLess; break; + case '=': op_kind = clang::OO_LessEqual; break; + } + } + else if (post_op_name[3] == '\0') + { + if (post_op_name[2] == '=') + op_kind = clang::OO_LessLessEqual; + } + break; + + case '>': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Greater; + else if (post_op_name[2] == '\0') + { + switch (post_op_name[1]) + { + case '>': op_kind = clang::OO_GreaterGreater; break; + case '=': op_kind = clang::OO_GreaterEqual; break; + } + } + else if (post_op_name[1] == '>' && + post_op_name[2] == '=' && + post_op_name[3] == '\0') + { + op_kind = clang::OO_GreaterGreaterEqual; + } + break; + + case ',': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Comma; + break; + + case '(': + if (post_op_name[1] == ')' && post_op_name[2] == '\0') + op_kind = clang::OO_Call; + break; + + case '[': + if (post_op_name[1] == ']' && post_op_name[2] == '\0') + op_kind = clang::OO_Subscript; + break; + } + + return true; +} + +clang::EnumDecl * +ClangASTContext::GetAsEnumDecl (const ClangASTType& type) +{ + const clang::EnumType *enutype = llvm::dyn_cast(GetCanonicalQualType(type)); + if (enutype) + return enutype->getDecl(); + return NULL; +} + +clang::RecordDecl * +ClangASTContext::GetAsRecordDecl (const ClangASTType& type) +{ + const clang::RecordType *record_type = llvm::dyn_cast(GetCanonicalQualType(type)); + if (record_type) + return record_type->getDecl(); + return nullptr; +} + +clang::CXXRecordDecl * +ClangASTContext::GetAsCXXRecordDecl (void* type) +{ + return GetCanonicalQualType(type)->getAsCXXRecordDecl(); +} + +clang::ObjCInterfaceDecl * +ClangASTContext::GetAsObjCInterfaceDecl (const ClangASTType& type) +{ + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(GetCanonicalQualType(type)); + if (objc_class_type) + return objc_class_type->getInterface(); + return nullptr; +} + +clang::FieldDecl * +ClangASTContext::AddFieldToRecordType (const ClangASTType& type, const char *name, + const ClangASTType &field_clang_type, + AccessType access, + uint32_t bitfield_bit_size) +{ + if (!type.IsValid() || !field_clang_type.IsValid()) + return nullptr; + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return nullptr; + clang::ASTContext* clang_ast = ast->getASTContext(); + + clang::FieldDecl *field = nullptr; + + clang::Expr *bit_width = nullptr; + if (bitfield_bit_size != 0) + { + llvm::APInt bitfield_bit_size_apint(clang_ast->getTypeSize(clang_ast->IntTy), bitfield_bit_size); + bit_width = new (*clang_ast)clang::IntegerLiteral (*clang_ast, bitfield_bit_size_apint, clang_ast->IntTy, clang::SourceLocation()); + } + + clang::RecordDecl *record_decl = ast->GetAsRecordDecl (type); + if (record_decl) + { + field = clang::FieldDecl::Create (*clang_ast, + record_decl, + clang::SourceLocation(), + clang::SourceLocation(), + name ? &clang_ast->Idents.get(name) : nullptr, // Identifier + GetQualType(field_clang_type), // Field type + nullptr, // TInfo * + bit_width, // BitWidth + false, // Mutable + clang::ICIS_NoInit); // HasInit + + if (!name) + { + // Determine whether this field corresponds to an anonymous + // struct or union. + if (const clang::TagType *TagT = field->getType()->getAs()) { + if (clang::RecordDecl *Rec = llvm::dyn_cast(TagT->getDecl())) + if (!Rec->getDeclName()) { + Rec->setAnonymousStructOrUnion(true); + field->setImplicit(); + + } + } + } + + if (field) + { + field->setAccess (ClangASTContext::ConvertAccessTypeToAccessSpecifier (access)); + + record_decl->addDecl(field); + +#ifdef LLDB_CONFIGURATION_DEBUG + VerifyDecl(field); +#endif + } + } + else + { + clang::ObjCInterfaceDecl *class_interface_decl = ast->GetAsObjCInterfaceDecl (type); + + if (class_interface_decl) + { + const bool is_synthesized = false; + + field_clang_type.GetCompleteType(); + + field = clang::ObjCIvarDecl::Create (*clang_ast, + class_interface_decl, + clang::SourceLocation(), + clang::SourceLocation(), + name ? &clang_ast->Idents.get(name) : nullptr, // Identifier + GetQualType(field_clang_type), // Field type + nullptr, // TypeSourceInfo * + ConvertAccessTypeToObjCIvarAccessControl (access), + bit_width, + is_synthesized); + + if (field) + { + class_interface_decl->addDecl(field); + +#ifdef LLDB_CONFIGURATION_DEBUG + VerifyDecl(field); +#endif + } + } + } + return field; +} + +void +ClangASTContext::BuildIndirectFields (const ClangASTType& type) +{ + ClangASTContext* ast = nullptr; + if (type) + ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return; + + clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type); + + if (!record_decl) + return; + + typedef llvm::SmallVector IndirectFieldVector; + + IndirectFieldVector indirect_fields; + clang::RecordDecl::field_iterator field_pos; + clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end(); + clang::RecordDecl::field_iterator last_field_pos = field_end_pos; + for (field_pos = record_decl->field_begin(); field_pos != field_end_pos; last_field_pos = field_pos++) + { + if (field_pos->isAnonymousStructOrUnion()) + { + clang::QualType field_qual_type = field_pos->getType(); + + const clang::RecordType *field_record_type = field_qual_type->getAs(); + + if (!field_record_type) + continue; + + clang::RecordDecl *field_record_decl = field_record_type->getDecl(); + + if (!field_record_decl) + continue; + + for (clang::RecordDecl::decl_iterator di = field_record_decl->decls_begin(), de = field_record_decl->decls_end(); + di != de; + ++di) + { + if (clang::FieldDecl *nested_field_decl = llvm::dyn_cast(*di)) + { + clang::NamedDecl **chain = new (*ast->getASTContext()) clang::NamedDecl*[2]; + chain[0] = *field_pos; + chain[1] = nested_field_decl; + clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*ast->getASTContext(), + record_decl, + clang::SourceLocation(), + nested_field_decl->getIdentifier(), + nested_field_decl->getType(), + chain, + 2); + + indirect_field->setImplicit(); + + indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(), + nested_field_decl->getAccess())); + + indirect_fields.push_back(indirect_field); + } + else if (clang::IndirectFieldDecl *nested_indirect_field_decl = llvm::dyn_cast(*di)) + { + int nested_chain_size = nested_indirect_field_decl->getChainingSize(); + clang::NamedDecl **chain = new (*ast->getASTContext()) clang::NamedDecl*[nested_chain_size + 1]; + chain[0] = *field_pos; + + int chain_index = 1; + for (clang::IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(), + nce = nested_indirect_field_decl->chain_end(); + nci < nce; + ++nci) + { + chain[chain_index] = *nci; + chain_index++; + } + + clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*ast->getASTContext(), + record_decl, + clang::SourceLocation(), + nested_indirect_field_decl->getIdentifier(), + nested_indirect_field_decl->getType(), + chain, + nested_chain_size + 1); + + indirect_field->setImplicit(); + + indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(), + nested_indirect_field_decl->getAccess())); + + indirect_fields.push_back(indirect_field); + } + } + } + } + + // Check the last field to see if it has an incomplete array type as its + // last member and if it does, the tell the record decl about it + if (last_field_pos != field_end_pos) + { + if (last_field_pos->getType()->isIncompleteArrayType()) + record_decl->hasFlexibleArrayMember(); + } + + for (IndirectFieldVector::iterator ifi = indirect_fields.begin(), ife = indirect_fields.end(); + ifi < ife; + ++ifi) + { + record_decl->addDecl(*ifi); + } +} + +void +ClangASTContext::SetIsPacked (const ClangASTType& type) +{ + clang::RecordDecl *record_decl = GetAsRecordDecl(type); + + if (!record_decl) + return; + + record_decl->addAttr(clang::PackedAttr::CreateImplicit(*type.GetTypeSystem()->AsClangASTContext()->getASTContext())); +} + +clang::VarDecl * +ClangASTContext::AddVariableToRecordType (const ClangASTType& type, const char *name, + const ClangASTType &var_type, + AccessType access) +{ + clang::VarDecl *var_decl = nullptr; + + if (!type.IsValid() || !var_type.IsValid()) + return nullptr; + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return nullptr; + + clang::RecordDecl *record_decl = ast->GetAsRecordDecl (type); + if (record_decl) + { + var_decl = clang::VarDecl::Create (*ast->getASTContext(), // ASTContext & + record_decl, // DeclContext * + clang::SourceLocation(), // clang::SourceLocation StartLoc + clang::SourceLocation(), // clang::SourceLocation IdLoc + name ? &ast->getASTContext()->Idents.get(name) : nullptr, // clang::IdentifierInfo * + GetQualType(var_type), // Variable clang::QualType + nullptr, // TypeSourceInfo * + clang::SC_Static); // StorageClass + if (var_decl) + { + var_decl->setAccess(ClangASTContext::ConvertAccessTypeToAccessSpecifier (access)); + record_decl->addDecl(var_decl); + +#ifdef LLDB_CONFIGURATION_DEBUG + VerifyDecl(var_decl); +#endif + } + } + return var_decl; +} + + +clang::CXXMethodDecl * +ClangASTContext::AddMethodToCXXRecordType (void* type, const char *name, + const ClangASTType &method_clang_type, + lldb::AccessType access, + bool is_virtual, + bool is_static, + bool is_inline, + bool is_explicit, + bool is_attr_used, + bool is_artificial) +{ + if (!type || !method_clang_type.IsValid() || name == nullptr || name[0] == '\0') + return nullptr; + + clang::QualType record_qual_type(GetCanonicalQualType(type)); + + clang::CXXRecordDecl *cxx_record_decl = record_qual_type->getAsCXXRecordDecl(); + + if (cxx_record_decl == nullptr) + return nullptr; + + clang::QualType method_qual_type (GetQualType(method_clang_type)); + + clang::CXXMethodDecl *cxx_method_decl = nullptr; + + clang::DeclarationName decl_name (&getASTContext()->Idents.get(name)); + + const clang::FunctionType *function_type = llvm::dyn_cast(method_qual_type.getTypePtr()); + + if (function_type == nullptr) + return nullptr; + + const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast(function_type)); + + if (!method_function_prototype) + return nullptr; + + unsigned int num_params = method_function_prototype->getNumParams(); + + clang::CXXDestructorDecl *cxx_dtor_decl(nullptr); + clang::CXXConstructorDecl *cxx_ctor_decl(nullptr); + + if (is_artificial) + return nullptr; // skip everything artificial + + if (name[0] == '~') + { + cxx_dtor_decl = clang::CXXDestructorDecl::Create (*getASTContext(), + cxx_record_decl, + clang::SourceLocation(), + clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXDestructorName (getASTContext()->getCanonicalType (record_qual_type)), clang::SourceLocation()), + method_qual_type, + nullptr, + is_inline, + is_artificial); + cxx_method_decl = cxx_dtor_decl; + } + else if (decl_name == cxx_record_decl->getDeclName()) + { + cxx_ctor_decl = clang::CXXConstructorDecl::Create (*getASTContext(), + cxx_record_decl, + clang::SourceLocation(), + clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXConstructorName (getASTContext()->getCanonicalType (record_qual_type)), clang::SourceLocation()), + method_qual_type, + nullptr, // TypeSourceInfo * + is_explicit, + is_inline, + is_artificial, + false /*is_constexpr*/); + cxx_method_decl = cxx_ctor_decl; + } + else + { + clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None; + clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS; + + if (IsOperator (name, op_kind)) + { + if (op_kind != clang::NUM_OVERLOADED_OPERATORS) + { + // Check the number of operator parameters. Sometimes we have + // seen bad DWARF that doesn't correctly describe operators and + // if we try to create a method and add it to the class, clang + // will assert and crash, so we need to make sure things are + // acceptable. + if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount (op_kind, num_params)) + return nullptr; + cxx_method_decl = clang::CXXMethodDecl::Create (*getASTContext(), + cxx_record_decl, + clang::SourceLocation(), + clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXOperatorName (op_kind), clang::SourceLocation()), + method_qual_type, + nullptr, // TypeSourceInfo * + SC, + is_inline, + false /*is_constexpr*/, + clang::SourceLocation()); + } + else if (num_params == 0) + { + // Conversion operators don't take params... + cxx_method_decl = clang::CXXConversionDecl::Create (*getASTContext(), + cxx_record_decl, + clang::SourceLocation(), + clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXConversionFunctionName (getASTContext()->getCanonicalType (function_type->getReturnType())), clang::SourceLocation()), + method_qual_type, + nullptr, // TypeSourceInfo * + is_inline, + is_explicit, + false /*is_constexpr*/, + clang::SourceLocation()); + } + } + + if (cxx_method_decl == nullptr) + { + cxx_method_decl = clang::CXXMethodDecl::Create (*getASTContext(), + cxx_record_decl, + clang::SourceLocation(), + clang::DeclarationNameInfo (decl_name, clang::SourceLocation()), + method_qual_type, + nullptr, // TypeSourceInfo * + SC, + is_inline, + false /*is_constexpr*/, + clang::SourceLocation()); + } + } + + clang::AccessSpecifier access_specifier = ClangASTContext::ConvertAccessTypeToAccessSpecifier (access); + + cxx_method_decl->setAccess (access_specifier); + cxx_method_decl->setVirtualAsWritten (is_virtual); + + if (is_attr_used) + cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*getASTContext())); + + // Populate the method decl with parameter decls + + llvm::SmallVector params; + + for (unsigned param_index = 0; + param_index < num_params; + ++param_index) + { + params.push_back (clang::ParmVarDecl::Create (*getASTContext(), + cxx_method_decl, + clang::SourceLocation(), + clang::SourceLocation(), + nullptr, // anonymous + method_function_prototype->getParamType(param_index), + nullptr, + clang::SC_None, + nullptr)); + } + + cxx_method_decl->setParams (llvm::ArrayRef(params)); + + cxx_record_decl->addDecl (cxx_method_decl); + + // Sometimes the debug info will mention a constructor (default/copy/move), + // destructor, or assignment operator (copy/move) but there won't be any + // version of this in the code. So we check if the function was artificially + // generated and if it is trivial and this lets the compiler/backend know + // that it can inline the IR for these when it needs to and we can avoid a + // "missing function" error when running expressions. + + if (is_artificial) + { + if (cxx_ctor_decl && + ((cxx_ctor_decl->isDefaultConstructor() && cxx_record_decl->hasTrivialDefaultConstructor ()) || + (cxx_ctor_decl->isCopyConstructor() && cxx_record_decl->hasTrivialCopyConstructor ()) || + (cxx_ctor_decl->isMoveConstructor() && cxx_record_decl->hasTrivialMoveConstructor ()) )) + { + cxx_ctor_decl->setDefaulted(); + cxx_ctor_decl->setTrivial(true); + } + else if (cxx_dtor_decl) + { + if (cxx_record_decl->hasTrivialDestructor()) + { + cxx_dtor_decl->setDefaulted(); + cxx_dtor_decl->setTrivial(true); + } + } + else if ((cxx_method_decl->isCopyAssignmentOperator() && cxx_record_decl->hasTrivialCopyAssignment()) || + (cxx_method_decl->isMoveAssignmentOperator() && cxx_record_decl->hasTrivialMoveAssignment())) + { + cxx_method_decl->setDefaulted(); + cxx_method_decl->setTrivial(true); + } + } + +#ifdef LLDB_CONFIGURATION_DEBUG + VerifyDecl(cxx_method_decl); +#endif + + // printf ("decl->isPolymorphic() = %i\n", cxx_record_decl->isPolymorphic()); + // printf ("decl->isAggregate() = %i\n", cxx_record_decl->isAggregate()); + // printf ("decl->isPOD() = %i\n", cxx_record_decl->isPOD()); + // printf ("decl->isEmpty() = %i\n", cxx_record_decl->isEmpty()); + // printf ("decl->isAbstract() = %i\n", cxx_record_decl->isAbstract()); + // printf ("decl->hasTrivialConstructor() = %i\n", cxx_record_decl->hasTrivialConstructor()); + // printf ("decl->hasTrivialCopyConstructor() = %i\n", cxx_record_decl->hasTrivialCopyConstructor()); + // printf ("decl->hasTrivialCopyAssignment() = %i\n", cxx_record_decl->hasTrivialCopyAssignment()); + // printf ("decl->hasTrivialDestructor() = %i\n", cxx_record_decl->hasTrivialDestructor()); + return cxx_method_decl; +} + + +#pragma mark C++ Base Classes + +clang::CXXBaseSpecifier * +ClangASTContext::CreateBaseClassSpecifier (void* type, AccessType access, bool is_virtual, bool base_of_class) +{ + if (type) + return new clang::CXXBaseSpecifier (clang::SourceRange(), + is_virtual, + base_of_class, + ClangASTContext::ConvertAccessTypeToAccessSpecifier (access), + getASTContext()->getTrivialTypeSourceInfo (GetQualType(type)), + clang::SourceLocation()); + return nullptr; +} + +void +ClangASTContext::DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, unsigned num_base_classes) +{ + for (unsigned i=0; isetBases(base_classes, num_base_classes); + return true; + } + } + return false; +} + +bool +ClangASTContext::SetObjCSuperClass (const ClangASTType& type, const ClangASTType &superclass_clang_type) +{ + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return false; + clang::ASTContext* clang_ast = ast->getASTContext(); + + if (type && superclass_clang_type.IsValid() && superclass_clang_type.GetTypeSystem() == type.GetTypeSystem()) + { + clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (type); + clang::ObjCInterfaceDecl *super_interface_decl = GetAsObjCInterfaceDecl (superclass_clang_type); + if (class_interface_decl && super_interface_decl) + { + class_interface_decl->setSuperClass(clang_ast->getTrivialTypeSourceInfo(clang_ast->getObjCInterfaceType(super_interface_decl))); + return true; + } + } + return false; +} + +bool +ClangASTContext::AddObjCClassProperty (const ClangASTType& type, + const char *property_name, + const ClangASTType &property_clang_type, + clang::ObjCIvarDecl *ivar_decl, + const char *property_setter_name, + const char *property_getter_name, + uint32_t property_attributes, + ClangASTMetadata *metadata) +{ + if (!type || !property_clang_type.IsValid() || property_name == nullptr || property_name[0] == '\0') + return false; + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return false; + clang::ASTContext* clang_ast = ast->getASTContext(); + + clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (type); + + if (class_interface_decl) + { + ClangASTType property_clang_type_to_access; + + if (property_clang_type.IsValid()) + property_clang_type_to_access = property_clang_type; + else if (ivar_decl) + property_clang_type_to_access = ClangASTType (clang_ast, ivar_decl->getType()); + + if (class_interface_decl && property_clang_type_to_access.IsValid()) + { + clang::TypeSourceInfo *prop_type_source; + if (ivar_decl) + prop_type_source = clang_ast->getTrivialTypeSourceInfo (ivar_decl->getType()); + else + prop_type_source = clang_ast->getTrivialTypeSourceInfo (GetQualType(property_clang_type)); + + clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create (*clang_ast, + class_interface_decl, + clang::SourceLocation(), // Source Location + &clang_ast->Idents.get(property_name), + clang::SourceLocation(), //Source Location for AT + clang::SourceLocation(), //Source location for ( + ivar_decl ? ivar_decl->getType() : ClangASTContext::GetQualType(property_clang_type), + prop_type_source); + + if (property_decl) + { + if (metadata) + ClangASTContext::SetMetadata(clang_ast, property_decl, *metadata); + + class_interface_decl->addDecl (property_decl); + + clang::Selector setter_sel, getter_sel; + + if (property_setter_name != nullptr) + { + std::string property_setter_no_colon(property_setter_name, strlen(property_setter_name) - 1); + clang::IdentifierInfo *setter_ident = &clang_ast->Idents.get(property_setter_no_colon.c_str()); + setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident); + } + else if (!(property_attributes & DW_APPLE_PROPERTY_readonly)) + { + std::string setter_sel_string("set"); + setter_sel_string.push_back(::toupper(property_name[0])); + setter_sel_string.append(&property_name[1]); + clang::IdentifierInfo *setter_ident = &clang_ast->Idents.get(setter_sel_string.c_str()); + setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident); + } + property_decl->setSetterName(setter_sel); + property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_setter); + + if (property_getter_name != nullptr) + { + clang::IdentifierInfo *getter_ident = &clang_ast->Idents.get(property_getter_name); + getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident); + } + else + { + clang::IdentifierInfo *getter_ident = &clang_ast->Idents.get(property_name); + getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident); + } + property_decl->setGetterName(getter_sel); + property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_getter); + + if (ivar_decl) + property_decl->setPropertyIvarDecl (ivar_decl); + + if (property_attributes & DW_APPLE_PROPERTY_readonly) + property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readonly); + if (property_attributes & DW_APPLE_PROPERTY_readwrite) + property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readwrite); + if (property_attributes & DW_APPLE_PROPERTY_assign) + property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_assign); + if (property_attributes & DW_APPLE_PROPERTY_retain) + property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_retain); + if (property_attributes & DW_APPLE_PROPERTY_copy) + property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_copy); + if (property_attributes & DW_APPLE_PROPERTY_nonatomic) + property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_nonatomic); + + if (!getter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(getter_sel)) + { + const bool isInstance = true; + const bool isVariadic = false; + const bool isSynthesized = false; + const bool isImplicitlyDeclared = true; + const bool isDefined = false; + const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None; + const bool HasRelatedResultType = false; + + clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create (*clang_ast, + clang::SourceLocation(), + clang::SourceLocation(), + getter_sel, + GetQualType(property_clang_type_to_access), + nullptr, + class_interface_decl, + isInstance, + isVariadic, + isSynthesized, + isImplicitlyDeclared, + isDefined, + impControl, + HasRelatedResultType); + + if (getter && metadata) + ClangASTContext::SetMetadata(clang_ast, getter, *metadata); + + if (getter) + { + getter->setMethodParams(*clang_ast, llvm::ArrayRef(), llvm::ArrayRef()); + + class_interface_decl->addDecl(getter); + } + } + + if (!setter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(setter_sel)) + { + clang::QualType result_type = clang_ast->VoidTy; + + const bool isInstance = true; + const bool isVariadic = false; + const bool isSynthesized = false; + const bool isImplicitlyDeclared = true; + const bool isDefined = false; + const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None; + const bool HasRelatedResultType = false; + + clang::ObjCMethodDecl *setter = clang::ObjCMethodDecl::Create (*clang_ast, + clang::SourceLocation(), + clang::SourceLocation(), + setter_sel, + result_type, + nullptr, + class_interface_decl, + isInstance, + isVariadic, + isSynthesized, + isImplicitlyDeclared, + isDefined, + impControl, + HasRelatedResultType); + + if (setter && metadata) + ClangASTContext::SetMetadata(clang_ast, setter, *metadata); + + llvm::SmallVector params; + + params.push_back (clang::ParmVarDecl::Create (*clang_ast, + setter, + clang::SourceLocation(), + clang::SourceLocation(), + nullptr, // anonymous + GetQualType(property_clang_type_to_access), + nullptr, + clang::SC_Auto, + nullptr)); + + if (setter) + { + setter->setMethodParams(*clang_ast, llvm::ArrayRef(params), llvm::ArrayRef()); + + class_interface_decl->addDecl(setter); + } + } + + return true; + } + } + } + return false; +} + +bool +ClangASTContext::IsObjCClassTypeAndHasIVars (const ClangASTType& type, bool check_superclass) +{ + clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (type); + if (class_interface_decl) + return ObjCDeclHasIVars (class_interface_decl, check_superclass); + return false; +} + + +clang::ObjCMethodDecl * +ClangASTContext::AddMethodToObjCObjectType (const ClangASTType& type, + const char *name, // the full symbol name as seen in the symbol table (void* type, "-[NString stringWithCString:]") + const ClangASTType &method_clang_type, + lldb::AccessType access, + bool is_artificial) +{ + if (!type || !method_clang_type.IsValid()) + return nullptr; + + clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type); + + if (class_interface_decl == nullptr) + return nullptr; + clang::ASTContext* ast = type.GetTypeSystem()->AsClangASTContext()->getASTContext(); + + const char *selector_start = ::strchr (name, ' '); + if (selector_start == nullptr) + return nullptr; + + selector_start++; + llvm::SmallVector selector_idents; + + size_t len = 0; + const char *start; + //printf ("name = '%s'\n", name); + + unsigned num_selectors_with_args = 0; + for (start = selector_start; + start && *start != '\0' && *start != ']'; + start += len) + { + len = ::strcspn(start, ":]"); + bool has_arg = (start[len] == ':'); + if (has_arg) + ++num_selectors_with_args; + selector_idents.push_back (&ast->Idents.get (llvm::StringRef (start, len))); + if (has_arg) + len += 1; + } + + + if (selector_idents.size() == 0) + return nullptr; + + clang::Selector method_selector = ast->Selectors.getSelector (num_selectors_with_args ? selector_idents.size() : 0, + selector_idents.data()); + + clang::QualType method_qual_type (GetQualType(method_clang_type)); + + // Populate the method decl with parameter decls + const clang::Type *method_type(method_qual_type.getTypePtr()); + + if (method_type == nullptr) + return nullptr; + + const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast(method_type)); + + if (!method_function_prototype) + return nullptr; + + + bool is_variadic = false; + bool is_synthesized = false; + bool is_defined = false; + clang::ObjCMethodDecl::ImplementationControl imp_control = clang::ObjCMethodDecl::None; + + const unsigned num_args = method_function_prototype->getNumParams(); + + if (num_args != num_selectors_with_args) + return nullptr; // some debug information is corrupt. We are not going to deal with it. + + clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create (*ast, + clang::SourceLocation(), // beginLoc, + clang::SourceLocation(), // endLoc, + method_selector, + method_function_prototype->getReturnType(), + nullptr, // TypeSourceInfo *ResultTInfo, + ClangASTContext::GetASTContext(ast)->GetDeclContextForType(GetQualType(type)), + name[0] == '-', + is_variadic, + is_synthesized, + true, // is_implicitly_declared; we force this to true because we don't have source locations + is_defined, + imp_control, + false /*has_related_result_type*/); + + + if (objc_method_decl == nullptr) + return nullptr; + + if (num_args > 0) + { + llvm::SmallVector params; + + for (unsigned param_index = 0; param_index < num_args; ++param_index) + { + params.push_back (clang::ParmVarDecl::Create (*ast, + objc_method_decl, + clang::SourceLocation(), + clang::SourceLocation(), + nullptr, // anonymous + method_function_prototype->getParamType(param_index), + nullptr, + clang::SC_Auto, + nullptr)); + } + + objc_method_decl->setMethodParams(*ast, llvm::ArrayRef(params), llvm::ArrayRef()); + } + + class_interface_decl->addDecl (objc_method_decl); + +#ifdef LLDB_CONFIGURATION_DEBUG + VerifyDecl(objc_method_decl); +#endif + + return objc_method_decl; +} + +bool +ClangASTContext::SetHasExternalStorage (void* type, bool has_extern) +{ + if (!type) + return false; + + clang::QualType qual_type (GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + { + clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + cxx_record_decl->setHasExternalLexicalStorage (has_extern); + cxx_record_decl->setHasExternalVisibleStorage (has_extern); + return true; + } + } + break; + + case clang::Type::Enum: + { + clang::EnumDecl *enum_decl = llvm::cast(qual_type)->getDecl(); + if (enum_decl) + { + enum_decl->setHasExternalLexicalStorage (has_extern); + enum_decl->setHasExternalVisibleStorage (has_extern); + return true; + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + assert (objc_class_type); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + + if (class_interface_decl) + { + class_interface_decl->setHasExternalLexicalStorage (has_extern); + class_interface_decl->setHasExternalVisibleStorage (has_extern); + return true; + } + } + } + break; + + case clang::Type::Typedef: + return SetHasExternalStorage(llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), has_extern); + + case clang::Type::Elaborated: + return SetHasExternalStorage (llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), has_extern); + + case clang::Type::Paren: + return SetHasExternalStorage (llvm::cast(qual_type)->desugar().getAsOpaquePtr(), has_extern); + + default: + break; + } + return false; +} + + +#pragma mark TagDecl + +bool +ClangASTContext::StartTagDeclarationDefinition (const ClangASTType &type) +{ + if (type) + { + + clang::QualType qual_type (GetQualType(type)); + const clang::Type *t = qual_type.getTypePtr(); + if (t) + { + const clang::TagType *tag_type = llvm::dyn_cast(t); + if (tag_type) + { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) + { + tag_decl->startDefinition(); + return true; + } + } + + const clang::ObjCObjectType *object_type = llvm::dyn_cast(t); + if (object_type) + { + clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface(); + if (interface_decl) + { + interface_decl->startDefinition(); + return true; + } + } + } + } + return false; +} + +bool +ClangASTContext::CompleteTagDeclarationDefinition (const ClangASTType& type) +{ + if (type) + { + clang::QualType qual_type (GetQualType(type)); + if (qual_type.isNull()) + return false; + clang::ASTContext* ast = type.GetTypeSystem()->AsClangASTContext()->getASTContext(); + + clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + + if (cxx_record_decl) + { + cxx_record_decl->completeDefinition(); + + return true; + } + + const clang::EnumType *enutype = llvm::dyn_cast(qual_type.getTypePtr()); + + if (enutype) + { + clang::EnumDecl *enum_decl = enutype->getDecl(); + + if (enum_decl) + { + /// TODO This really needs to be fixed. + + unsigned NumPositiveBits = 1; + unsigned NumNegativeBits = 0; + + clang::QualType promotion_qual_type; + // If the enum integer type is less than an integer in bit width, + // then we must promote it to an integer size. + if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy)) + { + if (enum_decl->getIntegerType()->isSignedIntegerType()) + promotion_qual_type = ast->IntTy; + else + promotion_qual_type = ast->UnsignedIntTy; + } + else + promotion_qual_type = enum_decl->getIntegerType(); + + enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits); + return true; + } + } + } + return false; +} + + + + + + + +bool +ClangASTContext::AddEnumerationValueToEnumerationType (void* type, const ClangASTType &enumerator_clang_type, + const Declaration &decl, + const char *name, + int64_t enum_value, + uint32_t enum_value_bit_size) +{ + if (type && enumerator_clang_type.IsValid() && name && name[0]) + { + clang::QualType enum_qual_type (GetCanonicalQualType(type)); + + bool is_signed = false; + enumerator_clang_type.IsIntegerType (is_signed); + const clang::Type *clang_type = enum_qual_type.getTypePtr(); + if (clang_type) + { + const clang::EnumType *enutype = llvm::dyn_cast(clang_type); + + if (enutype) + { + llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed); + enum_llvm_apsint = enum_value; + clang::EnumConstantDecl *enumerator_decl = + clang::EnumConstantDecl::Create (*getASTContext(), + enutype->getDecl(), + clang::SourceLocation(), + name ? &getASTContext()->Idents.get(name) : nullptr, // Identifier + GetQualType(enumerator_clang_type), + nullptr, + enum_llvm_apsint); + + if (enumerator_decl) + { + enutype->getDecl()->addDecl(enumerator_decl); + +#ifdef LLDB_CONFIGURATION_DEBUG + VerifyDecl(enumerator_decl); +#endif + + return true; + } + } + } + } + return false; +} + + +ClangASTType +ClangASTContext::GetEnumerationIntegerType (void* type) +{ + clang::QualType enum_qual_type (GetCanonicalQualType(type)); + const clang::Type *clang_type = enum_qual_type.getTypePtr(); + if (clang_type) + { + const clang::EnumType *enutype = llvm::dyn_cast(clang_type); + if (enutype) + { + clang::EnumDecl *enum_decl = enutype->getDecl(); + if (enum_decl) + return ClangASTType (getASTContext(), enum_decl->getIntegerType()); + } + } + return ClangASTType(); +} + +ClangASTType +ClangASTContext::CreateMemberPointerType (const ClangASTType& type, const ClangASTType &pointee_type) +{ + if (type && pointee_type.IsValid() && type.GetTypeSystem() == pointee_type.GetTypeSystem()) + { + ClangASTContext* ast = type.GetTypeSystem()->AsClangASTContext(); + if (!ast) + return ClangASTType(); + return ClangASTType (ast->getASTContext(), + ast->getASTContext()->getMemberPointerType (GetQualType(pointee_type), + GetQualType(type).getTypePtr())); + } + return ClangASTType(); +} + + +size_t +ClangASTContext::ConvertStringToFloatValue (void* type, const char *s, uint8_t *dst, size_t dst_size) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + uint32_t count = 0; + bool is_complex = false; + if (IsFloatingPointType (type, count, is_complex)) + { + // TODO: handle complex and vector types + if (count != 1) + return false; + + llvm::StringRef s_sref(s); + llvm::APFloat ap_float(getASTContext()->getFloatTypeSemantics(qual_type), s_sref); + + const uint64_t bit_size = getASTContext()->getTypeSize (qual_type); + const uint64_t byte_size = bit_size / 8; + if (dst_size >= byte_size) + { + if (bit_size == sizeof(float)*8) + { + float float32 = ap_float.convertToFloat(); + ::memcpy (dst, &float32, byte_size); + return byte_size; + } + else if (bit_size >= 64) + { + llvm::APInt ap_int(ap_float.bitcastToAPInt()); + ::memcpy (dst, ap_int.getRawData(), byte_size); + return byte_size; + } + } + } + } + return 0; +} + + + +//---------------------------------------------------------------------- +// Dumping types +//---------------------------------------------------------------------- +#define DEPTH_INCREMENT 2 + +void +ClangASTContext::DumpValue (void* type, ExecutionContext *exe_ctx, + Stream *s, + lldb::Format format, + const lldb_private::DataExtractor &data, + lldb::offset_t data_byte_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool show_types, + bool show_summary, + bool verbose, + uint32_t depth) +{ + if (!type) + return; + + clang::QualType qual_type(GetQualType(type)); + switch (qual_type->getTypeClass()) + { + case clang::Type::Record: + if (GetCompleteType(type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + uint32_t field_bit_offset = 0; + uint32_t field_byte_offset = 0; + const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(record_decl); + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + if (cxx_record_decl) + { + // We might have base classes to print out first + clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; + ++base_class) + { + const clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); + + // Skip empty base classes + if (verbose == false && ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + + if (base_class->isVirtual()) + field_bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; + else + field_bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; + field_byte_offset = field_bit_offset / 8; + assert (field_bit_offset % 8 == 0); + if (child_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + clang::QualType base_class_qual_type = base_class->getType(); + std::string base_class_type_name(base_class_qual_type.getAsString()); + + // Indent and print the base class type name + s->Printf("\n%*s%s ", depth + DEPTH_INCREMENT, "", base_class_type_name.c_str()); + + clang::TypeInfo base_class_type_info = getASTContext()->getTypeInfo(base_class_qual_type); + + // Dump the value of the member + ClangASTType base_clang_type(getASTContext(), base_class_qual_type); + base_clang_type.DumpValue (exe_ctx, + s, // Stream to dump to + base_clang_type.GetFormat(), // The format with which to display the member + data, // Data buffer containing all bytes for this type + data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from + base_class_type_info.Width / 8, // Size of this type in bytes + 0, // Bitfield bit size + 0, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the current type + verbose, // Verbose output? + depth + DEPTH_INCREMENT); // Scope depth for any types that have children + + ++child_idx; + } + } + uint32_t field_idx = 0; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx) + { + // Print the starting squiggly bracket (if this is the + // first member) or comma (for member 2 and beyond) for + // the struct/union/class member. + if (child_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + // Indent + s->Printf("\n%*s", depth + DEPTH_INCREMENT, ""); + + clang::QualType field_type = field->getType(); + // Print the member type if requested + // Figure out the type byte size (field_type_info.first) and + // alignment (field_type_info.second) from the AST context. + clang::TypeInfo field_type_info = getASTContext()->getTypeInfo(field_type); + assert(field_idx < record_layout.getFieldCount()); + // Figure out the field offset within the current struct/union/class type + field_bit_offset = record_layout.getFieldOffset (field_idx); + field_byte_offset = field_bit_offset / 8; + uint32_t field_bitfield_bit_size = 0; + uint32_t field_bitfield_bit_offset = 0; + if (ClangASTContext::FieldIsBitfield (getASTContext(), *field, field_bitfield_bit_size)) + field_bitfield_bit_offset = field_bit_offset % 8; + + if (show_types) + { + std::string field_type_name(field_type.getAsString()); + if (field_bitfield_bit_size > 0) + s->Printf("(%s:%u) ", field_type_name.c_str(), field_bitfield_bit_size); + else + s->Printf("(%s) ", field_type_name.c_str()); + } + // Print the member name and equal sign + s->Printf("%s = ", field->getNameAsString().c_str()); + + + // Dump the value of the member + ClangASTType field_clang_type (getASTContext(), field_type); + field_clang_type.DumpValue (exe_ctx, + s, // Stream to dump to + field_clang_type.GetFormat(), // The format with which to display the member + data, // Data buffer containing all bytes for this type + data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from + field_type_info.Width / 8, // Size of this type in bytes + field_bitfield_bit_size, // Bitfield bit size + field_bitfield_bit_offset, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the current type + verbose, // Verbose output? + depth + DEPTH_INCREMENT); // Scope depth for any types that have children + } + + // Indent the trailing squiggly bracket + if (child_idx > 0) + s->Printf("\n%*s}", depth, ""); + } + return; + + case clang::Type::Enum: + if (GetCompleteType(type)) + { + const clang::EnumType *enutype = llvm::cast(qual_type.getTypePtr()); + const clang::EnumDecl *enum_decl = enutype->getDecl(); + assert(enum_decl); + clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; + lldb::offset_t offset = data_byte_offset; + const int64_t enum_value = data.GetMaxU64Bitfield(&offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset); + for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) + { + if (enum_pos->getInitVal() == enum_value) + { + s->Printf("%s", enum_pos->getNameAsString().c_str()); + return; + } + } + // If we have gotten here we didn't get find the enumerator in the + // enum decl, so just print the integer. + s->Printf("%" PRIi64, enum_value); + } + return; + + case clang::Type::ConstantArray: + { + const clang::ConstantArrayType *array = llvm::cast(qual_type.getTypePtr()); + bool is_array_of_characters = false; + clang::QualType element_qual_type = array->getElementType(); + + const clang::Type *canonical_type = element_qual_type->getCanonicalTypeInternal().getTypePtr(); + if (canonical_type) + is_array_of_characters = canonical_type->isCharType(); + + const uint64_t element_count = array->getSize().getLimitedValue(); + + clang::TypeInfo field_type_info = getASTContext()->getTypeInfo(element_qual_type); + + uint32_t element_idx = 0; + uint32_t element_offset = 0; + uint64_t element_byte_size = field_type_info.Width / 8; + uint32_t element_stride = element_byte_size; + + if (is_array_of_characters) + { + s->PutChar('"'); + data.Dump(s, data_byte_offset, lldb::eFormatChar, element_byte_size, element_count, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('"'); + return; + } + else + { + ClangASTType element_clang_type(getASTContext(), element_qual_type); + lldb::Format element_format = element_clang_type.GetFormat(); + + for (element_idx = 0; element_idx < element_count; ++element_idx) + { + // Print the starting squiggly bracket (if this is the + // first member) or comman (for member 2 and beyong) for + // the struct/union/class member. + if (element_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + // Indent and print the index + s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx); + + // Figure out the field offset within the current struct/union/class type + element_offset = element_idx * element_stride; + + // Dump the value of the member + element_clang_type.DumpValue (exe_ctx, + s, // Stream to dump to + element_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset + element_offset,// Offset into "data" where to grab value from + element_byte_size, // Size of this type in bytes + 0, // Bitfield bit size + 0, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the current type + verbose, // Verbose output? + depth + DEPTH_INCREMENT); // Scope depth for any types that have children + } + + // Indent the trailing squiggly bracket + if (element_idx > 0) + s->Printf("\n%*s}", depth, ""); + } + } + return; + + case clang::Type::Typedef: + { + clang::QualType typedef_qual_type = llvm::cast(qual_type)->getDecl()->getUnderlyingType(); + + ClangASTType typedef_clang_type (getASTContext(), typedef_qual_type); + lldb::Format typedef_format = typedef_clang_type.GetFormat(); + clang::TypeInfo typedef_type_info = getASTContext()->getTypeInfo(typedef_qual_type); + uint64_t typedef_byte_size = typedef_type_info.Width / 8; + + return typedef_clang_type.DumpValue (exe_ctx, + s, // Stream to dump to + typedef_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset, // Offset into "data" where to grab value from + typedef_byte_size, // Size of this type in bytes + bitfield_bit_size, // Bitfield bit size + bitfield_bit_offset,// Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the current type + verbose, // Verbose output? + depth); // Scope depth for any types that have children + } + break; + + case clang::Type::Elaborated: + { + clang::QualType elaborated_qual_type = llvm::cast(qual_type)->getNamedType(); + ClangASTType elaborated_clang_type (getASTContext(), elaborated_qual_type); + lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); + clang::TypeInfo elaborated_type_info = getASTContext()->getTypeInfo(elaborated_qual_type); + uint64_t elaborated_byte_size = elaborated_type_info.Width / 8; + + return elaborated_clang_type.DumpValue (exe_ctx, + s, // Stream to dump to + elaborated_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset, // Offset into "data" where to grab value from + elaborated_byte_size, // Size of this type in bytes + bitfield_bit_size, // Bitfield bit size + bitfield_bit_offset,// Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the current type + verbose, // Verbose output? + depth); // Scope depth for any types that have children + } + break; + + case clang::Type::Paren: + { + clang::QualType desugar_qual_type = llvm::cast(qual_type)->desugar(); + ClangASTType desugar_clang_type (getASTContext(), desugar_qual_type); + + lldb::Format desugar_format = desugar_clang_type.GetFormat(); + clang::TypeInfo desugar_type_info = getASTContext()->getTypeInfo(desugar_qual_type); + uint64_t desugar_byte_size = desugar_type_info.Width / 8; + + return desugar_clang_type.DumpValue (exe_ctx, + s, // Stream to dump to + desugar_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset, // Offset into "data" where to grab value from + desugar_byte_size, // Size of this type in bytes + bitfield_bit_size, // Bitfield bit size + bitfield_bit_offset,// Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the current type + verbose, // Verbose output? + depth); // Scope depth for any types that have children + } + break; + + default: + // We are down to a scalar type that we just need to display. + data.Dump(s, + data_byte_offset, + format, + data_byte_size, + 1, + UINT32_MAX, + LLDB_INVALID_ADDRESS, + bitfield_bit_size, + bitfield_bit_offset); + + if (show_summary) + DumpSummary (type, exe_ctx, s, data, data_byte_offset, data_byte_size); + break; + } +} + + + + +bool +ClangASTContext::DumpTypeValue (void* type, Stream *s, + lldb::Format format, + const lldb_private::DataExtractor &data, + lldb::offset_t byte_offset, + size_t byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope) +{ + if (!type) + return false; + if (IsAggregateType(type)) + { + return false; + } + else + { + clang::QualType qual_type(GetQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Typedef: + { + clang::QualType typedef_qual_type = llvm::cast(qual_type)->getDecl()->getUnderlyingType(); + ClangASTType typedef_clang_type (getASTContext(), typedef_qual_type); + if (format == eFormatDefault) + format = typedef_clang_type.GetFormat(); + clang::TypeInfo typedef_type_info = getASTContext()->getTypeInfo(typedef_qual_type); + uint64_t typedef_byte_size = typedef_type_info.Width / 8; + + return typedef_clang_type.DumpTypeValue (s, + format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + byte_offset, // Offset into "data" where to grab value from + typedef_byte_size, // Size of this type in bytes + bitfield_bit_size, // Size in bits of a bitfield value, if zero don't treat as a bitfield + bitfield_bit_offset, // Offset in bits of a bitfield value if bitfield_bit_size != 0 + exe_scope); + } + break; + + case clang::Type::Enum: + // If our format is enum or default, show the enumeration value as + // its enumeration string value, else just display it as requested. + if ((format == eFormatEnum || format == eFormatDefault) && GetCompleteType(type)) + { + const clang::EnumType *enutype = llvm::cast(qual_type.getTypePtr()); + const clang::EnumDecl *enum_decl = enutype->getDecl(); + assert(enum_decl); + clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; + const bool is_signed = qual_type->isSignedIntegerOrEnumerationType(); + lldb::offset_t offset = byte_offset; + if (is_signed) + { + const int64_t enum_svalue = data.GetMaxS64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset); + for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) + { + if (enum_pos->getInitVal().getSExtValue() == enum_svalue) + { + s->PutCString (enum_pos->getNameAsString().c_str()); + return true; + } + } + // If we have gotten here we didn't get find the enumerator in the + // enum decl, so just print the integer. + s->Printf("%" PRIi64, enum_svalue); + } + else + { + const uint64_t enum_uvalue = data.GetMaxU64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset); + for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) + { + if (enum_pos->getInitVal().getZExtValue() == enum_uvalue) + { + s->PutCString (enum_pos->getNameAsString().c_str()); + return true; + } + } + // If we have gotten here we didn't get find the enumerator in the + // enum decl, so just print the integer. + s->Printf("%" PRIu64, enum_uvalue); + } + return true; + } + // format was not enum, just fall through and dump the value as requested.... + + default: + // We are down to a scalar type that we just need to display. + { + uint32_t item_count = 1; + // A few formats, we might need to modify our size and count for depending + // on how we are trying to display the value... + switch (format) + { + default: + case eFormatBoolean: + case eFormatBinary: + case eFormatComplex: + case eFormatCString: // NULL terminated C strings + case eFormatDecimal: + case eFormatEnum: + case eFormatHex: + case eFormatHexUppercase: + case eFormatFloat: + case eFormatOctal: + case eFormatOSType: + case eFormatUnsigned: + case eFormatPointer: + case eFormatVectorOfChar: + case eFormatVectorOfSInt8: + case eFormatVectorOfUInt8: + case eFormatVectorOfSInt16: + case eFormatVectorOfUInt16: + case eFormatVectorOfSInt32: + case eFormatVectorOfUInt32: + case eFormatVectorOfSInt64: + case eFormatVectorOfUInt64: + case eFormatVectorOfFloat32: + case eFormatVectorOfFloat64: + case eFormatVectorOfUInt128: + break; + + case eFormatChar: + case eFormatCharPrintable: + case eFormatCharArray: + case eFormatBytes: + case eFormatBytesWithASCII: + item_count = byte_size; + byte_size = 1; + break; + + case eFormatUnicode16: + item_count = byte_size / 2; + byte_size = 2; + break; + + case eFormatUnicode32: + item_count = byte_size / 4; + byte_size = 4; + break; + } + return data.Dump (s, + byte_offset, + format, + byte_size, + item_count, + UINT32_MAX, + LLDB_INVALID_ADDRESS, + bitfield_bit_size, + bitfield_bit_offset, + exe_scope); + } + break; + } + } + return 0; +} + + + +void +ClangASTContext::DumpSummary (void* type, ExecutionContext *exe_ctx, + Stream *s, + const lldb_private::DataExtractor &data, + lldb::offset_t data_byte_offset, + size_t data_byte_size) +{ + uint32_t length = 0; + if (IsCStringType (type, length)) + { + if (exe_ctx) + { + Process *process = exe_ctx->GetProcessPtr(); + if (process) + { + lldb::offset_t offset = data_byte_offset; + lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size); + std::vector buf; + if (length > 0) + buf.resize (length); + else + buf.resize (256); + + lldb_private::DataExtractor cstr_data(&buf.front(), buf.size(), process->GetByteOrder(), 4); + buf.back() = '\0'; + size_t bytes_read; + size_t total_cstr_len = 0; + Error error; + while ((bytes_read = process->ReadMemory (pointer_address, &buf.front(), buf.size(), error)) > 0) + { + const size_t len = strlen((const char *)&buf.front()); + if (len == 0) + break; + if (total_cstr_len == 0) + s->PutCString (" \""); + cstr_data.Dump(s, 0, lldb::eFormatChar, 1, len, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); + total_cstr_len += len; + if (len < buf.size()) + break; + pointer_address += total_cstr_len; + } + if (total_cstr_len > 0) + s->PutChar ('"'); + } + } + } +} + +void +ClangASTContext::DumpTypeDescription (void* type) +{ + StreamFile s (stdout, false); + DumpTypeDescription (&s); + ClangASTMetadata *metadata = ClangASTContext::GetMetadata (getASTContext(), type); + if (metadata) + { + metadata->Dump (&s); + } +} + +void +ClangASTContext::DumpTypeDescription (void* type, Stream *s) +{ + if (type) + { + clang::QualType qual_type(GetQualType(type)); + + llvm::SmallVector buf; + llvm::raw_svector_ostream llvm_ostrm (buf); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + GetCompleteType(type); + + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + assert (objc_class_type); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + if (class_interface_decl) + { + clang::PrintingPolicy policy = getASTContext()->getPrintingPolicy(); + class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel()); + } + } + } + break; + + case clang::Type::Typedef: + { + const clang::TypedefType *typedef_type = qual_type->getAs(); + if (typedef_type) + { + const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); + std::string clang_typedef_name (typedef_decl->getQualifiedNameAsString()); + if (!clang_typedef_name.empty()) + { + s->PutCString ("typedef "); + s->PutCString (clang_typedef_name.c_str()); + } + } + } + break; + + case clang::Type::Elaborated: + ClangASTType (getASTContext(), llvm::cast(qual_type)->getNamedType()).DumpTypeDescription(s); + return; + + case clang::Type::Paren: + ClangASTType (getASTContext(), llvm::cast(qual_type)->desugar()).DumpTypeDescription(s); + return; + + case clang::Type::Record: + { + GetCompleteType(type); + + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + + if (cxx_record_decl) + cxx_record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(), s->GetIndentLevel()); + else + record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(), s->GetIndentLevel()); + } + break; + + default: + { + const clang::TagType *tag_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (tag_type) + { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) + tag_decl->print(llvm_ostrm, 0); + } + else + { + std::string clang_type_name(qual_type.getAsString()); + if (!clang_type_name.empty()) + s->PutCString (clang_type_name.c_str()); + } + } + } + + llvm_ostrm.flush(); + if (buf.size() > 0) + { + s->Write (buf.data(), buf.size()); + } + } +} Index: source/Symbol/ClangASTType.cpp =================================================================== --- source/Symbol/ClangASTType.cpp +++ source/Symbol/ClangASTType.cpp @@ -55,130 +55,17 @@ using namespace lldb; using namespace lldb_private; -static bool -GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool allow_completion = true) +ClangASTType::ClangASTType (TypeSystem *type_system, + void* type) : +m_type (type), +m_type_system (type_system) { - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ConstantArray: - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - { - const clang::ArrayType *array_type = llvm::dyn_cast(qual_type.getTypePtr()); - - if (array_type) - return GetCompleteQualType (ast, array_type->getElementType(), allow_completion); - } - break; - - case clang::Type::Record: - case clang::Type::Enum: - { - const clang::TagType *tag_type = llvm::dyn_cast(qual_type.getTypePtr()); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - { - if (tag_decl->isCompleteDefinition()) - return true; - - if (!allow_completion) - return false; - - if (tag_decl->hasExternalLexicalStorage()) - { - if (ast) - { - clang::ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) - { - external_ast_source->CompleteType(tag_decl); - return !tag_type->isIncompleteType(); - } - } - } - return false; - } - } - - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - // We currently can't complete objective C types through the newly added ASTContext - // because it only supports TagDecl objects right now... - if (class_interface_decl) - { - if (class_interface_decl->getDefinition()) - return true; - - if (!allow_completion) - return false; - - if (class_interface_decl->hasExternalLexicalStorage()) - { - if (ast) - { - clang::ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) - { - external_ast_source->CompleteType (class_interface_decl); - return !objc_class_type->isIncompleteType(); - } - } - } - return false; - } - } - } - break; - - case clang::Type::Typedef: - return GetCompleteQualType (ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType(), allow_completion); - - case clang::Type::Elaborated: - return GetCompleteQualType (ast, llvm::cast(qual_type)->getNamedType(), allow_completion); - - case clang::Type::Paren: - return GetCompleteQualType (ast, llvm::cast(qual_type)->desugar(), allow_completion); - - default: - break; - } - - return true; } -static clang::ObjCIvarDecl::AccessControl -ConvertAccessTypeToObjCIvarAccessControl (AccessType access) -{ - switch (access) - { - case eAccessNone: return clang::ObjCIvarDecl::None; - case eAccessPublic: return clang::ObjCIvarDecl::Public; - case eAccessPrivate: return clang::ObjCIvarDecl::Private; - case eAccessProtected: return clang::ObjCIvarDecl::Protected; - case eAccessPackage: return clang::ObjCIvarDecl::Package; - } - return clang::ObjCIvarDecl::None; -} - -//---------------------------------------------------------------------- -// Tests -//---------------------------------------------------------------------- - ClangASTType::ClangASTType (clang::ASTContext *ast, clang::QualType qual_type) : m_type (qual_type.getAsOpaquePtr()), - m_ast (ast) +m_type_system (ClangASTContext::GetASTContext(ast)) { } @@ -193,33 +80,8 @@ bool ClangASTType::IsAggregateType () const { - if (!IsValid()) - return false; - - clang::QualType qual_type (GetCanonicalQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - case clang::Type::ConstantArray: - case clang::Type::ExtVector: - case clang::Type::Vector: - case clang::Type::Record: - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - return true; - case clang::Type::Elaborated: - return ClangASTType(m_ast, llvm::cast(qual_type)->getNamedType()).IsAggregateType(); - case clang::Type::Typedef: - return ClangASTType(m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).IsAggregateType(); - case clang::Type::Paren: - return ClangASTType(m_ast, llvm::cast(qual_type)->desugar()).IsAggregateType(); - default: - break; - } - // The clang type does have a value + if (IsValid()) + return m_type_system->IsAggregateType(m_type); return false; } @@ -229,59 +91,8 @@ bool *is_incomplete) const { if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - - case clang::Type::ConstantArray: - if (element_type_ptr) - element_type_ptr->SetClangType (m_ast, llvm::cast(qual_type)->getElementType()); - if (size) - *size = llvm::cast(qual_type)->getSize().getLimitedValue(ULLONG_MAX); - return true; - - case clang::Type::IncompleteArray: - if (element_type_ptr) - element_type_ptr->SetClangType (m_ast, llvm::cast(qual_type)->getElementType()); - if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = true; - return true; - - case clang::Type::VariableArray: - if (element_type_ptr) - element_type_ptr->SetClangType (m_ast, llvm::cast(qual_type)->getElementType()); - if (size) - *size = 0; - return true; - - case clang::Type::DependentSizedArray: - if (element_type_ptr) - element_type_ptr->SetClangType (m_ast, llvm::cast(qual_type)->getElementType()); - if (size) - *size = 0; - return true; - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).IsArrayType (element_type_ptr, - size, - is_incomplete); - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).IsArrayType (element_type_ptr, - size, - is_incomplete); - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).IsArrayType (element_type_ptr, - size, - is_incomplete); - } - } + return m_type_system->IsArrayType(m_type, element_type_ptr, size, is_incomplete); + if (element_type_ptr) element_type_ptr->Clear(); if (size) @@ -296,113 +107,48 @@ uint64_t *size) const { if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Vector: - { - const clang::VectorType *vector_type = qual_type->getAs(); - if (vector_type) - { - if (size) - *size = vector_type->getNumElements(); - if (element_type) - *element_type = ClangASTType(m_ast, vector_type->getElementType().getAsOpaquePtr()); - } - return true; - } - break; - case clang::Type::ExtVector: - { - const clang::ExtVectorType *ext_vector_type = qual_type->getAs(); - if (ext_vector_type) - { - if (size) - *size = ext_vector_type->getNumElements(); - if (element_type) - *element_type = ClangASTType(m_ast, ext_vector_type->getElementType().getAsOpaquePtr()); - } - return true; - } - default: - break; - } - } + return m_type_system->IsVectorType(m_type, element_type, size); return false; } bool ClangASTType::IsRuntimeGeneratedType () const { - if (!IsValid()) - return false; - - clang::DeclContext* decl_ctx = GetDeclContextForType(); - if (!decl_ctx) - return false; - - if (!llvm::isa(decl_ctx)) - return false; - - clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast(decl_ctx); - - ClangASTMetadata* ast_metadata = ClangASTContext::GetMetadata(m_ast, result_iface_decl); - if (!ast_metadata) - return false; - return (ast_metadata->GetISAPtr() != 0); + if (IsValid()) + return m_type_system->IsRuntimeGeneratedType(m_type); + return false; } bool ClangASTType::IsCharType () const { - if (!IsValid()) - return false; - return GetQualType().getUnqualifiedType()->isCharType(); + if (IsValid()) + return m_type_system->IsCharType(m_type); + return false; } bool ClangASTType::IsCompleteType () const { - if (!IsValid()) - return false; - const bool allow_completion = false; - return GetCompleteQualType (m_ast, GetQualType(), allow_completion); + if (IsValid()) + return m_type_system->IsCompleteType(m_type); + return false; } bool ClangASTType::IsConst() const { - return GetQualType().isConstQualified(); + if (IsValid()) + return m_type_system->IsConst(m_type); + return false; } bool ClangASTType::IsCStringType (uint32_t &length) const { - ClangASTType pointee_or_element_clang_type; - length = 0; - Flags type_flags (GetTypeInfo (&pointee_or_element_clang_type)); - - if (!pointee_or_element_clang_type.IsValid()) - return false; - - if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer)) - { - if (pointee_or_element_clang_type.IsCharType()) - { - if (type_flags.Test (eTypeIsArray)) - { - // We know the size of the array and it could be a C string - // since it is an array of characters - length = llvm::cast(GetCanonicalQualType().getTypePtr())->getSize().getLimitedValue(); - } - return true; - - } - } + if (IsValid()) + return m_type_system->IsCStringType(m_type, length); return false; } @@ -410,44 +156,7 @@ ClangASTType::IsFunctionType (bool *is_variadic_ptr) const { if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - - if (qual_type->isFunctionType()) - { - if (is_variadic_ptr) - { - const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast(qual_type.getTypePtr()); - if (function_proto_type) - *is_variadic_ptr = function_proto_type->isVariadic(); - else - *is_variadic_ptr = false; - } - return true; - } - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).IsFunctionType(); - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).IsFunctionType(); - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).IsFunctionType(); - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); - if (reference_type) - return ClangASTType (m_ast, reference_type->getPointeeType()).IsFunctionType(); - } - break; - } - } + return m_type_system->IsFunctionType(m_type, is_variadic_ptr); return false; } @@ -455,95 +164,8 @@ uint32_t ClangASTType::IsHomogeneousAggregate (ClangASTType* base_type_ptr) const { - if (!IsValid()) - return 0; - - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType ()) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - if (cxx_record_decl->getNumBases() || - cxx_record_decl->isDynamicClass()) - return 0; - } - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - if (record_type) - { - const clang::RecordDecl *record_decl = record_type->getDecl(); - if (record_decl) - { - // We are looking for a structure that contains only floating point types - clang::RecordDecl::field_iterator field_pos, field_end = record_decl->field_end(); - uint32_t num_fields = 0; - bool is_hva = false; - bool is_hfa = false; - clang::QualType base_qual_type; - for (field_pos = record_decl->field_begin(); field_pos != field_end; ++field_pos) - { - clang::QualType field_qual_type = field_pos->getType(); - if (field_qual_type->isFloatingType()) - { - if (field_qual_type->isComplexType()) - return 0; - else - { - if (num_fields == 0) - base_qual_type = field_qual_type; - else - { - if (is_hva) - return 0; - is_hfa = true; - if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) - return 0; - } - } - } - else if (field_qual_type->isVectorType() || field_qual_type->isExtVectorType()) - { - const clang::VectorType *array = field_qual_type.getTypePtr()->getAs(); - if (array && array->getNumElements() <= 4) - { - if (num_fields == 0) - base_qual_type = array->getElementType(); - else - { - if (is_hfa) - return 0; - is_hva = true; - if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) - return 0; - } - } - else - return 0; - } - else - return 0; - ++num_fields; - } - if (base_type_ptr) - *base_type_ptr = ClangASTType (m_ast, base_qual_type); - return num_fields; - } - } - } - break; - - case clang::Type::Typedef: - return ClangASTType(m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).IsHomogeneousAggregate (base_type_ptr); - - case clang::Type::Elaborated: - return ClangASTType(m_ast, llvm::cast(qual_type)->getNamedType()).IsHomogeneousAggregate (base_type_ptr); - default: - break; - } + if (IsValid()) + return m_type_system->IsHomogeneousAggregate(m_type, base_type_ptr); return 0; } @@ -551,12 +173,7 @@ ClangASTType::GetNumberOfFunctionArguments () const { if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - const clang::FunctionProtoType* func = llvm::dyn_cast(qual_type.getTypePtr()); - if (func) - return func->getNumParams(); - } + return m_type_system->GetNumberOfFunctionArguments(m_type); return 0; } @@ -564,15 +181,7 @@ ClangASTType::GetFunctionArgumentAtIndex (const size_t index) const { if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - const clang::FunctionProtoType* func = llvm::dyn_cast(qual_type.getTypePtr()); - if (func) - { - if (index < func->getNumParams()) - return ClangASTType(m_ast, func->getParamType(index).getAsOpaquePtr()); - } - } + return m_type_system->GetFunctionArgumentAtIndex(m_type, index); return ClangASTType(); } @@ -580,34 +189,7 @@ ClangASTType::IsFunctionPointerType () const { if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - - if (qual_type->isFunctionPointerType()) - return true; - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).IsFunctionPointerType(); - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).IsFunctionPointerType(); - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).IsFunctionPointerType(); - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); - if (reference_type) - return ClangASTType (m_ast, reference_type->getPointeeType()).IsFunctionPointerType(); - } - break; - } - } + return m_type_system->IsFunctionPointerType(m_type); return false; } @@ -615,21 +197,8 @@ bool ClangASTType::IsIntegerType (bool &is_signed) const { - if (!IsValid()) - return false; - - clang::QualType qual_type (GetCanonicalQualType()); - const clang::BuiltinType *builtin_type = llvm::dyn_cast(qual_type->getCanonicalTypeInternal()); - - if (builtin_type) - { - if (builtin_type->isInteger()) - { - is_signed = builtin_type->isSignedInteger(); - return true; - } - } - + if (IsValid()) + return m_type_system->IsIntegerType(m_type, is_signed); return false; } @@ -638,45 +207,7 @@ { if (IsValid()) { - clang::QualType qual_type (GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (llvm::cast(qual_type)->getKind()) - { - default: - break; - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - return true; - } - return false; - case clang::Type::ObjCObjectPointer: - if (pointee_type) - pointee_type->SetClangType (m_ast, llvm::cast(qual_type)->getPointeeType()); - return true; - case clang::Type::BlockPointer: - if (pointee_type) - pointee_type->SetClangType (m_ast, llvm::cast(qual_type)->getPointeeType()); - return true; - case clang::Type::Pointer: - if (pointee_type) - pointee_type->SetClangType (m_ast, llvm::cast(qual_type)->getPointeeType()); - return true; - case clang::Type::MemberPointer: - if (pointee_type) - pointee_type->SetClangType (m_ast, llvm::cast(qual_type)->getPointeeType()); - return true; - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).IsPointerType(pointee_type); - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).IsPointerType(pointee_type); - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).IsPointerType(pointee_type); - default: - break; - } + return m_type_system->IsPointerType(m_type, pointee_type); } if (pointee_type) pointee_type->Clear(); @@ -689,53 +220,7 @@ { if (IsValid()) { - clang::QualType qual_type (GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (llvm::cast(qual_type)->getKind()) - { - default: - break; - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - return true; - } - return false; - case clang::Type::ObjCObjectPointer: - if (pointee_type) - pointee_type->SetClangType(m_ast, llvm::cast(qual_type)->getPointeeType()); - return true; - case clang::Type::BlockPointer: - if (pointee_type) - pointee_type->SetClangType(m_ast, llvm::cast(qual_type)->getPointeeType()); - return true; - case clang::Type::Pointer: - if (pointee_type) - pointee_type->SetClangType(m_ast, llvm::cast(qual_type)->getPointeeType()); - return true; - case clang::Type::MemberPointer: - if (pointee_type) - pointee_type->SetClangType(m_ast, llvm::cast(qual_type)->getPointeeType()); - return true; - case clang::Type::LValueReference: - if (pointee_type) - pointee_type->SetClangType(m_ast, llvm::cast(qual_type)->desugar()); - return true; - case clang::Type::RValueReference: - if (pointee_type) - pointee_type->SetClangType(m_ast, llvm::cast(qual_type)->desugar()); - return true; - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).IsPointerOrReferenceType(pointee_type); - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).IsPointerOrReferenceType(pointee_type); - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).IsPointerOrReferenceType(pointee_type); - default: - break; - } + return m_type_system->IsPointerOrReferenceType(m_type, pointee_type); } if (pointee_type) pointee_type->Clear(); @@ -748,33 +233,7 @@ { if (IsValid()) { - clang::QualType qual_type (GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - - switch (type_class) - { - case clang::Type::LValueReference: - if (pointee_type) - pointee_type->SetClangType(m_ast, llvm::cast(qual_type)->desugar()); - if (is_rvalue) - *is_rvalue = false; - return true; - case clang::Type::RValueReference: - if (pointee_type) - pointee_type->SetClangType(m_ast, llvm::cast(qual_type)->desugar()); - if (is_rvalue) - *is_rvalue = true; - return true; - case clang::Type::Typedef: - return ClangASTType(m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).IsReferenceType(pointee_type, is_rvalue); - case clang::Type::Elaborated: - return ClangASTType(m_ast, llvm::cast(qual_type)->getNamedType()).IsReferenceType(pointee_type, is_rvalue); - case clang::Type::Paren: - return ClangASTType(m_ast, llvm::cast(qual_type)->desugar()).IsReferenceType(pointee_type, is_rvalue); - - default: - break; - } + return m_type_system->IsReferenceType(m_type, pointee_type, is_rvalue); } if (pointee_type) pointee_type->Clear(); @@ -786,36 +245,7 @@ { if (IsValid()) { - clang::QualType qual_type (GetCanonicalQualType()); - - if (const clang::BuiltinType *BT = llvm::dyn_cast(qual_type->getCanonicalTypeInternal())) - { - clang::BuiltinType::Kind kind = BT->getKind(); - if (kind >= clang::BuiltinType::Float && kind <= clang::BuiltinType::LongDouble) - { - count = 1; - is_complex = false; - return true; - } - } - else if (const clang::ComplexType *CT = llvm::dyn_cast(qual_type->getCanonicalTypeInternal())) - { - if (ClangASTType (m_ast, CT->getElementType()).IsFloatingPointType (count, is_complex)) - { - count = 2; - is_complex = true; - return true; - } - } - else if (const clang::VectorType *VT = llvm::dyn_cast(qual_type->getCanonicalTypeInternal())) - { - if (ClangASTType (m_ast, VT->getElementType()).IsFloatingPointType (count, is_complex)) - { - count = VT->getNumElements(); - is_complex = false; - return true; - } - } + return m_type_system->IsFloatingPointType(m_type, count, is_complex); } count = 0; is_complex = false; @@ -826,281 +256,47 @@ bool ClangASTType::IsDefined() const { - if (!IsValid()) - return false; - - clang::QualType qual_type(GetQualType()); - const clang::TagType *tag_type = llvm::dyn_cast(qual_type.getTypePtr()); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - return tag_decl->isCompleteDefinition(); - return false; - } - else - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl) - return class_interface_decl->getDefinition() != nullptr; - return false; - } - } + if (IsValid()) + return m_type_system->IsDefined(m_type); return true; } bool -ClangASTType::IsObjCClassType () const +ClangASTType::IsPolymorphicClass () const { if (IsValid()) { - clang::QualType qual_type (GetCanonicalQualType()); - - const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast(qual_type); - - if (obj_pointer_type) - return obj_pointer_type->isObjCClassType(); + return m_type_system->IsPolymorphicClass(m_type); } return false; } bool -ClangASTType::IsObjCObjectOrInterfaceType () const +ClangASTType::IsPossibleDynamicType (ClangASTType *dynamic_pointee_type, + bool check_cplusplus, + bool check_objc) const { if (IsValid()) - return GetCanonicalQualType()->isObjCObjectOrInterfaceType(); + return m_type_system->IsPossibleDynamicType(m_type, dynamic_pointee_type, check_cplusplus, check_objc); return false; } + bool -ClangASTType::IsPolymorphicClass () const +ClangASTType::IsScalarType () const { - if (IsValid()) - { - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType()) - { - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - if (record_decl) - { - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - if (cxx_record_decl) - return cxx_record_decl->isPolymorphic(); - } - } - break; - - default: - break; - } - } - return false; + if (!IsValid()) + return false; + + return m_type_system->IsScalarType(m_type); } bool -ClangASTType::IsPossibleDynamicType (ClangASTType *dynamic_pointee_type, - bool check_cplusplus, - bool check_objc) const -{ - clang::QualType pointee_qual_type; - if (m_type) - { - clang::QualType qual_type (GetCanonicalQualType()); - bool success = false; - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - if (check_objc && llvm::cast(qual_type)->getKind() == clang::BuiltinType::ObjCId) - { - if (dynamic_pointee_type) - dynamic_pointee_type->SetClangType(m_ast, m_type); - return true; - } - break; - - case clang::Type::ObjCObjectPointer: - if (check_objc) - { - if (dynamic_pointee_type) - dynamic_pointee_type->SetClangType(m_ast, llvm::cast(qual_type)->getPointeeType()); - return true; - } - break; - - case clang::Type::Pointer: - pointee_qual_type = llvm::cast(qual_type)->getPointeeType(); - success = true; - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - pointee_qual_type = llvm::cast(qual_type)->getPointeeType(); - success = true; - break; - - case clang::Type::Typedef: - return ClangASTType (m_ast, - llvm::cast(qual_type)->getDecl()->getUnderlyingType()).IsPossibleDynamicType (dynamic_pointee_type, - check_cplusplus, - check_objc); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, - llvm::cast(qual_type)->getNamedType()).IsPossibleDynamicType (dynamic_pointee_type, - check_cplusplus, - check_objc); - - case clang::Type::Paren: - return ClangASTType (m_ast, - llvm::cast(qual_type)->desugar()).IsPossibleDynamicType (dynamic_pointee_type, - check_cplusplus, - check_objc); - default: - break; - } - - if (success) - { - // Check to make sure what we are pointing too is a possible dynamic C++ type - // We currently accept any "void *" (in case we have a class that has been - // watered down to an opaque pointer) and virtual C++ classes. - const clang::Type::TypeClass pointee_type_class = pointee_qual_type.getCanonicalType()->getTypeClass(); - switch (pointee_type_class) - { - case clang::Type::Builtin: - switch (llvm::cast(pointee_qual_type)->getKind()) - { - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - if (dynamic_pointee_type) - dynamic_pointee_type->SetClangType(m_ast, pointee_qual_type); - return true; - - case clang::BuiltinType::NullPtr: - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - case clang::BuiltinType::Dependent: - case clang::BuiltinType::Overload: - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCSel: - case clang::BuiltinType::BoundMember: - case clang::BuiltinType::Half: - case clang::BuiltinType::ARCUnbridgedCast: - case clang::BuiltinType::PseudoObject: - case clang::BuiltinType::BuiltinFn: - case clang::BuiltinType::OCLEvent: - case clang::BuiltinType::OCLImage1d: - case clang::BuiltinType::OCLImage1dArray: - case clang::BuiltinType::OCLImage1dBuffer: - case clang::BuiltinType::OCLImage2d: - case clang::BuiltinType::OCLImage2dArray: - case clang::BuiltinType::OCLImage3d: - case clang::BuiltinType::OCLSampler: - break; - } - break; - - case clang::Type::Record: - if (check_cplusplus) - { - clang::CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - bool is_complete = cxx_record_decl->isCompleteDefinition(); - - if (is_complete) - success = cxx_record_decl->isDynamicClass(); - else - { - ClangASTMetadata *metadata = ClangASTContext::GetMetadata (m_ast, cxx_record_decl); - if (metadata) - success = metadata->GetIsDynamicCXXType(); - else - { - is_complete = ClangASTType(m_ast, pointee_qual_type).GetCompleteType(); - if (is_complete) - success = cxx_record_decl->isDynamicClass(); - else - success = false; - } - } - - if (success) - { - if (dynamic_pointee_type) - dynamic_pointee_type->SetClangType(m_ast, pointee_qual_type); - return true; - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (check_objc) - { - if (dynamic_pointee_type) - dynamic_pointee_type->SetClangType(m_ast, pointee_qual_type); - return true; - } - break; - - default: - break; - } - } - } - if (dynamic_pointee_type) - dynamic_pointee_type->Clear(); - return false; -} - - -bool -ClangASTType::IsScalarType () const -{ - if (!IsValid()) - return false; - - return (GetTypeInfo (nullptr) & eTypeIsScalar) != 0; -} - -bool -ClangASTType::IsTypedefType () const +ClangASTType::IsTypedefType () const { if (!IsValid()) return false; - return GetQualType()->getTypeClass() == clang::Type::Typedef; + return m_type_system->IsTypedefType(m_type); } bool @@ -1108,7 +304,7 @@ { if (!IsValid()) return false; - return GetCanonicalQualType()->isVoidType(); + return m_type_system->IsVoidType(m_type); } bool @@ -1129,101 +325,14 @@ return false; } - -bool -ClangASTType::GetCXXClassName (std::string &class_name) const -{ - if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - class_name.assign (cxx_record_decl->getIdentifier()->getNameStart()); - return true; - } - } - class_name.clear(); - return false; -} - - -bool -ClangASTType::IsCXXClassType () const -{ - if (!IsValid()) - return false; - - clang::QualType qual_type (GetCanonicalQualType()); - if (qual_type->getAsCXXRecordDecl() != nullptr) - return true; - return false; -} - bool ClangASTType::IsBeingDefined () const { if (!IsValid()) return false; - clang::QualType qual_type (GetCanonicalQualType()); - const clang::TagType *tag_type = llvm::dyn_cast(qual_type); - if (tag_type) - return tag_type->isBeingDefined(); - return false; -} - -bool -ClangASTType::IsObjCObjectPointerType (ClangASTType *class_type_ptr) -{ - if (!IsValid()) - return false; - - clang::QualType qual_type (GetCanonicalQualType()); - - if (qual_type->isObjCObjectPointerType()) - { - if (class_type_ptr) - { - if (!qual_type->isObjCClassType() && - !qual_type->isObjCIdType()) - { - const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast(qual_type); - if (obj_pointer_type == nullptr) - class_type_ptr->Clear(); - else - class_type_ptr->SetClangType (m_ast, clang::QualType(obj_pointer_type->getInterfaceType(), 0)); - } - } - return true; - } - if (class_type_ptr) - class_type_ptr->Clear(); - return false; -} - -bool -ClangASTType::GetObjCClassName (std::string &class_name) -{ - if (!IsValid()) - return false; - - clang::QualType qual_type (GetCanonicalQualType()); - - const clang::ObjCObjectType *object_type = llvm::dyn_cast(qual_type); - if (object_type) - { - const clang::ObjCInterfaceDecl *interface = object_type->getInterface(); - if (interface) - { - class_name = interface->getNameAsString(); - return true; - } - } - return false; + return m_type_system->IsBeingDefined(m_type); } - //---------------------------------------------------------------------- // Type Completion //---------------------------------------------------------------------- @@ -1233,8 +342,7 @@ { if (!IsValid()) return false; - const bool allow_completion = true; - return GetCompleteQualType (m_ast, GetQualType(), allow_completion); + return m_type_system->GetCompleteType(m_type); } //---------------------------------------------------------------------- @@ -1243,8 +351,8 @@ size_t ClangASTType::GetPointerByteSize () const { - if (m_ast) - return m_ast->getTypeSize(m_ast->VoidPtrTy) / 8; + if (m_type_system) + return m_type_system->GetPointerByteSize(); return 0; } @@ -1269,25 +377,11 @@ ConstString ClangASTType::GetTypeName () const { - std::string type_name; if (IsValid()) { - clang::PrintingPolicy printing_policy (m_ast->getPrintingPolicy()); - clang::QualType qual_type(GetQualType()); - printing_policy.SuppressTagKeyword = true; - printing_policy.LangOpts.WChar = true; - const clang::TypedefType *typedef_type = qual_type->getAs(); - if (typedef_type) - { - const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); - type_name = typedef_decl->getQualifiedNameAsString(); - } - else - { - type_name = qual_type.getAsString(printing_policy); - } + return m_type_system->GetTypeName(m_type); } - return ConstString(type_name); + return ConstString(""); } ConstString @@ -1302,174 +396,7 @@ if (!IsValid()) return 0; - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->Clear(); - - clang::QualType qual_type (GetQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - { - const clang::BuiltinType *builtin_type = llvm::dyn_cast(qual_type->getCanonicalTypeInternal()); - - uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue; - switch (builtin_type->getKind()) - { - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetClangType(m_ast, m_ast->ObjCBuiltinClassTy); - builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; - break; - - case clang::BuiltinType::ObjCSel: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetClangType(m_ast, m_ast->CharTy); - builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; - break; - - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - builtin_type_flags |= eTypeIsScalar; - if (builtin_type->isInteger()) - { - builtin_type_flags |= eTypeIsInteger; - if (builtin_type->isSignedInteger()) - builtin_type_flags |= eTypeIsSigned; - } - else if (builtin_type->isFloatingPoint()) - builtin_type_flags |= eTypeIsFloat; - break; - default: - break; - } - return builtin_type_flags; - } - - case clang::Type::BlockPointer: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetClangType(m_ast, qual_type->getPointeeType()); - return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock; - - case clang::Type::Complex: - { - uint32_t complex_type_flags = eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex; - const clang::ComplexType *complex_type = llvm::dyn_cast(qual_type->getCanonicalTypeInternal()); - if (complex_type) - { - clang::QualType complex_element_type (complex_type->getElementType()); - if (complex_element_type->isIntegerType()) - complex_type_flags |= eTypeIsFloat; - else if (complex_element_type->isFloatingType()) - complex_type_flags |= eTypeIsInteger; - } - return complex_type_flags; - } - break; - - case clang::Type::ConstantArray: - case clang::Type::DependentSizedArray: - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetClangType(m_ast, llvm::cast(qual_type.getTypePtr())->getElementType()); - return eTypeHasChildren | eTypeIsArray; - - case clang::Type::DependentName: return 0; - case clang::Type::DependentSizedExtVector: return eTypeHasChildren | eTypeIsVector; - case clang::Type::DependentTemplateSpecialization: return eTypeIsTemplate; - case clang::Type::Decltype: return 0; - - case clang::Type::Enum: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetClangType(m_ast, llvm::cast(qual_type)->getDecl()->getIntegerType()); - return eTypeIsEnumeration | eTypeHasValue; - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetTypeInfo (pointee_or_element_clang_type); - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetTypeInfo (pointee_or_element_clang_type); - - case clang::Type::FunctionProto: return eTypeIsFuncPrototype | eTypeHasValue; - case clang::Type::FunctionNoProto: return eTypeIsFuncPrototype | eTypeHasValue; - case clang::Type::InjectedClassName: return 0; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetClangType(m_ast, llvm::cast(qual_type.getTypePtr())->getPointeeType()); - return eTypeHasChildren | eTypeIsReference | eTypeHasValue; - - case clang::Type::MemberPointer: return eTypeIsPointer | eTypeIsMember | eTypeHasValue; - - case clang::Type::ObjCObjectPointer: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetClangType(m_ast, qual_type->getPointeeType()); - return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer | eTypeHasValue; - - case clang::Type::ObjCObject: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; - case clang::Type::ObjCInterface: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; - - case clang::Type::Pointer: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetClangType(m_ast, qual_type->getPointeeType()); - return eTypeHasChildren | eTypeIsPointer | eTypeHasValue; - - case clang::Type::Record: - if (qual_type->getAsCXXRecordDecl()) - return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus; - else - return eTypeHasChildren | eTypeIsStructUnion; - break; - case clang::Type::SubstTemplateTypeParm: return eTypeIsTemplate; - case clang::Type::TemplateTypeParm: return eTypeIsTemplate; - case clang::Type::TemplateSpecialization: return eTypeIsTemplate; - - case clang::Type::Typedef: - return eTypeIsTypedef | ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetTypeInfo (pointee_or_element_clang_type); - case clang::Type::TypeOfExpr: return 0; - case clang::Type::TypeOf: return 0; - case clang::Type::UnresolvedUsing: return 0; - - case clang::Type::ExtVector: - case clang::Type::Vector: - { - uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector; - const clang::VectorType *vector_type = llvm::dyn_cast(qual_type->getCanonicalTypeInternal()); - if (vector_type) - { - if (vector_type->isIntegerType()) - vector_type_flags |= eTypeIsFloat; - else if (vector_type->isFloatingType()) - vector_type_flags |= eTypeIsInteger; - } - return vector_type_flags; - } - default: return 0; - } - return 0; + return m_type_system->GetTypeInfo(m_type, pointee_or_element_clang_type); } @@ -1480,82 +407,7 @@ if (!IsValid()) return lldb::eLanguageTypeC; - // If the type is a reference, then resolve it to what it refers to first: - clang::QualType qual_type (GetCanonicalQualType().getNonReferenceType()); - if (qual_type->isAnyPointerType()) - { - if (qual_type->isObjCObjectPointerType()) - return lldb::eLanguageTypeObjC; - - clang::QualType pointee_type (qual_type->getPointeeType()); - if (pointee_type->getPointeeCXXRecordDecl() != nullptr) - return lldb::eLanguageTypeC_plus_plus; - if (pointee_type->isObjCObjectOrInterfaceType()) - return lldb::eLanguageTypeObjC; - if (pointee_type->isObjCClassType()) - return lldb::eLanguageTypeObjC; - if (pointee_type.getTypePtr() == m_ast->ObjCBuiltinIdTy.getTypePtr()) - return lldb::eLanguageTypeObjC; - } - else - { - if (qual_type->isObjCObjectOrInterfaceType()) - return lldb::eLanguageTypeObjC; - if (qual_type->getAsCXXRecordDecl()) - return lldb::eLanguageTypeC_plus_plus; - switch (qual_type->getTypeClass()) - { - default: - break; - case clang::Type::Builtin: - switch (llvm::cast(qual_type)->getKind()) - { - default: - case clang::BuiltinType::Void: - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - break; - - case clang::BuiltinType::NullPtr: - return eLanguageTypeC_plus_plus; - - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCSel: - return eLanguageTypeObjC; - - case clang::BuiltinType::Dependent: - case clang::BuiltinType::Overload: - case clang::BuiltinType::BoundMember: - case clang::BuiltinType::UnknownAny: - break; - } - break; - case clang::Type::Typedef: - return ClangASTType(m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetMinimumLanguage(); - } - } - return lldb::eLanguageTypeC; + return m_type_system->GetMinimumLanguage(m_type); } lldb::TypeClass @@ -1564,83 +416,21 @@ if (!IsValid()) return lldb::eTypeClassInvalid; - clang::QualType qual_type(GetQualType()); + return m_type_system->GetTypeClass(m_type); - switch (qual_type->getTypeClass()) - { - case clang::Type::UnaryTransform: break; - case clang::Type::FunctionNoProto: return lldb::eTypeClassFunction; - case clang::Type::FunctionProto: return lldb::eTypeClassFunction; - case clang::Type::IncompleteArray: return lldb::eTypeClassArray; - case clang::Type::VariableArray: return lldb::eTypeClassArray; - case clang::Type::ConstantArray: return lldb::eTypeClassArray; - case clang::Type::DependentSizedArray: return lldb::eTypeClassArray; - case clang::Type::DependentSizedExtVector: return lldb::eTypeClassVector; - case clang::Type::ExtVector: return lldb::eTypeClassVector; - case clang::Type::Vector: return lldb::eTypeClassVector; - case clang::Type::Builtin: return lldb::eTypeClassBuiltin; - case clang::Type::ObjCObjectPointer: return lldb::eTypeClassObjCObjectPointer; - case clang::Type::BlockPointer: return lldb::eTypeClassBlockPointer; - case clang::Type::Pointer: return lldb::eTypeClassPointer; - case clang::Type::LValueReference: return lldb::eTypeClassReference; - case clang::Type::RValueReference: return lldb::eTypeClassReference; - case clang::Type::MemberPointer: return lldb::eTypeClassMemberPointer; - case clang::Type::Complex: - if (qual_type->isComplexType()) - return lldb::eTypeClassComplexFloat; - else - return lldb::eTypeClassComplexInteger; - case clang::Type::ObjCObject: return lldb::eTypeClassObjCObject; - case clang::Type::ObjCInterface: return lldb::eTypeClassObjCInterface; - case clang::Type::Record: - { - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - if (record_decl->isUnion()) - return lldb::eTypeClassUnion; - else if (record_decl->isStruct()) - return lldb::eTypeClassStruct; - else - return lldb::eTypeClassClass; - } - break; - case clang::Type::Enum: return lldb::eTypeClassEnumeration; - case clang::Type::Typedef: return lldb::eTypeClassTypedef; - case clang::Type::UnresolvedUsing: break; - case clang::Type::Paren: - return ClangASTType(m_ast, llvm::cast(qual_type)->desugar()).GetTypeClass(); - case clang::Type::Elaborated: - return ClangASTType(m_ast, llvm::cast(qual_type)->getNamedType()).GetTypeClass(); - - case clang::Type::Attributed: break; - case clang::Type::TemplateTypeParm: break; - case clang::Type::SubstTemplateTypeParm: break; - case clang::Type::SubstTemplateTypeParmPack:break; - case clang::Type::Auto: break; - case clang::Type::InjectedClassName: break; - case clang::Type::DependentName: break; - case clang::Type::DependentTemplateSpecialization: break; - case clang::Type::PackExpansion: break; - - case clang::Type::TypeOfExpr: break; - case clang::Type::TypeOf: break; - case clang::Type::Decltype: break; - case clang::Type::TemplateSpecialization: break; - case clang::Type::Atomic: break; +} - // pointer type decayed from an array or function type. - case clang::Type::Decayed: break; - case clang::Type::Adjusted: break; - } - // We don't know hot to display this type... - return lldb::eTypeClassOther; - +void +ClangASTType::SetClangType (TypeSystem* type_system, void* type) +{ + m_type_system = type_system; + m_type = type; } void ClangASTType::SetClangType (clang::ASTContext *ast, clang::QualType qual_type) { - m_ast = ast; + m_type_system = ClangASTContext::GetASTContext(ast); m_type = qual_type.getAsOpaquePtr(); } @@ -1648,7 +438,7 @@ ClangASTType::GetTypeQualifiers() const { if (IsValid()) - return GetQualType().getQualifiers().getCVRQualifiers(); + return m_type_system->GetTypeQualifiers(m_type); return 0; } @@ -1657,60 +447,11 @@ //---------------------------------------------------------------------- ClangASTType -ClangASTType::AddConstModifier () const -{ - if (m_type) - { - clang::QualType result(GetQualType()); - result.addConst(); - return ClangASTType (m_ast, result); - } - return ClangASTType(); -} - -ClangASTType -ClangASTType::AddRestrictModifier () const -{ - if (m_type) - { - clang::QualType result(GetQualType()); - result.getQualifiers().setRestrict (true); - return ClangASTType (m_ast, result); - } - return ClangASTType(); -} - -ClangASTType -ClangASTType::AddVolatileModifier () const -{ - if (m_type) - { - clang::QualType result(GetQualType()); - result.getQualifiers().setVolatile (true); - return ClangASTType (m_ast, result); - } - return ClangASTType(); -} - -ClangASTType ClangASTType::GetArrayElementType (uint64_t *stride) const { if (IsValid()) { - clang::QualType qual_type(GetCanonicalQualType()); - - const clang::Type *array_elem_type = qual_type.getTypePtr()->getArrayElementTypeNoTypeQual(); - - if (!array_elem_type) - return ClangASTType(); - - ClangASTType element_type (m_ast, array_elem_type->getCanonicalTypeUnqualified()); - - // TODO: the real stride will be >= this value.. find the real one! - if (stride) - *stride = element_type.GetByteSize(nullptr); - - return element_type; + return m_type_system->GetArrayElementType(m_type, stride); } return ClangASTType(); @@ -1720,28 +461,15 @@ ClangASTType::GetCanonicalType () const { if (IsValid()) - return ClangASTType (m_ast, GetCanonicalQualType()); + return m_type_system->GetCanonicalType(m_type); return ClangASTType(); } -static clang::QualType -GetFullyUnqualifiedType_Impl (clang::ASTContext *ast, clang::QualType qual_type) -{ - if (qual_type->isPointerType()) - qual_type = ast->getPointerType(GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType())); - else - qual_type = qual_type.getUnqualifiedType(); - qual_type.removeLocalConst(); - qual_type.removeLocalRestrict(); - qual_type.removeLocalVolatile(); - return qual_type; -} - ClangASTType ClangASTType::GetFullyUnqualifiedType () const { if (IsValid()) - return ClangASTType(m_ast, GetFullyUnqualifiedType_Impl(m_ast, GetQualType())); + return m_type_system->GetFullyUnqualifiedType(m_type); return ClangASTType(); } @@ -1751,9 +479,7 @@ { if (IsValid()) { - const clang::FunctionProtoType* func = llvm::dyn_cast(GetCanonicalQualType()); - if (func) - return func->getNumParams(); + return m_type_system->GetFunctionArgumentCount(m_type); } return -1; } @@ -1763,13 +489,7 @@ { if (IsValid()) { - const clang::FunctionProtoType* func = llvm::dyn_cast(GetCanonicalQualType()); - if (func) - { - const uint32_t num_args = func->getNumParams(); - if (idx < num_args) - return ClangASTType(m_ast, func->getParamType(idx)); - } + return m_type_system->GetFunctionArgumentTypeAtIndex(m_type, idx); } return ClangASTType(); } @@ -1779,10 +499,7 @@ { if (IsValid()) { - clang::QualType qual_type(GetCanonicalQualType()); - const clang::FunctionProtoType* func = llvm::dyn_cast(qual_type.getTypePtr()); - if (func) - return ClangASTType(m_ast, func->getReturnType()); + return m_type_system->GetFunctionReturnType(m_type); } return ClangASTType(); } @@ -1790,257 +507,37 @@ size_t ClangASTType::GetNumMemberFunctions () const { - size_t num_functions = 0; if (IsValid()) { - clang::QualType qual_type(GetCanonicalQualType()); - switch (qual_type->getTypeClass()) { - case clang::Type::Record: - if (GetCompleteQualType (m_ast, qual_type)) - { - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - if (cxx_record_decl) - num_functions = std::distance(cxx_record_decl->method_begin(), cxx_record_decl->method_end()); - } - break; - - case clang::Type::ObjCObjectPointer: - if (GetCompleteType()) - { - const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); - if (class_interface_decl) - num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType()) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl) - num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); - } - } - break; - - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumMemberFunctions(); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetNumMemberFunctions(); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetNumMemberFunctions(); - - default: - break; - } + return m_type_system->GetNumMemberFunctions(m_type); } - return num_functions; + return 0; } TypeMemberFunctionImpl ClangASTType::GetMemberFunctionAtIndex (size_t idx) { - std::string name(""); - MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown); - ClangASTType type{}; - clang::ObjCMethodDecl *method_decl(nullptr); if (IsValid()) { - clang::QualType qual_type(GetCanonicalQualType()); - switch (qual_type->getTypeClass()) { - case clang::Type::Record: - if (GetCompleteQualType (m_ast, qual_type)) - { - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - if (cxx_record_decl) - { - auto method_iter = cxx_record_decl->method_begin(); - auto method_end = cxx_record_decl->method_end(); - if (idx < static_cast(std::distance(method_iter, method_end))) - { - std::advance(method_iter, idx); - auto method_decl = method_iter->getCanonicalDecl(); - if (method_decl) - { - if (!method_decl->getName().empty()) - name.assign(method_decl->getName().data()); - else - name.clear(); - if (method_decl->isStatic()) - kind = lldb::eMemberFunctionKindStaticMethod; - else if (llvm::isa(method_decl)) - kind = lldb::eMemberFunctionKindConstructor; - else if (llvm::isa(method_decl)) - kind = lldb::eMemberFunctionKindDestructor; - else - kind = lldb::eMemberFunctionKindInstanceMethod; - type = ClangASTType(m_ast,method_decl->getType().getAsOpaquePtr()); - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - if (GetCompleteType()) - { - const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); - if (class_interface_decl) - { - auto method_iter = class_interface_decl->meth_begin(); - auto method_end = class_interface_decl->meth_end(); - if (idx < static_cast(std::distance(method_iter, method_end))) - { - std::advance(method_iter, idx); - method_decl = method_iter->getCanonicalDecl(); - if (method_decl) - { - name = method_decl->getSelector().getAsString(); - if (method_decl->isClassMethod()) - kind = lldb::eMemberFunctionKindStaticMethod; - else - kind = lldb::eMemberFunctionKindInstanceMethod; - } - } - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType()) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl) - { - auto method_iter = class_interface_decl->meth_begin(); - auto method_end = class_interface_decl->meth_end(); - if (idx < static_cast(std::distance(method_iter, method_end))) - { - std::advance(method_iter, idx); - method_decl = method_iter->getCanonicalDecl(); - if (method_decl) - { - name = method_decl->getSelector().getAsString(); - if (method_decl->isClassMethod()) - kind = lldb::eMemberFunctionKindStaticMethod; - else - kind = lldb::eMemberFunctionKindInstanceMethod; - } - } - } - } - } - break; - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetMemberFunctionAtIndex(idx); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetMemberFunctionAtIndex(idx); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetMemberFunctionAtIndex(idx); - - default: - break; - } + return m_type_system->GetMemberFunctionAtIndex(m_type, idx); } - - if (kind == eMemberFunctionKindUnknown) - return TypeMemberFunctionImpl(); - if (method_decl) - return TypeMemberFunctionImpl(method_decl, name, kind); - if (type) - return TypeMemberFunctionImpl(type, name, kind); - return TypeMemberFunctionImpl(); } ClangASTType -ClangASTType::GetLValueReferenceType () const +ClangASTType::GetNonReferenceType () const { if (IsValid()) - { - return ClangASTType(m_ast, m_ast->getLValueReferenceType(GetQualType())); - } - return ClangASTType(); -} - -ClangASTType -ClangASTType::GetRValueReferenceType () const -{ - if (IsValid()) - { - return ClangASTType(m_ast, m_ast->getRValueReferenceType(GetQualType())); - } - return ClangASTType(); -} - -ClangASTType -ClangASTType::GetNonReferenceType () const -{ - if (IsValid()) - return ClangASTType(m_ast, GetQualType().getNonReferenceType()); - return ClangASTType(); -} - -ClangASTType -ClangASTType::CreateTypedefType (const char *typedef_name, - clang::DeclContext *decl_ctx) const -{ - if (IsValid() && typedef_name && typedef_name[0]) - { - clang::QualType qual_type (GetQualType()); - if (decl_ctx == nullptr) - decl_ctx = m_ast->getTranslationUnitDecl(); - clang::TypedefDecl *decl = clang::TypedefDecl::Create (*m_ast, - decl_ctx, - clang::SourceLocation(), - clang::SourceLocation(), - &m_ast->Idents.get(typedef_name), - m_ast->getTrivialTypeSourceInfo(qual_type)); - - decl->setAccess(clang::AS_public); // TODO respect proper access specifier - - // Get a uniqued clang::QualType for the typedef decl type - return ClangASTType (m_ast, m_ast->getTypedefType (decl)); - } + return m_type_system->GetNonReferenceType(m_type); return ClangASTType(); - } ClangASTType ClangASTType::GetPointeeType () const { - if (m_type) + if (IsValid()) { - clang::QualType qual_type(GetQualType()); - return ClangASTType (m_ast, qual_type.getTypePtr()->getPointeeType()); + return m_type_system->GetPointeeType(m_type); } return ClangASTType(); } @@ -2050,18 +547,7 @@ { if (IsValid()) { - clang::QualType qual_type (GetQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - return ClangASTType(m_ast, m_ast->getObjCObjectPointerType(qual_type).getAsOpaquePtr()); - - default: - return ClangASTType(m_ast, m_ast->getPointerType(qual_type).getAsOpaquePtr()); - } + return m_type_system->GetPointerType(m_type); } return ClangASTType(); } @@ -2071,21 +557,7 @@ { if (IsValid()) { - const clang::TypedefType *typedef_type = llvm::dyn_cast(GetQualType()); - if (typedef_type) - return ClangASTType (m_ast, typedef_type->getDecl()->getUnderlyingType()); - } - return ClangASTType(); -} - -ClangASTType -ClangASTType::RemoveFastQualifiers () const -{ - if (m_type) - { - clang::QualType qual_type(GetQualType()); - qual_type.getQualifiers().removeFastQualifiers(); - return ClangASTType (m_ast, qual_type); + return m_type_system->GetTypedefedType(m_type); } return ClangASTType(); } @@ -2099,7 +571,7 @@ ClangASTType::GetBasicTypeFromAST (lldb::BasicType basic_type) const { if (IsValid()) - return ClangASTContext::GetBasicType(m_ast, basic_type); + return m_type_system->GetBasicTypeFromAST(m_type, basic_type); return ClangASTType(); } //---------------------------------------------------------------------- @@ -2109,56 +581,9 @@ uint64_t ClangASTType::GetBitSize (ExecutionContextScope *exe_scope) const { - if (GetCompleteType ()) + if (IsValid()) { - clang::QualType qual_type(GetCanonicalQualType()); - switch (qual_type->getTypeClass()) - { - case clang::Type::ObjCInterface: - case clang::Type::ObjCObject: - { - ExecutionContext exe_ctx (exe_scope); - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); - if (objc_runtime) - { - uint64_t bit_size = 0; - if (objc_runtime->GetTypeBitSize(*this, bit_size)) - return bit_size; - } - } - else - { - static bool g_printed = false; - if (!g_printed) - { - StreamString s; - DumpTypeDescription(&s); - - llvm::outs() << "warning: trying to determine the size of type "; - llvm::outs() << s.GetString() << "\n"; - llvm::outs() << "without a valid ExecutionContext. this is not reliable. please file a bug against LLDB.\n"; - llvm::outs() << "backtrace:\n"; - llvm::sys::PrintStackTrace(llvm::outs()); - llvm::outs() << "\n"; - g_printed = true; - } - } - } - // fallthrough - default: - const uint32_t bit_size = m_ast->getTypeSize (qual_type); - if (bit_size == 0) - { - if (qual_type->isIncompleteArrayType()) - return m_ast->getTypeSize (qual_type->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified()); - } - if (qual_type->isObjCObjectOrInterfaceType()) - return bit_size + m_ast->getTypeSize(m_ast->ObjCBuiltinClassTy); - return bit_size; - } + return m_type_system->GetBitSize(m_type, exe_scope); } return 0; } @@ -2173,8 +598,8 @@ size_t ClangASTType::GetTypeBitAlign () const { - if (GetCompleteType ()) - return m_ast->getTypeAlign(GetQualType()); + if (IsValid()) + return m_type_system->GetTypeBitAlign(m_type); return 0; } @@ -2185,153 +610,7 @@ if (!IsValid()) return lldb::eEncodingInvalid; - count = 1; - clang::QualType qual_type(GetCanonicalQualType()); - - switch (qual_type->getTypeClass()) - { - case clang::Type::UnaryTransform: - break; - - case clang::Type::FunctionNoProto: - case clang::Type::FunctionProto: - break; - - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - break; - - case clang::Type::ConstantArray: - break; - - case clang::Type::ExtVector: - case clang::Type::Vector: - // TODO: Set this to more than one??? - break; - - case clang::Type::Builtin: - switch (llvm::cast(qual_type)->getKind()) - { - default: assert(0 && "Unknown builtin type!"); - case clang::BuiltinType::Void: - break; - - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: return lldb::eEncodingSint; - - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: return lldb::eEncodingUint; - - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: return lldb::eEncodingIEEE754; - - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCSel: return lldb::eEncodingUint; - - case clang::BuiltinType::NullPtr: return lldb::eEncodingUint; - - case clang::BuiltinType::Kind::ARCUnbridgedCast: - case clang::BuiltinType::Kind::BoundMember: - case clang::BuiltinType::Kind::BuiltinFn: - case clang::BuiltinType::Kind::Dependent: - case clang::BuiltinType::Kind::Half: - case clang::BuiltinType::Kind::OCLEvent: - case clang::BuiltinType::Kind::OCLImage1d: - case clang::BuiltinType::Kind::OCLImage1dArray: - case clang::BuiltinType::Kind::OCLImage1dBuffer: - case clang::BuiltinType::Kind::OCLImage2d: - case clang::BuiltinType::Kind::OCLImage2dArray: - case clang::BuiltinType::Kind::OCLImage3d: - case clang::BuiltinType::Kind::OCLSampler: - case clang::BuiltinType::Kind::Overload: - case clang::BuiltinType::Kind::PseudoObject: - case clang::BuiltinType::Kind::UnknownAny: - break; - } - break; - // All pointer types are represented as unsigned integer encodings. - // We may nee to add a eEncodingPointer if we ever need to know the - // difference - case clang::Type::ObjCObjectPointer: - case clang::Type::BlockPointer: - case clang::Type::Pointer: - case clang::Type::LValueReference: - case clang::Type::RValueReference: - case clang::Type::MemberPointer: return lldb::eEncodingUint; - case clang::Type::Complex: - { - lldb::Encoding encoding = lldb::eEncodingIEEE754; - if (qual_type->isComplexType()) - encoding = lldb::eEncodingIEEE754; - else - { - const clang::ComplexType *complex_type = qual_type->getAsComplexIntegerType(); - if (complex_type) - encoding = ClangASTType(m_ast, complex_type->getElementType()).GetEncoding(count); - else - encoding = lldb::eEncodingSint; - } - count = 2; - return encoding; - } - - case clang::Type::ObjCInterface: break; - case clang::Type::Record: break; - case clang::Type::Enum: return lldb::eEncodingSint; - case clang::Type::Typedef: - return ClangASTType(m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetEncoding(count); - - case clang::Type::Elaborated: - return ClangASTType(m_ast, llvm::cast(qual_type)->getNamedType()).GetEncoding(count); - - case clang::Type::Paren: - return ClangASTType(m_ast, llvm::cast(qual_type)->desugar()).GetEncoding(count); - - case clang::Type::DependentSizedArray: - case clang::Type::DependentSizedExtVector: - case clang::Type::UnresolvedUsing: - case clang::Type::Attributed: - case clang::Type::TemplateTypeParm: - case clang::Type::SubstTemplateTypeParm: - case clang::Type::SubstTemplateTypeParmPack: - case clang::Type::Auto: - case clang::Type::InjectedClassName: - case clang::Type::DependentName: - case clang::Type::DependentTemplateSpecialization: - case clang::Type::PackExpansion: - case clang::Type::ObjCObject: - - case clang::Type::TypeOfExpr: - case clang::Type::TypeOf: - case clang::Type::Decltype: - case clang::Type::TemplateSpecialization: - case clang::Type::Atomic: - case clang::Type::Adjusted: - break; - - // pointer type decayed from an array or function type. - case clang::Type::Decayed: - break; - } - count = 0; - return lldb::eEncodingInvalid; + return m_type_system->GetEncoding(m_type, count); } lldb::Format @@ -2340,147 +619,7 @@ if (!IsValid()) return lldb::eFormatDefault; - clang::QualType qual_type(GetCanonicalQualType()); - - switch (qual_type->getTypeClass()) - { - case clang::Type::UnaryTransform: - break; - - case clang::Type::FunctionNoProto: - case clang::Type::FunctionProto: - break; - - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - break; - - case clang::Type::ConstantArray: - return lldb::eFormatVoid; // no value - - case clang::Type::ExtVector: - case clang::Type::Vector: - break; - - case clang::Type::Builtin: - switch (llvm::cast(qual_type)->getKind()) - { - //default: assert(0 && "Unknown builtin type!"); - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - case clang::BuiltinType::BoundMember: - break; - - case clang::BuiltinType::Bool: return lldb::eFormatBoolean; - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: return lldb::eFormatChar; - case clang::BuiltinType::Char16: return lldb::eFormatUnicode16; - case clang::BuiltinType::Char32: return lldb::eFormatUnicode32; - case clang::BuiltinType::UShort: return lldb::eFormatUnsigned; - case clang::BuiltinType::Short: return lldb::eFormatDecimal; - case clang::BuiltinType::UInt: return lldb::eFormatUnsigned; - case clang::BuiltinType::Int: return lldb::eFormatDecimal; - case clang::BuiltinType::ULong: return lldb::eFormatUnsigned; - case clang::BuiltinType::Long: return lldb::eFormatDecimal; - case clang::BuiltinType::ULongLong: return lldb::eFormatUnsigned; - case clang::BuiltinType::LongLong: return lldb::eFormatDecimal; - case clang::BuiltinType::UInt128: return lldb::eFormatUnsigned; - case clang::BuiltinType::Int128: return lldb::eFormatDecimal; - case clang::BuiltinType::Float: return lldb::eFormatFloat; - case clang::BuiltinType::Double: return lldb::eFormatFloat; - case clang::BuiltinType::LongDouble: return lldb::eFormatFloat; - case clang::BuiltinType::NullPtr: - case clang::BuiltinType::Overload: - case clang::BuiltinType::Dependent: - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCSel: - case clang::BuiltinType::Half: - case clang::BuiltinType::ARCUnbridgedCast: - case clang::BuiltinType::PseudoObject: - case clang::BuiltinType::BuiltinFn: - case clang::BuiltinType::OCLEvent: - case clang::BuiltinType::OCLImage1d: - case clang::BuiltinType::OCLImage1dArray: - case clang::BuiltinType::OCLImage1dBuffer: - case clang::BuiltinType::OCLImage2d: - case clang::BuiltinType::OCLImage2dArray: - case clang::BuiltinType::OCLImage3d: - case clang::BuiltinType::OCLSampler: - return lldb::eFormatHex; - } - break; - case clang::Type::ObjCObjectPointer: return lldb::eFormatHex; - case clang::Type::BlockPointer: return lldb::eFormatHex; - case clang::Type::Pointer: return lldb::eFormatHex; - case clang::Type::LValueReference: - case clang::Type::RValueReference: return lldb::eFormatHex; - case clang::Type::MemberPointer: break; - case clang::Type::Complex: - { - if (qual_type->isComplexType()) - return lldb::eFormatComplex; - else - return lldb::eFormatComplexInteger; - } - case clang::Type::ObjCInterface: break; - case clang::Type::Record: break; - case clang::Type::Enum: return lldb::eFormatEnum; - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetFormat(); - case clang::Type::Auto: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetFormat(); - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetFormat(); - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetFormat(); - case clang::Type::DependentSizedArray: - case clang::Type::DependentSizedExtVector: - case clang::Type::UnresolvedUsing: - case clang::Type::Attributed: - case clang::Type::TemplateTypeParm: - case clang::Type::SubstTemplateTypeParm: - case clang::Type::SubstTemplateTypeParmPack: - case clang::Type::InjectedClassName: - case clang::Type::DependentName: - case clang::Type::DependentTemplateSpecialization: - case clang::Type::PackExpansion: - case clang::Type::ObjCObject: - - case clang::Type::TypeOfExpr: - case clang::Type::TypeOf: - case clang::Type::Decltype: - case clang::Type::TemplateSpecialization: - case clang::Type::Atomic: - case clang::Type::Adjusted: - break; - - // pointer type decayed from an array or function type. - case clang::Type::Decayed: - break; - } - // We don't know hot to display this type... - return lldb::eFormatBytes; -} - -static bool -ObjCDeclHasIVars (clang::ObjCInterfaceDecl *class_interface_decl, bool check_superclass) -{ - while (class_interface_decl) - { - if (class_interface_decl->ivar_size() > 0) - return true; - - if (check_superclass) - class_interface_decl = class_interface_decl->getSuperClass(); - else - break; - } - return false; + return m_type_system->GetFormat(m_type); } uint32_t @@ -2488,168 +627,7 @@ { if (!IsValid()) return 0; - - uint32_t num_children = 0; - clang::QualType qual_type(GetQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (llvm::cast(qual_type)->getKind()) - { - case clang::BuiltinType::ObjCId: // child is Class - case clang::BuiltinType::ObjCClass: // child is Class - num_children = 1; - break; - - default: - break; - } - break; - - case clang::Type::Complex: return 0; - - case clang::Type::Record: - if (GetCompleteQualType (m_ast, qual_type)) - { - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - if (cxx_record_decl) - { - if (omit_empty_base_classes) - { - // Check each base classes to see if it or any of its - // base classes contain any fields. This can help - // limit the noise in variable views by not having to - // show base classes that contain no members. - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - const clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); - - // Skip empty base classes - if (ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - - num_children++; - } - } - else - { - // Include all base classes - num_children += cxx_record_decl->getNumBases(); - } - - } - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field) - ++num_children; - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteQualType (m_ast, qual_type)) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (omit_empty_base_classes) - { - if (ObjCDeclHasIVars (superclass_interface_decl, true)) - ++num_children; - } - else - ++num_children; - } - - num_children += class_interface_decl->ivar_size(); - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - { - const clang::ObjCObjectPointerType *pointer_type = llvm::cast(qual_type.getTypePtr()); - clang::QualType pointee_type = pointer_type->getPointeeType(); - uint32_t num_pointee_children = ClangASTType (m_ast,pointee_type).GetNumChildren (omit_empty_base_classes); - // If this type points to a simple type, then it has 1 child - if (num_pointee_children == 0) - num_children = 1; - else - num_children = num_pointee_children; - } - break; - - case clang::Type::Vector: - case clang::Type::ExtVector: - num_children = llvm::cast(qual_type.getTypePtr())->getNumElements(); - break; - - case clang::Type::ConstantArray: - num_children = llvm::cast(qual_type.getTypePtr())->getSize().getLimitedValue(); - break; - - case clang::Type::Pointer: - { - const clang::PointerType *pointer_type = llvm::cast(qual_type.getTypePtr()); - clang::QualType pointee_type (pointer_type->getPointeeType()); - uint32_t num_pointee_children = ClangASTType (m_ast,pointee_type).GetNumChildren (omit_empty_base_classes); - if (num_pointee_children == 0) - { - // We have a pointer to a pointee type that claims it has no children. - // We will want to look at - num_children = ClangASTType (m_ast, pointee_type).GetNumPointeeChildren(); - } - else - num_children = num_pointee_children; - } - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); - clang::QualType pointee_type = reference_type->getPointeeType(); - uint32_t num_pointee_children = ClangASTType (m_ast, pointee_type).GetNumChildren (omit_empty_base_classes); - // If this type points to a simple type, then it has 1 child - if (num_pointee_children == 0) - num_children = 1; - else - num_children = num_pointee_children; - } - break; - - - case clang::Type::Typedef: - num_children = ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumChildren (omit_empty_base_classes); - break; - - case clang::Type::Elaborated: - num_children = ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetNumChildren (omit_empty_base_classes); - break; - - case clang::Type::Paren: - num_children = ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetNumChildren (omit_empty_base_classes); - break; - default: - break; - } - return num_children; + return m_type_system->GetNumChildren(m_type, omit_empty_base_classes); } lldb::BasicType @@ -2657,3752 +635,136 @@ { if (IsValid()) { - clang::QualType qual_type(GetQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - if (type_class == clang::Type::Builtin) - { - switch (llvm::cast(qual_type)->getKind()) - { - case clang::BuiltinType::Void: return eBasicTypeVoid; - case clang::BuiltinType::Bool: return eBasicTypeBool; - case clang::BuiltinType::Char_S: return eBasicTypeSignedChar; - case clang::BuiltinType::Char_U: return eBasicTypeUnsignedChar; - case clang::BuiltinType::Char16: return eBasicTypeChar16; - case clang::BuiltinType::Char32: return eBasicTypeChar32; - case clang::BuiltinType::UChar: return eBasicTypeUnsignedChar; - case clang::BuiltinType::SChar: return eBasicTypeSignedChar; - case clang::BuiltinType::WChar_S: return eBasicTypeSignedWChar; - case clang::BuiltinType::WChar_U: return eBasicTypeUnsignedWChar; - case clang::BuiltinType::Short: return eBasicTypeShort; - case clang::BuiltinType::UShort: return eBasicTypeUnsignedShort; - case clang::BuiltinType::Int: return eBasicTypeInt; - case clang::BuiltinType::UInt: return eBasicTypeUnsignedInt; - case clang::BuiltinType::Long: return eBasicTypeLong; - case clang::BuiltinType::ULong: return eBasicTypeUnsignedLong; - case clang::BuiltinType::LongLong: return eBasicTypeLongLong; - case clang::BuiltinType::ULongLong: return eBasicTypeUnsignedLongLong; - case clang::BuiltinType::Int128: return eBasicTypeInt128; - case clang::BuiltinType::UInt128: return eBasicTypeUnsignedInt128; - - case clang::BuiltinType::Half: return eBasicTypeHalf; - case clang::BuiltinType::Float: return eBasicTypeFloat; - case clang::BuiltinType::Double: return eBasicTypeDouble; - case clang::BuiltinType::LongDouble:return eBasicTypeLongDouble; - - case clang::BuiltinType::NullPtr: return eBasicTypeNullPtr; - case clang::BuiltinType::ObjCId: return eBasicTypeObjCID; - case clang::BuiltinType::ObjCClass: return eBasicTypeObjCClass; - case clang::BuiltinType::ObjCSel: return eBasicTypeObjCSel; - case clang::BuiltinType::Dependent: - case clang::BuiltinType::Overload: - case clang::BuiltinType::BoundMember: - case clang::BuiltinType::PseudoObject: - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::BuiltinFn: - case clang::BuiltinType::ARCUnbridgedCast: - case clang::BuiltinType::OCLEvent: - case clang::BuiltinType::OCLImage1d: - case clang::BuiltinType::OCLImage1dArray: - case clang::BuiltinType::OCLImage1dBuffer: - case clang::BuiltinType::OCLImage2d: - case clang::BuiltinType::OCLImage2dArray: - case clang::BuiltinType::OCLImage3d: - case clang::BuiltinType::OCLSampler: - return eBasicTypeOther; - } - } + return m_type_system->GetBasicTypeEnumeration(m_type); } return eBasicTypeInvalid; } - #pragma mark Aggregate Types uint32_t -ClangASTType::GetNumDirectBaseClasses () const +ClangASTType::GetNumFields () const { if (!IsValid()) return 0; - - uint32_t count = 0; - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType()) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - count = cxx_record_decl->getNumBases(); - } - break; - - case clang::Type::ObjCObjectPointer: - count = GetPointeeType().GetNumDirectBaseClasses(); - break; - - case clang::Type::ObjCObject: - if (GetCompleteType()) - { - const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl && class_interface_decl->getSuperClass()) - count = 1; - } - } - break; - case clang::Type::ObjCInterface: - if (GetCompleteType()) - { - const clang::ObjCInterfaceType *objc_interface_type = qual_type->getAs(); - if (objc_interface_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface(); - - if (class_interface_decl && class_interface_decl->getSuperClass()) - count = 1; - } - } - break; - - - case clang::Type::Typedef: - count = ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumDirectBaseClasses (); - break; - - case clang::Type::Elaborated: - count = ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetNumDirectBaseClasses (); - break; - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetNumDirectBaseClasses (); - - default: - break; - } - return count; + return m_type_system->GetNumFields(m_type); } -uint32_t -ClangASTType::GetNumVirtualBaseClasses () const +ClangASTType +ClangASTType::GetFieldAtIndex (size_t idx, + std::string& name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) const { if (!IsValid()) - return 0; - - uint32_t count = 0; - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType()) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - count = cxx_record_decl->getNumVBases(); - } - break; - - case clang::Type::Typedef: - count = ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumVirtualBaseClasses(); - break; - - case clang::Type::Elaborated: - count = ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetNumVirtualBaseClasses(); - break; - - case clang::Type::Paren: - count = ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetNumVirtualBaseClasses(); - break; - - default: - break; - } - return count; + return ClangASTType(); + return m_type_system->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); } uint32_t -ClangASTType::GetNumFields () const +ClangASTType::GetIndexOfFieldWithName (const char* name, + ClangASTType* field_clang_type_ptr, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) const { - if (!IsValid()) - return 0; - - uint32_t count = 0; - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) + unsigned count = GetNumFields(); + std::string field_name; + for (unsigned index = 0; index < count; index++) { - case clang::Type::Record: - if (GetCompleteType()) - { - const clang::RecordType *record_type = llvm::dyn_cast(qual_type.getTypePtr()); - if (record_type) - { - clang::RecordDecl *record_decl = record_type->getDecl(); - if (record_decl) - { - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field) - ++field_idx; - count = field_idx; - } - } - } - break; - - case clang::Type::Typedef: - count = ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumFields(); - break; - - case clang::Type::Elaborated: - count = ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetNumFields(); - break; - - case clang::Type::Paren: - count = ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetNumFields(); - break; - - case clang::Type::ObjCObjectPointer: - if (GetCompleteType()) - { - const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); - - if (class_interface_decl) - count = class_interface_decl->ivar_size(); - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType()) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - count = class_interface_decl->ivar_size(); - } - } - break; - - default: - break; + ClangASTType field_clang_type (GetFieldAtIndex(index, field_name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); + if (strcmp(field_name.c_str(), name) == 0) + { + if (field_clang_type_ptr) + *field_clang_type_ptr = field_clang_type; + return index; + } } - return count; + return UINT32_MAX; } ClangASTType -ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) const +ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, + size_t idx, + bool transparent_pointers, + bool omit_empty_base_classes, + bool ignore_array_bounds, + std::string& child_name, + uint32_t &child_byte_size, + int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, + uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, + bool &child_is_deref_of_parent, + ValueObject *valobj) const { if (!IsValid()) return ClangASTType(); - - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType()) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - uint32_t curr_idx = 0; - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class, ++curr_idx) - { - if (curr_idx == idx) - { - if (bit_offset_ptr) - { - const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(cxx_record_decl); - const clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); - if (base_class->isVirtual()) - *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; - else - *bit_offset_ptr = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; - } - return ClangASTType (m_ast, base_class->getType()); - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - return GetPointeeType().GetDirectBaseClassAtIndex(idx,bit_offset_ptr); - - case clang::Type::ObjCObject: - if (idx == 0 && GetCompleteType()) - { - const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (bit_offset_ptr) - *bit_offset_ptr = 0; - return ClangASTType (m_ast, m_ast->getObjCInterfaceType(superclass_interface_decl)); - } - } - } - } - break; - case clang::Type::ObjCInterface: - if (idx == 0 && GetCompleteType()) - { - const clang::ObjCObjectType *objc_interface_type = qual_type->getAs(); - if (objc_interface_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface(); - - if (class_interface_decl) - { - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (bit_offset_ptr) - *bit_offset_ptr = 0; - return ClangASTType (m_ast, m_ast->getObjCInterfaceType(superclass_interface_decl)); - } - } - } - } - break; - - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr); - - default: - break; - } - return ClangASTType(); + return m_type_system->GetChildClangTypeAtIndex(m_type, exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, valobj); } -ClangASTType -ClangASTType::GetVirtualBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) const -{ - if (!IsValid()) - return ClangASTType(); - - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType()) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - uint32_t curr_idx = 0; - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->vbases_begin(), base_class_end = cxx_record_decl->vbases_end(); - base_class != base_class_end; - ++base_class, ++curr_idx) - { - if (curr_idx == idx) - { - if (bit_offset_ptr) - { - const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(cxx_record_decl); - const clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); - *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; - - } - return ClangASTType (m_ast, base_class->getType()); - } - } - } - } - break; - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr); - - default: - break; - } - return ClangASTType(); -} - -static clang_type_t -GetObjCFieldAtIndex (clang::ASTContext *ast, - clang::ObjCInterfaceDecl *class_interface_decl, - size_t idx, - std::string& name, - uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, - bool *is_bitfield_ptr) -{ - if (class_interface_decl) - { - if (idx < (class_interface_decl->ivar_size())) - { - clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - uint32_t ivar_idx = 0; - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++ivar_idx) - { - if (ivar_idx == idx) - { - const clang::ObjCIvarDecl* ivar_decl = *ivar_pos; - - clang::QualType ivar_qual_type(ivar_decl->getType()); - - name.assign(ivar_decl->getNameAsString()); - - if (bit_offset_ptr) - { - const clang::ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl); - *bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx); - } - - const bool is_bitfield = ivar_pos->isBitField(); - - if (bitfield_bit_size_ptr) - { - *bitfield_bit_size_ptr = 0; - - if (is_bitfield && ast) - { - clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth(); - llvm::APSInt bitfield_apsint; - if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast)) - { - *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); - } - } - } - if (is_bitfield_ptr) - *is_bitfield_ptr = is_bitfield; - - return ivar_qual_type.getAsOpaquePtr(); - } - } - } - } - return nullptr; -} - -ClangASTType -ClangASTType::GetFieldAtIndex (size_t idx, - std::string& name, - uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, - bool *is_bitfield_ptr) const -{ - if (!IsValid()) - return ClangASTType(); - - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType()) - { - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx) - { - if (idx == field_idx) - { - // Print the member type if requested - // Print the member name and equal sign - name.assign(field->getNameAsString()); - - // Figure out the type byte size (field_type_info.first) and - // alignment (field_type_info.second) from the AST context. - if (bit_offset_ptr) - { - const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl); - *bit_offset_ptr = record_layout.getFieldOffset (field_idx); - } - - const bool is_bitfield = field->isBitField(); - - if (bitfield_bit_size_ptr) - { - *bitfield_bit_size_ptr = 0; - - if (is_bitfield) - { - clang::Expr *bitfield_bit_size_expr = field->getBitWidth(); - llvm::APSInt bitfield_apsint; - if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *m_ast)) - { - *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); - } - } - } - if (is_bitfield_ptr) - *is_bitfield_ptr = is_bitfield; - - return ClangASTType (m_ast, field->getType()); - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - if (GetCompleteType()) - { - const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); - return ClangASTType (m_ast, GetObjCFieldAtIndex(m_ast, class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType()) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - return ClangASTType (m_ast, GetObjCFieldAtIndex(m_ast, class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); - } - } - break; - - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - default: - break; - } - return ClangASTType(); -} - -uint32_t -ClangASTType::GetIndexOfFieldWithName (const char* name, - ClangASTType* field_clang_type_ptr, - uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, - bool *is_bitfield_ptr) const -{ - unsigned count = GetNumFields(); - std::string field_name; - for (unsigned index = 0; index < count; index++) - { - ClangASTType field_clang_type (GetFieldAtIndex(index, field_name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); - if (strcmp(field_name.c_str(), name) == 0) - { - if (field_clang_type_ptr) - *field_clang_type_ptr = field_clang_type; - return index; - } - } - return UINT32_MAX; -} - -// If a pointer to a pointee type (the clang_type arg) says that it has no -// children, then we either need to trust it, or override it and return a -// different result. For example, an "int *" has one child that is an integer, -// but a function pointer doesn't have any children. Likewise if a Record type -// claims it has no children, then there really is nothing to show. -uint32_t -ClangASTType::GetNumPointeeChildren () const -{ - if (!IsValid()) - return 0; - - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (llvm::cast(qual_type)->getKind()) - { - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - case clang::BuiltinType::NullPtr: - case clang::BuiltinType::OCLEvent: - case clang::BuiltinType::OCLImage1d: - case clang::BuiltinType::OCLImage1dArray: - case clang::BuiltinType::OCLImage1dBuffer: - case clang::BuiltinType::OCLImage2d: - case clang::BuiltinType::OCLImage2dArray: - case clang::BuiltinType::OCLImage3d: - case clang::BuiltinType::OCLSampler: - return 0; - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - case clang::BuiltinType::Dependent: - case clang::BuiltinType::Overload: - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCSel: - case clang::BuiltinType::BoundMember: - case clang::BuiltinType::Half: - case clang::BuiltinType::ARCUnbridgedCast: - case clang::BuiltinType::PseudoObject: - case clang::BuiltinType::BuiltinFn: - return 1; - } - break; - - case clang::Type::Complex: return 1; - case clang::Type::Pointer: return 1; - case clang::Type::BlockPointer: return 0; // If block pointers don't have debug info, then no children for them - case clang::Type::LValueReference: return 1; - case clang::Type::RValueReference: return 1; - case clang::Type::MemberPointer: return 0; - case clang::Type::ConstantArray: return 0; - case clang::Type::IncompleteArray: return 0; - case clang::Type::VariableArray: return 0; - case clang::Type::DependentSizedArray: return 0; - case clang::Type::DependentSizedExtVector: return 0; - case clang::Type::Vector: return 0; - case clang::Type::ExtVector: return 0; - case clang::Type::FunctionProto: return 0; // When we function pointers, they have no children... - case clang::Type::FunctionNoProto: return 0; // When we function pointers, they have no children... - case clang::Type::UnresolvedUsing: return 0; - case clang::Type::Paren: return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetNumPointeeChildren (); - case clang::Type::Typedef: return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumPointeeChildren (); - case clang::Type::Elaborated: return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetNumPointeeChildren (); - case clang::Type::TypeOfExpr: return 0; - case clang::Type::TypeOf: return 0; - case clang::Type::Decltype: return 0; - case clang::Type::Record: return 0; - case clang::Type::Enum: return 1; - case clang::Type::TemplateTypeParm: return 1; - case clang::Type::SubstTemplateTypeParm: return 1; - case clang::Type::TemplateSpecialization: return 1; - case clang::Type::InjectedClassName: return 0; - case clang::Type::DependentName: return 1; - case clang::Type::DependentTemplateSpecialization: return 1; - case clang::Type::ObjCObject: return 0; - case clang::Type::ObjCInterface: return 0; - case clang::Type::ObjCObjectPointer: return 1; - default: - break; - } - return 0; -} - - -ClangASTType -ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, - size_t idx, - bool transparent_pointers, - bool omit_empty_base_classes, - bool ignore_array_bounds, - std::string& child_name, - uint32_t &child_byte_size, - int32_t &child_byte_offset, - uint32_t &child_bitfield_bit_size, - uint32_t &child_bitfield_bit_offset, - bool &child_is_base_class, - bool &child_is_deref_of_parent, - ValueObject *valobj) const -{ - if (!IsValid()) - return ClangASTType(); - - clang::QualType parent_qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass(); - child_bitfield_bit_size = 0; - child_bitfield_bit_offset = 0; - child_is_base_class = false; - - const bool idx_is_valid = idx < GetNumChildren (omit_empty_base_classes); - uint32_t bit_offset; - switch (parent_type_class) - { - case clang::Type::Builtin: - if (idx_is_valid) - { - switch (llvm::cast(parent_qual_type)->getKind()) - { - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - child_name = "isa"; - child_byte_size = m_ast->getTypeSize(m_ast->ObjCBuiltinClassTy) / CHAR_BIT; - return ClangASTType (m_ast, m_ast->ObjCBuiltinClassTy); - - default: - break; - } - } - break; - - case clang::Type::Record: - if (idx_is_valid && GetCompleteType()) - { - const clang::RecordType *record_type = llvm::cast(parent_qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl); - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - if (cxx_record_decl) - { - // We might have base classes to print out first - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - const clang::CXXRecordDecl *base_class_decl = nullptr; - - // Skip empty base classes - if (omit_empty_base_classes) - { - base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); - if (ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - } - - if (idx == child_idx) - { - if (base_class_decl == nullptr) - base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); - - - if (base_class->isVirtual()) - { - bool handled = false; - if (valobj) - { - Error err; - AddressType addr_type = eAddressTypeInvalid; - lldb::addr_t vtable_ptr_addr = valobj->GetCPPVTableAddress(addr_type); - - if (vtable_ptr_addr != LLDB_INVALID_ADDRESS && addr_type == eAddressTypeLoad) - { - - ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - clang::VTableContextBase *vtable_ctx = m_ast->getVTableContext(); - if (vtable_ctx) - { - if (vtable_ctx->isMicrosoft()) - { - clang::MicrosoftVTableContext *msoft_vtable_ctx = static_cast(vtable_ctx); - - if (vtable_ptr_addr) - { - const lldb::addr_t vbtable_ptr_addr = vtable_ptr_addr + record_layout.getVBPtrOffset().getQuantity(); - - const lldb::addr_t vbtable_ptr = process->ReadPointerFromMemory(vbtable_ptr_addr, err); - if (vbtable_ptr != LLDB_INVALID_ADDRESS) - { - // Get the index into the virtual base table. The index is the index in uint32_t from vbtable_ptr - const unsigned vbtable_index = msoft_vtable_ctx->getVBTableIndex(cxx_record_decl, base_class_decl); - const lldb::addr_t base_offset_addr = vbtable_ptr + vbtable_index * 4; - const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err); - if (base_offset != UINT32_MAX) - { - handled = true; - bit_offset = base_offset * 8; - } - } - } - } - else - { - clang::ItaniumVTableContext *itanium_vtable_ctx = static_cast(vtable_ctx); - if (vtable_ptr_addr) - { - const lldb::addr_t vtable_ptr = process->ReadPointerFromMemory(vtable_ptr_addr, err); - if (vtable_ptr != LLDB_INVALID_ADDRESS) - { - clang::CharUnits base_offset_offset = itanium_vtable_ctx->getVirtualBaseOffsetOffset(cxx_record_decl, base_class_decl); - const lldb::addr_t base_offset_addr = vtable_ptr + base_offset_offset.getQuantity(); - const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err); - if (base_offset != UINT32_MAX) - { - handled = true; - bit_offset = base_offset * 8; - } - } - } - } - } - } - } - - } - if (!handled) - bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; - } - else - bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; - - // Base classes should be a multiple of 8 bits in size - child_byte_offset = bit_offset/8; - ClangASTType base_class_clang_type(m_ast, base_class->getType()); - child_name = base_class_clang_type.GetTypeName().AsCString(""); - uint64_t base_class_clang_type_bit_size = base_class_clang_type.GetBitSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - - // Base classes bit sizes should be a multiple of 8 bits in size - assert (base_class_clang_type_bit_size % 8 == 0); - child_byte_size = base_class_clang_type_bit_size / 8; - child_is_base_class = true; - return base_class_clang_type; - } - // We don't increment the child index in the for loop since we might - // be skipping empty base classes - ++child_idx; - } - } - // Make sure index is in range... - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx) - { - if (idx == child_idx) - { - // Print the member type if requested - // Print the member name and equal sign - child_name.assign(field->getNameAsString().c_str()); - - // Figure out the type byte size (field_type_info.first) and - // alignment (field_type_info.second) from the AST context. - ClangASTType field_clang_type (m_ast, field->getType()); - assert(field_idx < record_layout.getFieldCount()); - child_byte_size = field_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - - // Figure out the field offset within the current struct/union/class type - bit_offset = record_layout.getFieldOffset (field_idx); - child_byte_offset = bit_offset / 8; - if (ClangASTContext::FieldIsBitfield (m_ast, *field, child_bitfield_bit_size)) - child_bitfield_bit_offset = bit_offset % 8; - - return field_clang_type; - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (idx_is_valid && GetCompleteType()) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(parent_qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - uint32_t child_idx = 0; - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - - const clang::ASTRecordLayout &interface_layout = m_ast->getASTObjCInterfaceLayout(class_interface_decl); - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (omit_empty_base_classes) - { - ClangASTType base_class_clang_type (m_ast, m_ast->getObjCInterfaceType(superclass_interface_decl)); - if (base_class_clang_type.GetNumChildren(omit_empty_base_classes) > 0) - { - if (idx == 0) - { - clang::QualType ivar_qual_type(m_ast->getObjCInterfaceType(superclass_interface_decl)); - - - child_name.assign(superclass_interface_decl->getNameAsString().c_str()); - - clang::TypeInfo ivar_type_info = m_ast->getTypeInfo(ivar_qual_type.getTypePtr()); - - child_byte_size = ivar_type_info.Width / 8; - child_byte_offset = 0; - child_is_base_class = true; - - return ClangASTType (m_ast, ivar_qual_type); - } - - ++child_idx; - } - } - else - ++child_idx; - } - - const uint32_t superclass_idx = child_idx; - - if (idx < (child_idx + class_interface_decl->ivar_size())) - { - clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos) - { - if (child_idx == idx) - { - clang::ObjCIvarDecl* ivar_decl = *ivar_pos; - - clang::QualType ivar_qual_type(ivar_decl->getType()); - - child_name.assign(ivar_decl->getNameAsString().c_str()); - - clang::TypeInfo ivar_type_info = m_ast->getTypeInfo(ivar_qual_type.getTypePtr()); - - child_byte_size = ivar_type_info.Width / 8; - - // Figure out the field offset within the current struct/union/class type - // For ObjC objects, we can't trust the bit offset we get from the Clang AST, since - // that doesn't account for the space taken up by unbacked properties, or from - // the changing size of base classes that are newer than this class. - // So if we have a process around that we can ask about this object, do so. - child_byte_offset = LLDB_INVALID_IVAR_OFFSET; - Process *process = nullptr; - if (exe_ctx) - process = exe_ctx->GetProcessPtr(); - if (process) - { - ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); - if (objc_runtime != nullptr) - { - ClangASTType parent_ast_type (m_ast, parent_qual_type); - child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str()); - } - } - - // Setting this to UINT32_MAX to make sure we don't compute it twice... - bit_offset = UINT32_MAX; - - if (child_byte_offset == static_cast(LLDB_INVALID_IVAR_OFFSET)) - { - bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); - child_byte_offset = bit_offset / 8; - } - - // Note, the ObjC Ivar Byte offset is just that, it doesn't account for the bit offset - // of a bitfield within its containing object. So regardless of where we get the byte - // offset from, we still need to get the bit offset for bitfields from the layout. - - if (ClangASTContext::FieldIsBitfield (m_ast, ivar_decl, child_bitfield_bit_size)) - { - if (bit_offset == UINT32_MAX) - bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); - - child_bitfield_bit_offset = bit_offset % 8; - } - return ClangASTType (m_ast, ivar_qual_type); - } - ++child_idx; - } - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - if (idx_is_valid) - { - ClangASTType pointee_clang_type (GetPointeeType()); - - if (transparent_pointers && pointee_clang_type.IsAggregateType()) - { - child_is_deref_of_parent = false; - bool tmp_child_is_deref_of_parent = false; - return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - tmp_child_is_deref_of_parent, - valobj); - } - else - { - child_is_deref_of_parent = true; - const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; - if (parent_name) - { - child_name.assign(1, '*'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0 && pointee_clang_type.GetCompleteType()) - { - child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee_clang_type; - } - } - } - break; - - case clang::Type::Vector: - case clang::Type::ExtVector: - if (idx_is_valid) - { - const clang::VectorType *array = llvm::cast(parent_qual_type.getTypePtr()); - if (array) - { - ClangASTType element_type (m_ast, array->getElementType()); - if (element_type.GetCompleteType()) - { - char element_name[64]; - ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", static_cast(idx)); - child_name.assign(element_name); - child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; - return element_type; - } - } - } - break; - - case clang::Type::ConstantArray: - case clang::Type::IncompleteArray: - if (ignore_array_bounds || idx_is_valid) - { - const clang::ArrayType *array = GetQualType()->getAsArrayTypeUnsafe(); - if (array) - { - ClangASTType element_type (m_ast, array->getElementType()); - if (element_type.GetCompleteType()) - { - char element_name[64]; - ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", static_cast(idx)); - child_name.assign(element_name); - child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; - return element_type; - } - } - } - break; - - - case clang::Type::Pointer: - if (idx_is_valid) - { - ClangASTType pointee_clang_type (GetPointeeType()); - - // Don't dereference "void *" pointers - if (pointee_clang_type.IsVoidType()) - return ClangASTType(); - - if (transparent_pointers && pointee_clang_type.IsAggregateType ()) - { - child_is_deref_of_parent = false; - bool tmp_child_is_deref_of_parent = false; - return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - tmp_child_is_deref_of_parent, - valobj); - } - else - { - child_is_deref_of_parent = true; - - const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; - if (parent_name) - { - child_name.assign(1, '*'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0) - { - child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee_clang_type; - } - } - } - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - if (idx_is_valid) - { - const clang::ReferenceType *reference_type = llvm::cast(parent_qual_type.getTypePtr()); - ClangASTType pointee_clang_type (m_ast, reference_type->getPointeeType()); - if (transparent_pointers && pointee_clang_type.IsAggregateType ()) - { - child_is_deref_of_parent = false; - bool tmp_child_is_deref_of_parent = false; - return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - tmp_child_is_deref_of_parent, - valobj); - } - else - { - const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; - if (parent_name) - { - child_name.assign(1, '&'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0) - { - child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee_clang_type; - } - } - } - break; - - case clang::Type::Typedef: - { - ClangASTType typedefed_clang_type (m_ast, llvm::cast(parent_qual_type)->getDecl()->getUnderlyingType()); - return typedefed_clang_type.GetChildClangTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - valobj); - } - break; - - case clang::Type::Elaborated: - { - ClangASTType elaborated_clang_type (m_ast, llvm::cast(parent_qual_type)->getNamedType()); - return elaborated_clang_type.GetChildClangTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - valobj); - } - - case clang::Type::Paren: - { - ClangASTType paren_clang_type (m_ast, llvm::cast(parent_qual_type)->desugar()); - return paren_clang_type.GetChildClangTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - valobj); - } - - - default: - break; - } - return ClangASTType(); -} - -static inline bool -BaseSpecifierIsEmpty (const clang::CXXBaseSpecifier *b) -{ - return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == false; -} - -static uint32_t -GetIndexForRecordBase -( - const clang::RecordDecl *record_decl, - const clang::CXXBaseSpecifier *base_spec, - bool omit_empty_base_classes - ) -{ - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - - // const char *super_name = record_decl->getNameAsCString(); - // const char *base_name = base_spec->getType()->getAs()->getDecl()->getNameAsCString(); - // printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name); - // - if (cxx_record_decl) - { - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - if (omit_empty_base_classes) - { - if (BaseSpecifierIsEmpty (base_class)) - continue; - } - - // printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", super_name, base_name, - // child_idx, - // base_class->getType()->getAs()->getDecl()->getNameAsCString()); - // - // - if (base_class == base_spec) - return child_idx; - ++child_idx; - } - } - - return UINT32_MAX; -} - - -static uint32_t -GetIndexForRecordChild (const clang::RecordDecl *record_decl, - clang::NamedDecl *canonical_decl, - bool omit_empty_base_classes) -{ - uint32_t child_idx = ClangASTContext::GetNumBaseClasses (llvm::dyn_cast(record_decl), - omit_empty_base_classes); - - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); - field != field_end; - ++field, ++child_idx) - { - if (field->getCanonicalDecl() == canonical_decl) - return child_idx; - } - - return UINT32_MAX; -} -// Look for a child member (doesn't include base classes, but it does include -// their members) in the type hierarchy. Returns an index path into "clang_type" -// on how to reach the appropriate member. -// -// class A -// { -// public: -// int m_a; -// int m_b; -// }; -// -// class B -// { -// }; -// -// class C : -// public B, -// public A -// { -// }; -// -// If we have a clang type that describes "class C", and we wanted to looked -// "m_b" in it: -// -// With omit_empty_base_classes == false we would get an integer array back with: -// { 1, 1 } -// The first index 1 is the child index for "class A" within class C -// The second index 1 is the child index for "m_b" within class A -// -// With omit_empty_base_classes == true we would get an integer array back with: -// { 0, 1 } -// The first index 0 is the child index for "class A" within class C (since class B doesn't have any members it doesn't count) -// The second index 1 is the child index for "m_b" within class A size_t ClangASTType::GetIndexOfChildMemberWithName (const char *name, bool omit_empty_base_classes, - std::vector& child_indexes) const -{ - if (IsValid() && name && name[0]) - { - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType ()) - { - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - - assert(record_decl); - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - - // Try and find a field that matches NAME - clang::RecordDecl::field_iterator field, field_end; - llvm::StringRef name_sref(name); - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); - field != field_end; - ++field, ++child_idx) - { - llvm::StringRef field_name = field->getName(); - if (field_name.empty()) - { - ClangASTType field_type(m_ast,field->getType()); - child_indexes.push_back(child_idx); - if (field_type.GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes)) - return child_indexes.size(); - child_indexes.pop_back(); - - } - else if (field_name.equals (name_sref)) - { - // We have to add on the number of base classes to this index! - child_indexes.push_back (child_idx + ClangASTContext::GetNumBaseClasses (cxx_record_decl, omit_empty_base_classes)); - return child_indexes.size(); - } - } - - if (cxx_record_decl) - { - const clang::RecordDecl *parent_record_decl = cxx_record_decl; - - //printf ("parent = %s\n", parent_record_decl->getNameAsCString()); - - //const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl(); - // Didn't find things easily, lets let clang do its thang... - clang::IdentifierInfo & ident_ref = m_ast->Idents.get(name_sref); - clang::DeclarationName decl_name(&ident_ref); - - clang::CXXBasePaths paths; - if (cxx_record_decl->lookupInBases(clang::CXXRecordDecl::FindOrdinaryMember, - decl_name.getAsOpaquePtr(), - paths)) - { - clang::CXXBasePaths::const_paths_iterator path, path_end = paths.end(); - for (path = paths.begin(); path != path_end; ++path) - { - const size_t num_path_elements = path->size(); - for (size_t e=0; e(elem.Base->getType()->getAs()->getDecl()); - } - } - for (clang::NamedDecl *path_decl : path->Decls) - { - child_idx = GetIndexForRecordChild (parent_record_decl, path_decl, omit_empty_base_classes); - if (child_idx == UINT32_MAX) - { - child_indexes.clear(); - return 0; - } - else - { - child_indexes.push_back (child_idx); - } - } - } - return child_indexes.size(); - } - } - - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType ()) - { - llvm::StringRef name_sref(name); - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - uint32_t child_idx = 0; - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx) - { - const clang::ObjCIvarDecl* ivar_decl = *ivar_pos; - - if (ivar_decl->getName().equals (name_sref)) - { - if ((!omit_empty_base_classes && superclass_interface_decl) || - ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true))) - ++child_idx; - - child_indexes.push_back (child_idx); - return child_indexes.size(); - } - } - - if (superclass_interface_decl) - { - // The super class index is always zero for ObjC classes, - // so we push it onto the child indexes in case we find - // an ivar in our superclass... - child_indexes.push_back (0); - - ClangASTType superclass_clang_type (m_ast, m_ast->getObjCInterfaceType(superclass_interface_decl)); - if (superclass_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes)) - { - // We did find an ivar in a superclass so just - // return the results! - return child_indexes.size(); - } - - // We didn't find an ivar matching "name" in our - // superclass, pop the superclass zero index that - // we pushed on above. - child_indexes.pop_back(); - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - { - ClangASTType objc_object_clang_type (m_ast, llvm::cast(qual_type.getTypePtr())->getPointeeType()); - return objc_object_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - } - break; - - - case clang::Type::ConstantArray: - { - // const clang::ConstantArrayType *array = llvm::cast(parent_qual_type.getTypePtr()); - // const uint64_t element_count = array->getSize().getLimitedValue(); - // - // if (idx < element_count) - // { - // std::pair field_type_info = ast->getTypeInfo(array->getElementType()); - // - // char element_name[32]; - // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx); - // - // child_name.assign(element_name); - // assert(field_type_info.first % 8 == 0); - // child_byte_size = field_type_info.first / 8; - // child_byte_offset = idx * child_byte_size; - // return array->getElementType().getAsOpaquePtr(); - // } - } - break; - - // case clang::Type::MemberPointerType: - // { - // MemberPointerType *mem_ptr_type = llvm::cast(qual_type.getTypePtr()); - // clang::QualType pointee_type = mem_ptr_type->getPointeeType(); - // - // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - // { - // return GetIndexOfChildWithName (ast, - // mem_ptr_type->getPointeeType().getAsOpaquePtr(), - // name); - // } - // } - // break; - // - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); - clang::QualType pointee_type(reference_type->getPointeeType()); - ClangASTType pointee_clang_type (m_ast, pointee_type); - - if (pointee_clang_type.IsAggregateType ()) - { - return pointee_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - } - } - break; - - case clang::Type::Pointer: - { - ClangASTType pointee_clang_type (GetPointeeType()); - - if (pointee_clang_type.IsAggregateType ()) - { - return pointee_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - } - } - break; - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - default: - break; - } - } - return 0; -} - - -// Get the index of the child of "clang_type" whose name matches. This function -// doesn't descend into the children, but only looks one level deep and name -// matches can include base class names. - -uint32_t -ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_classes) const -{ - if (IsValid() && name && name[0]) - { - clang::QualType qual_type(GetCanonicalQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType ()) - { - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - - assert(record_decl); - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - - if (cxx_record_decl) - { - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - // Skip empty base classes - clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); - if (omit_empty_base_classes && ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - - ClangASTType base_class_clang_type (m_ast, base_class->getType()); - std::string base_class_type_name (base_class_clang_type.GetTypeName().AsCString("")); - if (base_class_type_name.compare (name) == 0) - return child_idx; - ++child_idx; - } - } - - // Try and find a field that matches NAME - clang::RecordDecl::field_iterator field, field_end; - llvm::StringRef name_sref(name); - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); - field != field_end; - ++field, ++child_idx) - { - if (field->getName().equals (name_sref)) - return child_idx; - } - - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType()) - { - llvm::StringRef name_sref(name); - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - uint32_t child_idx = 0; - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx) - { - const clang::ObjCIvarDecl* ivar_decl = *ivar_pos; - - if (ivar_decl->getName().equals (name_sref)) - { - if ((!omit_empty_base_classes && superclass_interface_decl) || - ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true))) - ++child_idx; - - return child_idx; - } - } - - if (superclass_interface_decl) - { - if (superclass_interface_decl->getName().equals (name_sref)) - return 0; - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - { - ClangASTType pointee_clang_type (m_ast, llvm::cast(qual_type.getTypePtr())->getPointeeType()); - return pointee_clang_type.GetIndexOfChildWithName (name, omit_empty_base_classes); - } - break; - - case clang::Type::ConstantArray: - { - // const clang::ConstantArrayType *array = llvm::cast(parent_qual_type.getTypePtr()); - // const uint64_t element_count = array->getSize().getLimitedValue(); - // - // if (idx < element_count) - // { - // std::pair field_type_info = ast->getTypeInfo(array->getElementType()); - // - // char element_name[32]; - // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx); - // - // child_name.assign(element_name); - // assert(field_type_info.first % 8 == 0); - // child_byte_size = field_type_info.first / 8; - // child_byte_offset = idx * child_byte_size; - // return array->getElementType().getAsOpaquePtr(); - // } - } - break; - - // case clang::Type::MemberPointerType: - // { - // MemberPointerType *mem_ptr_type = llvm::cast(qual_type.getTypePtr()); - // clang::QualType pointee_type = mem_ptr_type->getPointeeType(); - // - // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - // { - // return GetIndexOfChildWithName (ast, - // mem_ptr_type->getPointeeType().getAsOpaquePtr(), - // name); - // } - // } - // break; - // - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); - ClangASTType pointee_type (m_ast, reference_type->getPointeeType()); - - if (pointee_type.IsAggregateType ()) - { - return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes); - } - } - break; - - case clang::Type::Pointer: - { - const clang::PointerType *pointer_type = llvm::cast(qual_type.getTypePtr()); - ClangASTType pointee_type (m_ast, pointer_type->getPointeeType()); - - if (pointee_type.IsAggregateType ()) - { - return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes); - } - else - { - // if (parent_name) - // { - // child_name.assign(1, '*'); - // child_name += parent_name; - // } - // - // // We have a pointer to an simple type - // if (idx == 0) - // { - // std::pair clang_type_info = ast->getTypeInfo(pointee_type); - // assert(clang_type_info.first % 8 == 0); - // child_byte_size = clang_type_info.first / 8; - // child_byte_offset = 0; - // return pointee_type.getAsOpaquePtr(); - // } - } - } - break; - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - default: - break; - } - } - return UINT32_MAX; -} - - -size_t -ClangASTType::GetNumTemplateArguments () const -{ - if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType ()) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast(cxx_record_decl); - if (template_decl) - return template_decl->getTemplateArgs().size(); - } - } - break; - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumTemplateArguments(); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetNumTemplateArguments(); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetNumTemplateArguments(); - - default: - break; - } - } - return 0; -} - -ClangASTType -ClangASTType::GetTemplateArgument (size_t arg_idx, lldb::TemplateArgumentKind &kind) const -{ - if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType ()) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast(cxx_record_decl); - if (template_decl && arg_idx < template_decl->getTemplateArgs().size()) - { - const clang::TemplateArgument &template_arg = template_decl->getTemplateArgs()[arg_idx]; - switch (template_arg.getKind()) - { - case clang::TemplateArgument::Null: - kind = eTemplateArgumentKindNull; - return ClangASTType(); - - case clang::TemplateArgument::Type: - kind = eTemplateArgumentKindType; - return ClangASTType(m_ast, template_arg.getAsType()); - - case clang::TemplateArgument::Declaration: - kind = eTemplateArgumentKindDeclaration; - return ClangASTType(); - - case clang::TemplateArgument::Integral: - kind = eTemplateArgumentKindIntegral; - return ClangASTType(m_ast, template_arg.getIntegralType()); - - case clang::TemplateArgument::Template: - kind = eTemplateArgumentKindTemplate; - return ClangASTType(); - - case clang::TemplateArgument::TemplateExpansion: - kind = eTemplateArgumentKindTemplateExpansion; - return ClangASTType(); - - case clang::TemplateArgument::Expression: - kind = eTemplateArgumentKindExpression; - return ClangASTType(); - - case clang::TemplateArgument::Pack: - kind = eTemplateArgumentKindPack; - return ClangASTType(); - - default: - assert (!"Unhandled clang::TemplateArgument::ArgKind"); - break; - } - } - } - } - break; - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetTemplateArgument (arg_idx, kind); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetTemplateArgument (arg_idx, kind); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetTemplateArgument (arg_idx, kind); - - default: - break; - } - } - kind = eTemplateArgumentKindNull; - return ClangASTType (); -} - -static bool -IsOperator (const char *name, clang::OverloadedOperatorKind &op_kind) -{ - if (name == nullptr || name[0] == '\0') - return false; - -#define OPERATOR_PREFIX "operator" -#define OPERATOR_PREFIX_LENGTH (sizeof (OPERATOR_PREFIX) - 1) - - const char *post_op_name = nullptr; - - bool no_space = true; - - if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH)) - return false; - - post_op_name = name + OPERATOR_PREFIX_LENGTH; - - if (post_op_name[0] == ' ') - { - post_op_name++; - no_space = false; - } - -#undef OPERATOR_PREFIX -#undef OPERATOR_PREFIX_LENGTH - - // This is an operator, set the overloaded operator kind to invalid - // in case this is a conversion operator... - op_kind = clang::NUM_OVERLOADED_OPERATORS; - - switch (post_op_name[0]) - { - default: - if (no_space) - return false; - break; - case 'n': - if (no_space) - return false; - if (strcmp (post_op_name, "new") == 0) - op_kind = clang::OO_New; - else if (strcmp (post_op_name, "new[]") == 0) - op_kind = clang::OO_Array_New; - break; - - case 'd': - if (no_space) - return false; - if (strcmp (post_op_name, "delete") == 0) - op_kind = clang::OO_Delete; - else if (strcmp (post_op_name, "delete[]") == 0) - op_kind = clang::OO_Array_Delete; - break; - - case '+': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Plus; - else if (post_op_name[2] == '\0') - { - if (post_op_name[1] == '=') - op_kind = clang::OO_PlusEqual; - else if (post_op_name[1] == '+') - op_kind = clang::OO_PlusPlus; - } - break; - - case '-': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Minus; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '=': op_kind = clang::OO_MinusEqual; break; - case '-': op_kind = clang::OO_MinusMinus; break; - case '>': op_kind = clang::OO_Arrow; break; - } - } - else if (post_op_name[3] == '\0') - { - if (post_op_name[2] == '*') - op_kind = clang::OO_ArrowStar; break; - } - break; - - case '*': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Star; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_StarEqual; - break; - - case '/': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Slash; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_SlashEqual; - break; - - case '%': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Percent; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_PercentEqual; - break; - - - case '^': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Caret; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_CaretEqual; - break; - - case '&': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Amp; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '=': op_kind = clang::OO_AmpEqual; break; - case '&': op_kind = clang::OO_AmpAmp; break; - } - } - break; - - case '|': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Pipe; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '=': op_kind = clang::OO_PipeEqual; break; - case '|': op_kind = clang::OO_PipePipe; break; - } - } - break; - - case '~': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Tilde; - break; - - case '!': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Exclaim; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_ExclaimEqual; - break; - - case '=': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Equal; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_EqualEqual; - break; - - case '<': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Less; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '<': op_kind = clang::OO_LessLess; break; - case '=': op_kind = clang::OO_LessEqual; break; - } - } - else if (post_op_name[3] == '\0') - { - if (post_op_name[2] == '=') - op_kind = clang::OO_LessLessEqual; - } - break; - - case '>': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Greater; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '>': op_kind = clang::OO_GreaterGreater; break; - case '=': op_kind = clang::OO_GreaterEqual; break; - } - } - else if (post_op_name[1] == '>' && - post_op_name[2] == '=' && - post_op_name[3] == '\0') - { - op_kind = clang::OO_GreaterGreaterEqual; - } - break; - - case ',': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Comma; - break; - - case '(': - if (post_op_name[1] == ')' && post_op_name[2] == '\0') - op_kind = clang::OO_Call; - break; - - case '[': - if (post_op_name[1] == ']' && post_op_name[2] == '\0') - op_kind = clang::OO_Subscript; - break; - } - - return true; -} - -clang::EnumDecl * -ClangASTType::GetAsEnumDecl () const -{ - const clang::EnumType *enum_type = llvm::dyn_cast(GetCanonicalQualType()); - if (enum_type) - return enum_type->getDecl(); - return NULL; -} - -clang::RecordDecl * -ClangASTType::GetAsRecordDecl () const -{ - const clang::RecordType *record_type = llvm::dyn_cast(GetCanonicalQualType()); - if (record_type) - return record_type->getDecl(); - return nullptr; -} - -clang::CXXRecordDecl * -ClangASTType::GetAsCXXRecordDecl () const -{ - return GetCanonicalQualType()->getAsCXXRecordDecl(); -} - -clang::ObjCInterfaceDecl * -ClangASTType::GetAsObjCInterfaceDecl () const -{ - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(GetCanonicalQualType()); - if (objc_class_type) - return objc_class_type->getInterface(); - return nullptr; -} - -clang::FieldDecl * -ClangASTType::AddFieldToRecordType (const char *name, - const ClangASTType &field_clang_type, - AccessType access, - uint32_t bitfield_bit_size) -{ - if (!IsValid() || !field_clang_type.IsValid()) - return nullptr; - - clang::FieldDecl *field = nullptr; - - clang::Expr *bit_width = nullptr; - if (bitfield_bit_size != 0) - { - llvm::APInt bitfield_bit_size_apint(m_ast->getTypeSize(m_ast->IntTy), bitfield_bit_size); - bit_width = new (*m_ast)clang::IntegerLiteral (*m_ast, bitfield_bit_size_apint, m_ast->IntTy, clang::SourceLocation()); - } - - clang::RecordDecl *record_decl = GetAsRecordDecl (); - if (record_decl) - { - field = clang::FieldDecl::Create (*m_ast, - record_decl, - clang::SourceLocation(), - clang::SourceLocation(), - name ? &m_ast->Idents.get(name) : nullptr, // Identifier - field_clang_type.GetQualType(), // Field type - nullptr, // TInfo * - bit_width, // BitWidth - false, // Mutable - clang::ICIS_NoInit); // HasInit - - if (!name) - { - // Determine whether this field corresponds to an anonymous - // struct or union. - if (const clang::TagType *TagT = field->getType()->getAs()) { - if (clang::RecordDecl *Rec = llvm::dyn_cast(TagT->getDecl())) - if (!Rec->getDeclName()) { - Rec->setAnonymousStructOrUnion(true); - field->setImplicit(); - - } - } - } - - if (field) - { - field->setAccess (ClangASTContext::ConvertAccessTypeToAccessSpecifier (access)); - - record_decl->addDecl(field); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(field); -#endif - } - } - else - { - clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (); - - if (class_interface_decl) - { - const bool is_synthesized = false; - - field_clang_type.GetCompleteType(); - - field = clang::ObjCIvarDecl::Create (*m_ast, - class_interface_decl, - clang::SourceLocation(), - clang::SourceLocation(), - name ? &m_ast->Idents.get(name) : nullptr, // Identifier - field_clang_type.GetQualType(), // Field type - nullptr, // TypeSourceInfo * - ConvertAccessTypeToObjCIvarAccessControl (access), - bit_width, - is_synthesized); - - if (field) - { - class_interface_decl->addDecl(field); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(field); -#endif - } - } - } - return field; -} - -void -ClangASTType::BuildIndirectFields () -{ - clang::RecordDecl *record_decl = GetAsRecordDecl(); - - if (!record_decl) - return; - - typedef llvm::SmallVector IndirectFieldVector; - - IndirectFieldVector indirect_fields; - clang::RecordDecl::field_iterator field_pos; - clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end(); - clang::RecordDecl::field_iterator last_field_pos = field_end_pos; - for (field_pos = record_decl->field_begin(); field_pos != field_end_pos; last_field_pos = field_pos++) - { - if (field_pos->isAnonymousStructOrUnion()) - { - clang::QualType field_qual_type = field_pos->getType(); - - const clang::RecordType *field_record_type = field_qual_type->getAs(); - - if (!field_record_type) - continue; - - clang::RecordDecl *field_record_decl = field_record_type->getDecl(); - - if (!field_record_decl) - continue; - - for (clang::RecordDecl::decl_iterator di = field_record_decl->decls_begin(), de = field_record_decl->decls_end(); - di != de; - ++di) - { - if (clang::FieldDecl *nested_field_decl = llvm::dyn_cast(*di)) - { - clang::NamedDecl **chain = new (*m_ast) clang::NamedDecl*[2]; - chain[0] = *field_pos; - chain[1] = nested_field_decl; - clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*m_ast, - record_decl, - clang::SourceLocation(), - nested_field_decl->getIdentifier(), - nested_field_decl->getType(), - chain, - 2); - - indirect_field->setImplicit(); - - indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(), - nested_field_decl->getAccess())); - - indirect_fields.push_back(indirect_field); - } - else if (clang::IndirectFieldDecl *nested_indirect_field_decl = llvm::dyn_cast(*di)) - { - int nested_chain_size = nested_indirect_field_decl->getChainingSize(); - clang::NamedDecl **chain = new (*m_ast) clang::NamedDecl*[nested_chain_size + 1]; - chain[0] = *field_pos; - - int chain_index = 1; - for (clang::IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(), - nce = nested_indirect_field_decl->chain_end(); - nci < nce; - ++nci) - { - chain[chain_index] = *nci; - chain_index++; - } - - clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*m_ast, - record_decl, - clang::SourceLocation(), - nested_indirect_field_decl->getIdentifier(), - nested_indirect_field_decl->getType(), - chain, - nested_chain_size + 1); - - indirect_field->setImplicit(); - - indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(), - nested_indirect_field_decl->getAccess())); - - indirect_fields.push_back(indirect_field); - } - } - } - } - - // Check the last field to see if it has an incomplete array type as its - // last member and if it does, the tell the record decl about it - if (last_field_pos != field_end_pos) - { - if (last_field_pos->getType()->isIncompleteArrayType()) - record_decl->hasFlexibleArrayMember(); - } - - for (IndirectFieldVector::iterator ifi = indirect_fields.begin(), ife = indirect_fields.end(); - ifi < ife; - ++ifi) - { - record_decl->addDecl(*ifi); - } -} - -void -ClangASTType::SetIsPacked () -{ - clang::RecordDecl *record_decl = GetAsRecordDecl(); - - if (!record_decl) - return; - - record_decl->addAttr(clang::PackedAttr::CreateImplicit(*m_ast)); -} - -clang::VarDecl * -ClangASTType::AddVariableToRecordType (const char *name, - const ClangASTType &var_type, - AccessType access) -{ - clang::VarDecl *var_decl = nullptr; - - if (!IsValid() || !var_type.IsValid()) - return nullptr; - - clang::RecordDecl *record_decl = GetAsRecordDecl (); - if (record_decl) - { - var_decl = clang::VarDecl::Create (*m_ast, // ASTContext & - record_decl, // DeclContext * - clang::SourceLocation(), // clang::SourceLocation StartLoc - clang::SourceLocation(), // clang::SourceLocation IdLoc - name ? &m_ast->Idents.get(name) : nullptr, // clang::IdentifierInfo * - var_type.GetQualType(), // Variable clang::QualType - nullptr, // TypeSourceInfo * - clang::SC_Static); // StorageClass - if (var_decl) - { - var_decl->setAccess(ClangASTContext::ConvertAccessTypeToAccessSpecifier (access)); - record_decl->addDecl(var_decl); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(var_decl); -#endif - } - } - return var_decl; -} - - -clang::CXXMethodDecl * -ClangASTType::AddMethodToCXXRecordType (const char *name, - const ClangASTType &method_clang_type, - lldb::AccessType access, - bool is_virtual, - bool is_static, - bool is_inline, - bool is_explicit, - bool is_attr_used, - bool is_artificial) -{ - if (!IsValid() || !method_clang_type.IsValid() || name == nullptr || name[0] == '\0') - return nullptr; - - clang::QualType record_qual_type(GetCanonicalQualType()); - - clang::CXXRecordDecl *cxx_record_decl = record_qual_type->getAsCXXRecordDecl(); - - if (cxx_record_decl == nullptr) - return nullptr; - - clang::QualType method_qual_type (method_clang_type.GetQualType()); - - clang::CXXMethodDecl *cxx_method_decl = nullptr; - - clang::DeclarationName decl_name (&m_ast->Idents.get(name)); - - const clang::FunctionType *function_type = llvm::dyn_cast(method_qual_type.getTypePtr()); - - if (function_type == nullptr) - return nullptr; - - const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast(function_type)); - - if (!method_function_prototype) - return nullptr; - - unsigned int num_params = method_function_prototype->getNumParams(); - - clang::CXXDestructorDecl *cxx_dtor_decl(nullptr); - clang::CXXConstructorDecl *cxx_ctor_decl(nullptr); - - if (is_artificial) - return nullptr; // skip everything artificial - - if (name[0] == '~') - { - cxx_dtor_decl = clang::CXXDestructorDecl::Create (*m_ast, - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXDestructorName (m_ast->getCanonicalType (record_qual_type)), clang::SourceLocation()), - method_qual_type, - nullptr, - is_inline, - is_artificial); - cxx_method_decl = cxx_dtor_decl; - } - else if (decl_name == cxx_record_decl->getDeclName()) - { - cxx_ctor_decl = clang::CXXConstructorDecl::Create (*m_ast, - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXConstructorName (m_ast->getCanonicalType (record_qual_type)), clang::SourceLocation()), - method_qual_type, - nullptr, // TypeSourceInfo * - is_explicit, - is_inline, - is_artificial, - false /*is_constexpr*/); - cxx_method_decl = cxx_ctor_decl; - } - else - { - clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None; - clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS; - - if (IsOperator (name, op_kind)) - { - if (op_kind != clang::NUM_OVERLOADED_OPERATORS) - { - // Check the number of operator parameters. Sometimes we have - // seen bad DWARF that doesn't correctly describe operators and - // if we try to create a method and add it to the class, clang - // will assert and crash, so we need to make sure things are - // acceptable. - if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount (op_kind, num_params)) - return nullptr; - cxx_method_decl = clang::CXXMethodDecl::Create (*m_ast, - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXOperatorName (op_kind), clang::SourceLocation()), - method_qual_type, - nullptr, // TypeSourceInfo * - SC, - is_inline, - false /*is_constexpr*/, - clang::SourceLocation()); - } - else if (num_params == 0) - { - // Conversion operators don't take params... - cxx_method_decl = clang::CXXConversionDecl::Create (*m_ast, - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXConversionFunctionName (m_ast->getCanonicalType (function_type->getReturnType())), clang::SourceLocation()), - method_qual_type, - nullptr, // TypeSourceInfo * - is_inline, - is_explicit, - false /*is_constexpr*/, - clang::SourceLocation()); - } - } - - if (cxx_method_decl == nullptr) - { - cxx_method_decl = clang::CXXMethodDecl::Create (*m_ast, - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (decl_name, clang::SourceLocation()), - method_qual_type, - nullptr, // TypeSourceInfo * - SC, - is_inline, - false /*is_constexpr*/, - clang::SourceLocation()); - } - } - - clang::AccessSpecifier access_specifier = ClangASTContext::ConvertAccessTypeToAccessSpecifier (access); - - cxx_method_decl->setAccess (access_specifier); - cxx_method_decl->setVirtualAsWritten (is_virtual); - - if (is_attr_used) - cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*m_ast)); - - // Populate the method decl with parameter decls - - llvm::SmallVector params; - - for (unsigned param_index = 0; - param_index < num_params; - ++param_index) - { - params.push_back (clang::ParmVarDecl::Create (*m_ast, - cxx_method_decl, - clang::SourceLocation(), - clang::SourceLocation(), - nullptr, // anonymous - method_function_prototype->getParamType(param_index), - nullptr, - clang::SC_None, - nullptr)); - } - - cxx_method_decl->setParams (llvm::ArrayRef(params)); - - cxx_record_decl->addDecl (cxx_method_decl); - - // Sometimes the debug info will mention a constructor (default/copy/move), - // destructor, or assignment operator (copy/move) but there won't be any - // version of this in the code. So we check if the function was artificially - // generated and if it is trivial and this lets the compiler/backend know - // that it can inline the IR for these when it needs to and we can avoid a - // "missing function" error when running expressions. - - if (is_artificial) - { - if (cxx_ctor_decl && - ((cxx_ctor_decl->isDefaultConstructor() && cxx_record_decl->hasTrivialDefaultConstructor ()) || - (cxx_ctor_decl->isCopyConstructor() && cxx_record_decl->hasTrivialCopyConstructor ()) || - (cxx_ctor_decl->isMoveConstructor() && cxx_record_decl->hasTrivialMoveConstructor ()) )) - { - cxx_ctor_decl->setDefaulted(); - cxx_ctor_decl->setTrivial(true); - } - else if (cxx_dtor_decl) - { - if (cxx_record_decl->hasTrivialDestructor()) - { - cxx_dtor_decl->setDefaulted(); - cxx_dtor_decl->setTrivial(true); - } - } - else if ((cxx_method_decl->isCopyAssignmentOperator() && cxx_record_decl->hasTrivialCopyAssignment()) || - (cxx_method_decl->isMoveAssignmentOperator() && cxx_record_decl->hasTrivialMoveAssignment())) - { - cxx_method_decl->setDefaulted(); - cxx_method_decl->setTrivial(true); - } - } - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(cxx_method_decl); -#endif - - // printf ("decl->isPolymorphic() = %i\n", cxx_record_decl->isPolymorphic()); - // printf ("decl->isAggregate() = %i\n", cxx_record_decl->isAggregate()); - // printf ("decl->isPOD() = %i\n", cxx_record_decl->isPOD()); - // printf ("decl->isEmpty() = %i\n", cxx_record_decl->isEmpty()); - // printf ("decl->isAbstract() = %i\n", cxx_record_decl->isAbstract()); - // printf ("decl->hasTrivialConstructor() = %i\n", cxx_record_decl->hasTrivialConstructor()); - // printf ("decl->hasTrivialCopyConstructor() = %i\n", cxx_record_decl->hasTrivialCopyConstructor()); - // printf ("decl->hasTrivialCopyAssignment() = %i\n", cxx_record_decl->hasTrivialCopyAssignment()); - // printf ("decl->hasTrivialDestructor() = %i\n", cxx_record_decl->hasTrivialDestructor()); - return cxx_method_decl; -} - - -#pragma mark C++ Base Classes - -clang::CXXBaseSpecifier * -ClangASTType::CreateBaseClassSpecifier (AccessType access, bool is_virtual, bool base_of_class) -{ - if (IsValid()) - return new clang::CXXBaseSpecifier (clang::SourceRange(), - is_virtual, - base_of_class, - ClangASTContext::ConvertAccessTypeToAccessSpecifier (access), - m_ast->getTrivialTypeSourceInfo (GetQualType()), - clang::SourceLocation()); - return nullptr; -} - -void -ClangASTType::DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, unsigned num_base_classes) -{ - for (unsigned i=0; isetBases(base_classes, num_base_classes); - return true; - } - } - return false; -} - -bool -ClangASTType::SetObjCSuperClass (const ClangASTType &superclass_clang_type) -{ - if (IsValid() && superclass_clang_type.IsValid()) - { - clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (); - clang::ObjCInterfaceDecl *super_interface_decl = superclass_clang_type.GetAsObjCInterfaceDecl (); - if (class_interface_decl && super_interface_decl) - { - - class_interface_decl->setSuperClass( - m_ast->getTrivialTypeSourceInfo(m_ast->getObjCInterfaceType(super_interface_decl))); - return true; - } - } - return false; -} - -bool -ClangASTType::AddObjCClassProperty (const char *property_name, - const ClangASTType &property_clang_type, - clang::ObjCIvarDecl *ivar_decl, - const char *property_setter_name, - const char *property_getter_name, - uint32_t property_attributes, - ClangASTMetadata *metadata) -{ - if (!IsValid() || !property_clang_type.IsValid() || property_name == nullptr || property_name[0] == '\0') - return false; - - clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (); - - if (class_interface_decl) - { - ClangASTType property_clang_type_to_access; - - if (property_clang_type.IsValid()) - property_clang_type_to_access = property_clang_type; - else if (ivar_decl) - property_clang_type_to_access = ClangASTType (m_ast, ivar_decl->getType()); - - if (class_interface_decl && property_clang_type_to_access.IsValid()) - { - clang::TypeSourceInfo *prop_type_source; - if (ivar_decl) - prop_type_source = m_ast->getTrivialTypeSourceInfo (ivar_decl->getType()); - else - prop_type_source = m_ast->getTrivialTypeSourceInfo (property_clang_type.GetQualType()); - - clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create (*m_ast, - class_interface_decl, - clang::SourceLocation(), // Source Location - &m_ast->Idents.get(property_name), - clang::SourceLocation(), //Source Location for AT - clang::SourceLocation(), //Source location for ( - ivar_decl ? ivar_decl->getType() : property_clang_type.GetQualType(), - prop_type_source); - - if (property_decl) - { - if (metadata) - ClangASTContext::SetMetadata(m_ast, property_decl, *metadata); - - class_interface_decl->addDecl (property_decl); - - clang::Selector setter_sel, getter_sel; - - if (property_setter_name != nullptr) - { - std::string property_setter_no_colon(property_setter_name, strlen(property_setter_name) - 1); - clang::IdentifierInfo *setter_ident = &m_ast->Idents.get(property_setter_no_colon.c_str()); - setter_sel = m_ast->Selectors.getSelector(1, &setter_ident); - } - else if (!(property_attributes & DW_APPLE_PROPERTY_readonly)) - { - std::string setter_sel_string("set"); - setter_sel_string.push_back(::toupper(property_name[0])); - setter_sel_string.append(&property_name[1]); - clang::IdentifierInfo *setter_ident = &m_ast->Idents.get(setter_sel_string.c_str()); - setter_sel = m_ast->Selectors.getSelector(1, &setter_ident); - } - property_decl->setSetterName(setter_sel); - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_setter); - - if (property_getter_name != nullptr) - { - clang::IdentifierInfo *getter_ident = &m_ast->Idents.get(property_getter_name); - getter_sel = m_ast->Selectors.getSelector(0, &getter_ident); - } - else - { - clang::IdentifierInfo *getter_ident = &m_ast->Idents.get(property_name); - getter_sel = m_ast->Selectors.getSelector(0, &getter_ident); - } - property_decl->setGetterName(getter_sel); - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_getter); - - if (ivar_decl) - property_decl->setPropertyIvarDecl (ivar_decl); - - if (property_attributes & DW_APPLE_PROPERTY_readonly) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readonly); - if (property_attributes & DW_APPLE_PROPERTY_readwrite) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readwrite); - if (property_attributes & DW_APPLE_PROPERTY_assign) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_assign); - if (property_attributes & DW_APPLE_PROPERTY_retain) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_retain); - if (property_attributes & DW_APPLE_PROPERTY_copy) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_copy); - if (property_attributes & DW_APPLE_PROPERTY_nonatomic) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_nonatomic); - - if (!getter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(getter_sel)) - { - const bool isInstance = true; - const bool isVariadic = false; - const bool isSynthesized = false; - const bool isImplicitlyDeclared = true; - const bool isDefined = false; - const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None; - const bool HasRelatedResultType = false; - - clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create (*m_ast, - clang::SourceLocation(), - clang::SourceLocation(), - getter_sel, - property_clang_type_to_access.GetQualType(), - nullptr, - class_interface_decl, - isInstance, - isVariadic, - isSynthesized, - isImplicitlyDeclared, - isDefined, - impControl, - HasRelatedResultType); - - if (getter && metadata) - ClangASTContext::SetMetadata(m_ast, getter, *metadata); - - if (getter) - { - getter->setMethodParams(*m_ast, llvm::ArrayRef(), llvm::ArrayRef()); - - class_interface_decl->addDecl(getter); - } - } - - if (!setter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(setter_sel)) - { - clang::QualType result_type = m_ast->VoidTy; - - const bool isInstance = true; - const bool isVariadic = false; - const bool isSynthesized = false; - const bool isImplicitlyDeclared = true; - const bool isDefined = false; - const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None; - const bool HasRelatedResultType = false; - - clang::ObjCMethodDecl *setter = clang::ObjCMethodDecl::Create (*m_ast, - clang::SourceLocation(), - clang::SourceLocation(), - setter_sel, - result_type, - nullptr, - class_interface_decl, - isInstance, - isVariadic, - isSynthesized, - isImplicitlyDeclared, - isDefined, - impControl, - HasRelatedResultType); - - if (setter && metadata) - ClangASTContext::SetMetadata(m_ast, setter, *metadata); - - llvm::SmallVector params; - - params.push_back (clang::ParmVarDecl::Create (*m_ast, - setter, - clang::SourceLocation(), - clang::SourceLocation(), - nullptr, // anonymous - property_clang_type_to_access.GetQualType(), - nullptr, - clang::SC_Auto, - nullptr)); - - if (setter) - { - setter->setMethodParams(*m_ast, llvm::ArrayRef(params), llvm::ArrayRef()); - - class_interface_decl->addDecl(setter); - } - } - - return true; - } - } - } - return false; -} - -bool -ClangASTType::IsObjCClassTypeAndHasIVars (bool check_superclass) const -{ - clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (); - if (class_interface_decl) - return ObjCDeclHasIVars (class_interface_decl, check_superclass); - return false; -} - - -clang::ObjCMethodDecl * -ClangASTType::AddMethodToObjCObjectType (const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]") - const ClangASTType &method_clang_type, - lldb::AccessType access, - bool is_artificial) -{ - if (!IsValid() || !method_clang_type.IsValid()) - return nullptr; - - clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(); - - if (class_interface_decl == nullptr) - return nullptr; - - const char *selector_start = ::strchr (name, ' '); - if (selector_start == nullptr) - return nullptr; - - selector_start++; - llvm::SmallVector selector_idents; - - size_t len = 0; - const char *start; - //printf ("name = '%s'\n", name); - - unsigned num_selectors_with_args = 0; - for (start = selector_start; - start && *start != '\0' && *start != ']'; - start += len) - { - len = ::strcspn(start, ":]"); - bool has_arg = (start[len] == ':'); - if (has_arg) - ++num_selectors_with_args; - selector_idents.push_back (&m_ast->Idents.get (llvm::StringRef (start, len))); - if (has_arg) - len += 1; - } - - - if (selector_idents.size() == 0) - return nullptr; - - clang::Selector method_selector = m_ast->Selectors.getSelector (num_selectors_with_args ? selector_idents.size() : 0, - selector_idents.data()); - - clang::QualType method_qual_type (method_clang_type.GetQualType()); - - // Populate the method decl with parameter decls - const clang::Type *method_type(method_qual_type.getTypePtr()); - - if (method_type == nullptr) - return nullptr; - - const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast(method_type)); - - if (!method_function_prototype) - return nullptr; - - - bool is_variadic = false; - bool is_synthesized = false; - bool is_defined = false; - clang::ObjCMethodDecl::ImplementationControl imp_control = clang::ObjCMethodDecl::None; - - const unsigned num_args = method_function_prototype->getNumParams(); - - if (num_args != num_selectors_with_args) - return nullptr; // some debug information is corrupt. We are not going to deal with it. - - clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create (*m_ast, - clang::SourceLocation(), // beginLoc, - clang::SourceLocation(), // endLoc, - method_selector, - method_function_prototype->getReturnType(), - nullptr, // TypeSourceInfo *ResultTInfo, - GetDeclContextForType (), - name[0] == '-', - is_variadic, - is_synthesized, - true, // is_implicitly_declared; we force this to true because we don't have source locations - is_defined, - imp_control, - false /*has_related_result_type*/); - - - if (objc_method_decl == nullptr) - return nullptr; - - if (num_args > 0) - { - llvm::SmallVector params; - - for (unsigned param_index = 0; param_index < num_args; ++param_index) - { - params.push_back (clang::ParmVarDecl::Create (*m_ast, - objc_method_decl, - clang::SourceLocation(), - clang::SourceLocation(), - nullptr, // anonymous - method_function_prototype->getParamType(param_index), - nullptr, - clang::SC_Auto, - nullptr)); - } - - objc_method_decl->setMethodParams(*m_ast, llvm::ArrayRef(params), llvm::ArrayRef()); - } - - class_interface_decl->addDecl (objc_method_decl); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(objc_method_decl); -#endif - - return objc_method_decl; -} - - -clang::DeclContext * -ClangASTType::GetDeclContextForType () const -{ - if (!IsValid()) - return nullptr; - - clang::QualType qual_type(GetCanonicalQualType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::UnaryTransform: break; - case clang::Type::FunctionNoProto: break; - case clang::Type::FunctionProto: break; - case clang::Type::IncompleteArray: break; - case clang::Type::VariableArray: break; - case clang::Type::ConstantArray: break; - case clang::Type::DependentSizedArray: break; - case clang::Type::ExtVector: break; - case clang::Type::DependentSizedExtVector: break; - case clang::Type::Vector: break; - case clang::Type::Builtin: break; - case clang::Type::BlockPointer: break; - case clang::Type::Pointer: break; - case clang::Type::LValueReference: break; - case clang::Type::RValueReference: break; - case clang::Type::MemberPointer: break; - case clang::Type::Complex: break; - case clang::Type::ObjCObject: break; - case clang::Type::ObjCInterface: return llvm::cast(qual_type.getTypePtr())->getInterface(); - case clang::Type::ObjCObjectPointer: return ClangASTType (m_ast, llvm::cast(qual_type.getTypePtr())->getPointeeType()).GetDeclContextForType(); - case clang::Type::Record: return llvm::cast(qual_type)->getDecl(); - case clang::Type::Enum: return llvm::cast(qual_type)->getDecl(); - case clang::Type::Typedef: return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetDeclContextForType(); - case clang::Type::Elaborated: return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetDeclContextForType(); - case clang::Type::Paren: return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetDeclContextForType(); - case clang::Type::TypeOfExpr: break; - case clang::Type::TypeOf: break; - case clang::Type::Decltype: break; - //case clang::Type::QualifiedName: break; - case clang::Type::TemplateSpecialization: break; - case clang::Type::DependentTemplateSpecialization: break; - case clang::Type::TemplateTypeParm: break; - case clang::Type::SubstTemplateTypeParm: break; - case clang::Type::SubstTemplateTypeParmPack:break; - case clang::Type::PackExpansion: break; - case clang::Type::UnresolvedUsing: break; - case clang::Type::Attributed: break; - case clang::Type::Auto: break; - case clang::Type::InjectedClassName: break; - case clang::Type::DependentName: break; - case clang::Type::Atomic: break; - case clang::Type::Adjusted: break; - - // pointer type decayed from an array or function type. - case clang::Type::Decayed: break; - } - // No DeclContext in this type... - return nullptr; -} - -bool -ClangASTType::SetDefaultAccessForRecordFields (int default_accessibility, - int *assigned_accessibilities, - size_t num_assigned_accessibilities) -{ - if (IsValid()) - { - clang::RecordDecl *record_decl = GetAsRecordDecl(); - if (record_decl) - { - uint32_t field_idx; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(), field_idx = 0; - field != field_end; - ++field, ++field_idx) - { - // If no accessibility was assigned, assign the correct one - if (field_idx < num_assigned_accessibilities && assigned_accessibilities[field_idx] == clang::AS_none) - field->setAccess ((clang::AccessSpecifier)default_accessibility); - } - return true; - } - } - return false; -} - - -bool -ClangASTType::SetHasExternalStorage (bool has_extern) -{ - if (!IsValid()) - return false; - - clang::QualType qual_type (GetCanonicalQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - cxx_record_decl->setHasExternalLexicalStorage (has_extern); - cxx_record_decl->setHasExternalVisibleStorage (has_extern); - return true; - } - } - break; - - case clang::Type::Enum: - { - clang::EnumDecl *enum_decl = llvm::cast(qual_type)->getDecl(); - if (enum_decl) - { - enum_decl->setHasExternalLexicalStorage (has_extern); - enum_decl->setHasExternalVisibleStorage (has_extern); - return true; - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - class_interface_decl->setHasExternalLexicalStorage (has_extern); - class_interface_decl->setHasExternalVisibleStorage (has_extern); - return true; - } - } - } - break; - - case clang::Type::Typedef: - return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).SetHasExternalStorage (has_extern); - - case clang::Type::Elaborated: - return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).SetHasExternalStorage (has_extern); - - case clang::Type::Paren: - return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).SetHasExternalStorage (has_extern); - - default: - break; - } - return false; -} - -bool -ClangASTType::SetTagTypeKind (int kind) const -{ - if (IsValid()) - { - clang::QualType tag_qual_type(GetQualType()); - const clang::Type *clang_type = tag_qual_type.getTypePtr(); - if (clang_type) - { - const clang::TagType *tag_type = llvm::dyn_cast(clang_type); - if (tag_type) - { - clang::TagDecl *tag_decl = llvm::dyn_cast(tag_type->getDecl()); - if (tag_decl) - { - tag_decl->setTagKind ((clang::TagDecl::TagKind)kind); - return true; - } - } - } - } - return false; -} - - -#pragma mark TagDecl - -bool -ClangASTType::StartTagDeclarationDefinition () -{ - if (IsValid()) - { - clang::QualType qual_type (GetQualType()); - const clang::Type *t = qual_type.getTypePtr(); - if (t) - { - const clang::TagType *tag_type = llvm::dyn_cast(t); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - { - tag_decl->startDefinition(); - return true; - } - } - - const clang::ObjCObjectType *object_type = llvm::dyn_cast(t); - if (object_type) - { - clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface(); - if (interface_decl) - { - interface_decl->startDefinition(); - return true; - } - } - } - } - return false; -} - -bool -ClangASTType::CompleteTagDeclarationDefinition () -{ - if (IsValid()) - { - clang::QualType qual_type (GetQualType()); - - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - - if (cxx_record_decl) - { - cxx_record_decl->completeDefinition(); - - return true; - } - - const clang::EnumType *enum_type = llvm::dyn_cast(qual_type.getTypePtr()); - - if (enum_type) - { - clang::EnumDecl *enum_decl = enum_type->getDecl(); - - if (enum_decl) - { - /// TODO This really needs to be fixed. - - unsigned NumPositiveBits = 1; - unsigned NumNegativeBits = 0; - - clang::QualType promotion_qual_type; - // If the enum integer type is less than an integer in bit width, - // then we must promote it to an integer size. - if (m_ast->getTypeSize(enum_decl->getIntegerType()) < m_ast->getTypeSize(m_ast->IntTy)) - { - if (enum_decl->getIntegerType()->isSignedIntegerType()) - promotion_qual_type = m_ast->IntTy; - else - promotion_qual_type = m_ast->UnsignedIntTy; - } - else - promotion_qual_type = enum_decl->getIntegerType(); - - enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits); - return true; - } - } - } - return false; -} - - - - - - - -bool -ClangASTType::AddEnumerationValueToEnumerationType (const ClangASTType &enumerator_clang_type, - const Declaration &decl, - const char *name, - int64_t enum_value, - uint32_t enum_value_bit_size) -{ - if (IsValid() && enumerator_clang_type.IsValid() && name && name[0]) - { - clang::QualType enum_qual_type (GetCanonicalQualType()); - - bool is_signed = false; - enumerator_clang_type.IsIntegerType (is_signed); - const clang::Type *clang_type = enum_qual_type.getTypePtr(); - if (clang_type) - { - const clang::EnumType *enum_type = llvm::dyn_cast(clang_type); - - if (enum_type) - { - llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed); - enum_llvm_apsint = enum_value; - clang::EnumConstantDecl *enumerator_decl = - clang::EnumConstantDecl::Create (*m_ast, - enum_type->getDecl(), - clang::SourceLocation(), - name ? &m_ast->Idents.get(name) : nullptr, // Identifier - enumerator_clang_type.GetQualType(), - nullptr, - enum_llvm_apsint); - - if (enumerator_decl) - { - enum_type->getDecl()->addDecl(enumerator_decl); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(enumerator_decl); -#endif - - return true; - } - } - } - } - return false; -} - - -ClangASTType -ClangASTType::GetEnumerationIntegerType () const -{ - clang::QualType enum_qual_type (GetCanonicalQualType()); - const clang::Type *clang_type = enum_qual_type.getTypePtr(); - if (clang_type) - { - const clang::EnumType *enum_type = llvm::dyn_cast(clang_type); - if (enum_type) - { - clang::EnumDecl *enum_decl = enum_type->getDecl(); - if (enum_decl) - return ClangASTType (m_ast, enum_decl->getIntegerType()); - } - } - return ClangASTType(); -} - -ClangASTType -ClangASTType::CreateMemberPointerType (const ClangASTType &pointee_type) const -{ - if (IsValid() && pointee_type.IsValid()) - { - return ClangASTType (m_ast, m_ast->getMemberPointerType (pointee_type.GetQualType(), - GetQualType().getTypePtr())); - } - return ClangASTType(); -} - - -size_t -ClangASTType::ConvertStringToFloatValue (const char *s, uint8_t *dst, size_t dst_size) const -{ - if (IsValid()) - { - clang::QualType qual_type (GetCanonicalQualType()); - uint32_t count = 0; - bool is_complex = false; - if (IsFloatingPointType (count, is_complex)) - { - // TODO: handle complex and vector types - if (count != 1) - return false; - - llvm::StringRef s_sref(s); - llvm::APFloat ap_float(m_ast->getFloatTypeSemantics(qual_type), s_sref); - - const uint64_t bit_size = m_ast->getTypeSize (qual_type); - const uint64_t byte_size = bit_size / 8; - if (dst_size >= byte_size) - { - if (bit_size == sizeof(float)*8) - { - float float32 = ap_float.convertToFloat(); - ::memcpy (dst, &float32, byte_size); - return byte_size; - } - else if (bit_size >= 64) - { - llvm::APInt ap_int(ap_float.bitcastToAPInt()); - ::memcpy (dst, ap_int.getRawData(), byte_size); - return byte_size; - } - } - } - } - return 0; -} - - - -//---------------------------------------------------------------------- -// Dumping types -//---------------------------------------------------------------------- -#define DEPTH_INCREMENT 2 - -void -ClangASTType::DumpValue (ExecutionContext *exe_ctx, - Stream *s, - lldb::Format format, - const lldb_private::DataExtractor &data, - lldb::offset_t data_byte_offset, - size_t data_byte_size, - uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, - bool show_types, - bool show_summary, - bool verbose, - uint32_t depth) -{ - if (!IsValid()) - return; - - clang::QualType qual_type(GetQualType()); - switch (qual_type->getTypeClass()) - { - case clang::Type::Record: - if (GetCompleteType ()) - { - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - uint32_t field_bit_offset = 0; - uint32_t field_byte_offset = 0; - const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl); - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - if (cxx_record_decl) - { - // We might have base classes to print out first - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - const clang::CXXRecordDecl *base_class_decl = llvm::cast(base_class->getType()->getAs()->getDecl()); - - // Skip empty base classes - if (verbose == false && ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - - if (base_class->isVirtual()) - field_bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; - else - field_bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; - field_byte_offset = field_bit_offset / 8; - assert (field_bit_offset % 8 == 0); - if (child_idx == 0) - s->PutChar('{'); - else - s->PutChar(','); - - clang::QualType base_class_qual_type = base_class->getType(); - std::string base_class_type_name(base_class_qual_type.getAsString()); - - // Indent and print the base class type name - s->Printf("\n%*s%s ", depth + DEPTH_INCREMENT, "", base_class_type_name.c_str()); - - clang::TypeInfo base_class_type_info = m_ast->getTypeInfo(base_class_qual_type); - - // Dump the value of the member - ClangASTType base_clang_type(m_ast, base_class_qual_type); - base_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - base_clang_type.GetFormat(), // The format with which to display the member - data, // Data buffer containing all bytes for this type - data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from - base_class_type_info.Width / 8, // Size of this type in bytes - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have children - - ++child_idx; - } - } - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx) - { - // Print the starting squiggly bracket (if this is the - // first member) or comma (for member 2 and beyond) for - // the struct/union/class member. - if (child_idx == 0) - s->PutChar('{'); - else - s->PutChar(','); - - // Indent - s->Printf("\n%*s", depth + DEPTH_INCREMENT, ""); - - clang::QualType field_type = field->getType(); - // Print the member type if requested - // Figure out the type byte size (field_type_info.first) and - // alignment (field_type_info.second) from the AST context. - clang::TypeInfo field_type_info = m_ast->getTypeInfo(field_type); - assert(field_idx < record_layout.getFieldCount()); - // Figure out the field offset within the current struct/union/class type - field_bit_offset = record_layout.getFieldOffset (field_idx); - field_byte_offset = field_bit_offset / 8; - uint32_t field_bitfield_bit_size = 0; - uint32_t field_bitfield_bit_offset = 0; - if (ClangASTContext::FieldIsBitfield (m_ast, *field, field_bitfield_bit_size)) - field_bitfield_bit_offset = field_bit_offset % 8; - - if (show_types) - { - std::string field_type_name(field_type.getAsString()); - if (field_bitfield_bit_size > 0) - s->Printf("(%s:%u) ", field_type_name.c_str(), field_bitfield_bit_size); - else - s->Printf("(%s) ", field_type_name.c_str()); - } - // Print the member name and equal sign - s->Printf("%s = ", field->getNameAsString().c_str()); - - - // Dump the value of the member - ClangASTType field_clang_type (m_ast, field_type); - field_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - field_clang_type.GetFormat(), // The format with which to display the member - data, // Data buffer containing all bytes for this type - data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from - field_type_info.Width / 8, // Size of this type in bytes - field_bitfield_bit_size, // Bitfield bit size - field_bitfield_bit_offset, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have children - } - - // Indent the trailing squiggly bracket - if (child_idx > 0) - s->Printf("\n%*s}", depth, ""); - } - return; - - case clang::Type::Enum: - if (GetCompleteType ()) - { - const clang::EnumType *enum_type = llvm::cast(qual_type.getTypePtr()); - const clang::EnumDecl *enum_decl = enum_type->getDecl(); - assert(enum_decl); - clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; - lldb::offset_t offset = data_byte_offset; - const int64_t enum_value = data.GetMaxU64Bitfield(&offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset); - for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) - { - if (enum_pos->getInitVal() == enum_value) - { - s->Printf("%s", enum_pos->getNameAsString().c_str()); - return; - } - } - // If we have gotten here we didn't get find the enumerator in the - // enum decl, so just print the integer. - s->Printf("%" PRIi64, enum_value); - } - return; - - case clang::Type::ConstantArray: - { - const clang::ConstantArrayType *array = llvm::cast(qual_type.getTypePtr()); - bool is_array_of_characters = false; - clang::QualType element_qual_type = array->getElementType(); - - const clang::Type *canonical_type = element_qual_type->getCanonicalTypeInternal().getTypePtr(); - if (canonical_type) - is_array_of_characters = canonical_type->isCharType(); - - const uint64_t element_count = array->getSize().getLimitedValue(); - - clang::TypeInfo field_type_info = m_ast->getTypeInfo(element_qual_type); - - uint32_t element_idx = 0; - uint32_t element_offset = 0; - uint64_t element_byte_size = field_type_info.Width / 8; - uint32_t element_stride = element_byte_size; - - if (is_array_of_characters) - { - s->PutChar('"'); - data.Dump(s, data_byte_offset, lldb::eFormatChar, element_byte_size, element_count, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('"'); - return; - } - else - { - ClangASTType element_clang_type(m_ast, element_qual_type); - lldb::Format element_format = element_clang_type.GetFormat(); - - for (element_idx = 0; element_idx < element_count; ++element_idx) - { - // Print the starting squiggly bracket (if this is the - // first member) or comma (for member 2 and beyond) for - // the struct/union/class member. - if (element_idx == 0) - s->PutChar('{'); - else - s->PutChar(','); - - // Indent and print the index - s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx); + std::vector& child_indexes) const +{ + if (IsValid() && name && name[0]) + { + return m_type_system->GetIndexOfChildMemberWithName(m_type, name, omit_empty_base_classes, child_indexes); + } + return 0; +} - // Figure out the field offset within the current struct/union/class type - element_offset = element_idx * element_stride; - // Dump the value of the member - element_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - element_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset + element_offset,// Offset into "data" where to grab value from - element_byte_size, // Size of this type in bytes - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have children - } +// Get the index of the child of "clang_type" whose name matches. This function +// doesn't descend into the children, but only looks one level deep and name +// matches can include base class names. - // Indent the trailing squiggly bracket - if (element_idx > 0) - s->Printf("\n%*s}", depth, ""); - } - } - return; +uint32_t +ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_classes) const +{ + if (IsValid() && name && name[0]) + return m_type_system->GetIndexOfChildWithName(m_type, name, omit_empty_base_classes); + return UINT32_MAX; +} - case clang::Type::Typedef: - { - clang::QualType typedef_qual_type = llvm::cast(qual_type)->getDecl()->getUnderlyingType(); - - ClangASTType typedef_clang_type (m_ast, typedef_qual_type); - lldb::Format typedef_format = typedef_clang_type.GetFormat(); - clang::TypeInfo typedef_type_info = m_ast->getTypeInfo(typedef_qual_type); - uint64_t typedef_byte_size = typedef_type_info.Width / 8; +#pragma mark TagDecl - return typedef_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - typedef_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - typedef_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset,// Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children - } - break; - case clang::Type::Elaborated: - { - clang::QualType elaborated_qual_type = llvm::cast(qual_type)->getNamedType(); - ClangASTType elaborated_clang_type (m_ast, elaborated_qual_type); - lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); - clang::TypeInfo elaborated_type_info = m_ast->getTypeInfo(elaborated_qual_type); - uint64_t elaborated_byte_size = elaborated_type_info.Width / 8; +size_t +ClangASTType::ConvertStringToFloatValue (const char *s, uint8_t *dst, size_t dst_size) const +{ + if (IsValid()) + return m_type_system->ConvertStringToFloatValue(m_type, s, dst, dst_size); + return 0; +} - return elaborated_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - elaborated_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - elaborated_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset,// Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children - } - break; - - case clang::Type::Paren: - { - clang::QualType desugar_qual_type = llvm::cast(qual_type)->desugar(); - ClangASTType desugar_clang_type (m_ast, desugar_qual_type); - lldb::Format desugar_format = desugar_clang_type.GetFormat(); - clang::TypeInfo desugar_type_info = m_ast->getTypeInfo(desugar_qual_type); - uint64_t desugar_byte_size = desugar_type_info.Width / 8; - - return desugar_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - desugar_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - desugar_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset,// Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children - } - break; - default: - // We are down to a scalar type that we just need to display. - data.Dump(s, - data_byte_offset, - format, - data_byte_size, - 1, - UINT32_MAX, - LLDB_INVALID_ADDRESS, - bitfield_bit_size, - bitfield_bit_offset); +//---------------------------------------------------------------------- +// Dumping types +//---------------------------------------------------------------------- - if (show_summary) - DumpSummary (exe_ctx, s, data, data_byte_offset, data_byte_size); - break; - } +void +ClangASTType::DumpValue (ExecutionContext *exe_ctx, + Stream *s, + lldb::Format format, + const lldb_private::DataExtractor &data, + lldb::offset_t data_byte_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool show_types, + bool show_summary, + bool verbose, + uint32_t depth) +{ + if (!IsValid()) + return; + m_type_system->DumpValue(m_type, exe_ctx, s, format, data, data_byte_offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset, show_types, show_summary, verbose, depth); } @@ -6420,152 +782,7 @@ { if (!IsValid()) return false; - if (IsAggregateType()) - { - return false; - } - else - { - clang::QualType qual_type(GetQualType()); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Typedef: - { - clang::QualType typedef_qual_type = llvm::cast(qual_type)->getDecl()->getUnderlyingType(); - ClangASTType typedef_clang_type (m_ast, typedef_qual_type); - if (format == eFormatDefault) - format = typedef_clang_type.GetFormat(); - clang::TypeInfo typedef_type_info = m_ast->getTypeInfo(typedef_qual_type); - uint64_t typedef_byte_size = typedef_type_info.Width / 8; - - return typedef_clang_type.DumpTypeValue (s, - format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - byte_offset, // Offset into "data" where to grab value from - typedef_byte_size, // Size of this type in bytes - bitfield_bit_size, // Size in bits of a bitfield value, if zero don't treat as a bitfield - bitfield_bit_offset, // Offset in bits of a bitfield value if bitfield_bit_size != 0 - exe_scope); - } - break; - - case clang::Type::Enum: - // If our format is enum or default, show the enumeration value as - // its enumeration string value, else just display it as requested. - if ((format == eFormatEnum || format == eFormatDefault) && GetCompleteType ()) - { - const clang::EnumType *enum_type = llvm::cast(qual_type.getTypePtr()); - const clang::EnumDecl *enum_decl = enum_type->getDecl(); - assert(enum_decl); - clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; - const bool is_signed = qual_type->isSignedIntegerOrEnumerationType(); - lldb::offset_t offset = byte_offset; - if (is_signed) - { - const int64_t enum_svalue = data.GetMaxS64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset); - for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) - { - if (enum_pos->getInitVal().getSExtValue() == enum_svalue) - { - s->PutCString (enum_pos->getNameAsString().c_str()); - return true; - } - } - // If we have gotten here we didn't get find the enumerator in the - // enum decl, so just print the integer. - s->Printf("%" PRIi64, enum_svalue); - } - else - { - const uint64_t enum_uvalue = data.GetMaxU64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset); - for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) - { - if (enum_pos->getInitVal().getZExtValue() == enum_uvalue) - { - s->PutCString (enum_pos->getNameAsString().c_str()); - return true; - } - } - // If we have gotten here we didn't get find the enumerator in the - // enum decl, so just print the integer. - s->Printf("%" PRIu64, enum_uvalue); - } - return true; - } - // format was not enum, just fall through and dump the value as requested.... - - default: - // We are down to a scalar type that we just need to display. - { - uint32_t item_count = 1; - // A few formats, we might need to modify our size and count for depending - // on how we are trying to display the value... - switch (format) - { - default: - case eFormatBoolean: - case eFormatBinary: - case eFormatComplex: - case eFormatCString: // NULL terminated C strings - case eFormatDecimal: - case eFormatEnum: - case eFormatHex: - case eFormatHexUppercase: - case eFormatFloat: - case eFormatOctal: - case eFormatOSType: - case eFormatUnsigned: - case eFormatPointer: - case eFormatVectorOfChar: - case eFormatVectorOfSInt8: - case eFormatVectorOfUInt8: - case eFormatVectorOfSInt16: - case eFormatVectorOfUInt16: - case eFormatVectorOfSInt32: - case eFormatVectorOfUInt32: - case eFormatVectorOfSInt64: - case eFormatVectorOfUInt64: - case eFormatVectorOfFloat32: - case eFormatVectorOfFloat64: - case eFormatVectorOfUInt128: - break; - - case eFormatChar: - case eFormatCharPrintable: - case eFormatCharArray: - case eFormatBytes: - case eFormatBytesWithASCII: - item_count = byte_size; - byte_size = 1; - break; - - case eFormatUnicode16: - item_count = byte_size / 2; - byte_size = 2; - break; - - case eFormatUnicode32: - item_count = byte_size / 4; - byte_size = 4; - break; - } - return data.Dump (s, - byte_offset, - format, - byte_size, - item_count, - UINT32_MAX, - LLDB_INVALID_ADDRESS, - bitfield_bit_size, - bitfield_bit_offset, - exe_scope); - } - break; - } - } - return 0; + return m_type_system->DumpTypeValue(m_type, s, format, data, byte_offset, byte_size, bitfield_bit_size, bitfield_bit_offset, exe_scope); } @@ -6577,57 +794,15 @@ lldb::offset_t data_byte_offset, size_t data_byte_size) { - uint32_t length = 0; - if (IsCStringType (length)) - { - if (exe_ctx) - { - Process *process = exe_ctx->GetProcessPtr(); - if (process) - { - lldb::offset_t offset = data_byte_offset; - lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size); - std::vector buf; - if (length > 0) - buf.resize (length); - else - buf.resize (256); - - lldb_private::DataExtractor cstr_data(&buf.front(), buf.size(), process->GetByteOrder(), 4); - buf.back() = '\0'; - size_t bytes_read; - size_t total_cstr_len = 0; - Error error; - while ((bytes_read = process->ReadMemory (pointer_address, &buf.front(), buf.size(), error)) > 0) - { - const size_t len = strlen((const char *)&buf.front()); - if (len == 0) - break; - if (total_cstr_len == 0) - s->PutCString (" \""); - cstr_data.Dump(s, 0, lldb::eFormatChar, 1, len, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); - total_cstr_len += len; - if (len < buf.size()) - break; - pointer_address += total_cstr_len; - } - if (total_cstr_len > 0) - s->PutChar ('"'); - } - } - } + if (IsValid()) + m_type_system->DumpSummary(m_type, exe_ctx, s, data, data_byte_offset, data_byte_size); } void ClangASTType::DumpTypeDescription () const { - StreamFile s (stdout, false); - DumpTypeDescription (&s); - ClangASTMetadata *metadata = ClangASTContext::GetMetadata (m_ast, m_type); - if (metadata) - { - metadata->Dump (&s); - } + if (IsValid()) + m_type_system->DumpTypeDescription(m_type); } void @@ -6635,95 +810,7 @@ { if (IsValid()) { - clang::QualType qual_type(GetQualType()); - - llvm::SmallVector buf; - llvm::raw_svector_ostream llvm_ostrm (buf); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - GetCompleteType (); - - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl) - { - clang::PrintingPolicy policy = m_ast->getPrintingPolicy(); - class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel()); - } - } - } - break; - - case clang::Type::Typedef: - { - const clang::TypedefType *typedef_type = qual_type->getAs(); - if (typedef_type) - { - const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); - std::string clang_typedef_name (typedef_decl->getQualifiedNameAsString()); - if (!clang_typedef_name.empty()) - { - s->PutCString ("typedef "); - s->PutCString (clang_typedef_name.c_str()); - } - } - } - break; - - case clang::Type::Elaborated: - ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).DumpTypeDescription(s); - return; - - case clang::Type::Paren: - ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).DumpTypeDescription(s); - return; - - case clang::Type::Record: - { - GetCompleteType (); - - const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); - - if (cxx_record_decl) - cxx_record_decl->print(llvm_ostrm, m_ast->getPrintingPolicy(), s->GetIndentLevel()); - else - record_decl->print(llvm_ostrm, m_ast->getPrintingPolicy(), s->GetIndentLevel()); - } - break; - - default: - { - const clang::TagType *tag_type = llvm::dyn_cast(qual_type.getTypePtr()); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - tag_decl->print(llvm_ostrm, 0); - } - else - { - std::string clang_type_name(qual_type.getAsString()); - if (!clang_type_name.empty()) - s->PutCString (clang_type_name.c_str()); - } - } - } - - llvm_ostrm.flush(); - if (buf.size() > 0) - { - s->Write (buf.data(), buf.size()); - } + m_type_system->DumpTypeDescription(m_type, s); } } @@ -6735,7 +822,7 @@ { if (!IsValid()) return false; - + if (IsAggregateType ()) { return false; // Aggregate types don't have scalar values @@ -6744,120 +831,120 @@ { uint64_t count = 0; lldb::Encoding encoding = GetEncoding (count); - + if (encoding == lldb::eEncodingInvalid || count != 1) return false; - + const uint64_t byte_size = GetByteSize(nullptr); lldb::offset_t offset = data_byte_offset; switch (encoding) { - case lldb::eEncodingInvalid: - break; - case lldb::eEncodingVector: - break; - case lldb::eEncodingUint: - if (byte_size <= sizeof(unsigned long long)) - { - uint64_t uval64 = data.GetMaxU64 (&offset, byte_size); - if (byte_size <= sizeof(unsigned int)) - { - value = (unsigned int)uval64; - return true; - } - else if (byte_size <= sizeof(unsigned long)) - { - value = (unsigned long)uval64; - return true; - } - else if (byte_size <= sizeof(unsigned long long)) - { - value = (unsigned long long )uval64; - return true; - } - else - value.Clear(); - } - break; - - case lldb::eEncodingSint: - if (byte_size <= sizeof(long long)) - { - int64_t sval64 = data.GetMaxS64 (&offset, byte_size); - if (byte_size <= sizeof(int)) - { - value = (int)sval64; - return true; - } - else if (byte_size <= sizeof(long)) - { - value = (long)sval64; - return true; - } - else if (byte_size <= sizeof(long long)) - { - value = (long long )sval64; - return true; - } - else - value.Clear(); - } - break; - - case lldb::eEncodingIEEE754: - if (byte_size <= sizeof(long double)) - { - uint32_t u32; - uint64_t u64; - if (byte_size == sizeof(float)) + case lldb::eEncodingInvalid: + break; + case lldb::eEncodingVector: + break; + case lldb::eEncodingUint: + if (byte_size <= sizeof(unsigned long long)) { - if (sizeof(float) == sizeof(uint32_t)) + uint64_t uval64 = data.GetMaxU64 (&offset, byte_size); + if (byte_size <= sizeof(unsigned int)) { - u32 = data.GetU32(&offset); - value = *((float *)&u32); + value = (unsigned int)uval64; return true; } - else if (sizeof(float) == sizeof(uint64_t)) + else if (byte_size <= sizeof(unsigned long)) { - u64 = data.GetU64(&offset); - value = *((float *)&u64); + value = (unsigned long)uval64; return true; } + else if (byte_size <= sizeof(unsigned long long)) + { + value = (unsigned long long )uval64; + return true; + } + else + value.Clear(); } - else - if (byte_size == sizeof(double)) + break; + + case lldb::eEncodingSint: + if (byte_size <= sizeof(long long)) { - if (sizeof(double) == sizeof(uint32_t)) + int64_t sval64 = data.GetMaxS64 (&offset, byte_size); + if (byte_size <= sizeof(int)) { - u32 = data.GetU32(&offset); - value = *((double *)&u32); + value = (int)sval64; return true; } - else if (sizeof(double) == sizeof(uint64_t)) + else if (byte_size <= sizeof(long)) { - u64 = data.GetU64(&offset); - value = *((double *)&u64); + value = (long)sval64; return true; } - } - else - if (byte_size == sizeof(long double)) - { - if (sizeof(long double) == sizeof(uint32_t)) + else if (byte_size <= sizeof(long long)) { - u32 = data.GetU32(&offset); - value = *((long double *)&u32); + value = (long long )sval64; return true; } - else if (sizeof(long double) == sizeof(uint64_t)) + else + value.Clear(); + } + break; + + case lldb::eEncodingIEEE754: + if (byte_size <= sizeof(long double)) + { + uint32_t u32; + uint64_t u64; + if (byte_size == sizeof(float)) { - u64 = data.GetU64(&offset); - value = *((long double *)&u64); - return true; + if (sizeof(float) == sizeof(uint32_t)) + { + u32 = data.GetU32(&offset); + value = *((float *)&u32); + return true; + } + else if (sizeof(float) == sizeof(uint64_t)) + { + u64 = data.GetU64(&offset); + value = *((float *)&u64); + return true; + } } + else + if (byte_size == sizeof(double)) + { + if (sizeof(double) == sizeof(uint32_t)) + { + u32 = data.GetU32(&offset); + value = *((double *)&u32); + return true; + } + else if (sizeof(double) == sizeof(uint64_t)) + { + u64 = data.GetU64(&offset); + value = *((double *)&u64); + return true; + } + } + else + if (byte_size == sizeof(long double)) + { + if (sizeof(long double) == sizeof(uint32_t)) + { + u32 = data.GetU32(&offset); + value = *((long double *)&u32); + return true; + } + else if (sizeof(long double) == sizeof(uint64_t)) + { + u64 = data.GetU64(&offset); + value = *((long double *)&u64); + return true; + } + } } - } - break; + break; } } return false; @@ -6866,74 +953,77 @@ bool ClangASTType::SetValueFromScalar (const Scalar &value, Stream &strm) { + if (!IsValid()) + return false; + // Aggregate types don't have scalar values if (!IsAggregateType ()) { strm.GetFlags().Set(Stream::eBinary); uint64_t count = 0; lldb::Encoding encoding = GetEncoding (count); - + if (encoding == lldb::eEncodingInvalid || count != 1) return false; - + const uint64_t bit_width = GetBitSize(nullptr); // This function doesn't currently handle non-byte aligned assignments if ((bit_width % 8) != 0) return false; - + const uint64_t byte_size = (bit_width + 7 ) / 8; switch (encoding) { - case lldb::eEncodingInvalid: - break; - case lldb::eEncodingVector: - break; - case lldb::eEncodingUint: - switch (byte_size) - { - case 1: strm.PutHex8(value.UInt()); return true; - case 2: strm.PutHex16(value.UInt()); return true; - case 4: strm.PutHex32(value.UInt()); return true; - case 8: strm.PutHex64(value.ULongLong()); return true; - default: + case lldb::eEncodingInvalid: break; - } - break; - - case lldb::eEncodingSint: - switch (byte_size) - { - case 1: strm.PutHex8(value.SInt()); return true; - case 2: strm.PutHex16(value.SInt()); return true; - case 4: strm.PutHex32(value.SInt()); return true; - case 8: strm.PutHex64(value.SLongLong()); return true; - default: + case lldb::eEncodingVector: break; + case lldb::eEncodingUint: + switch (byte_size) + { + case 1: strm.PutHex8(value.UInt()); return true; + case 2: strm.PutHex16(value.UInt()); return true; + case 4: strm.PutHex32(value.UInt()); return true; + case 8: strm.PutHex64(value.ULongLong()); return true; + default: + break; } - break; - - case lldb::eEncodingIEEE754: - if (byte_size <= sizeof(long double)) + break; + + case lldb::eEncodingSint: + switch (byte_size) { - if (byte_size == sizeof(float)) - { - strm.PutFloat(value.Float()); - return true; - } - else - if (byte_size == sizeof(double)) - { - strm.PutDouble(value.Double()); - return true; - } - else - if (byte_size == sizeof(long double)) + case 1: strm.PutHex8(value.SInt()); return true; + case 2: strm.PutHex16(value.SInt()); return true; + case 4: strm.PutHex32(value.SInt()); return true; + case 8: strm.PutHex64(value.SLongLong()); return true; + default: + break; + } + break; + + case lldb::eEncodingIEEE754: + if (byte_size <= sizeof(long double)) { - strm.PutDouble(value.LongDouble()); - return true; + if (byte_size == sizeof(float)) + { + strm.PutFloat(value.Float()); + return true; + } + else + if (byte_size == sizeof(double)) + { + strm.PutDouble(value.Double()); + return true; + } + else + if (byte_size == sizeof(long double)) + { + strm.PutDouble(value.LongDouble()); + return true; + } } - } - break; + break; } } return false; @@ -6947,7 +1037,7 @@ { if (!IsValid()) return false; - + // Can't convert a file address to anything valid without more // context (which Module it came from) if (address_type == eAddressTypeFile) @@ -6997,17 +1087,17 @@ { if (!IsValid()) return false; - + // Can't convert a file address to anything valid without more // context (which Module it came from) if (address_type == eAddressTypeFile) return false; - + if (!GetCompleteType()) return false; - + const uint64_t byte_size = GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - + if (byte_size > 0) { if (address_type == eAddressTypeHost) @@ -7031,7 +1121,6 @@ return false; } - //clang::CXXRecordDecl * //ClangASTType::GetAsCXXRecordDecl (lldb::clang_type_t opaque_clang_qual_type) //{ @@ -7043,14 +1132,14 @@ bool lldb_private::operator == (const lldb_private::ClangASTType &lhs, const lldb_private::ClangASTType &rhs) { - return lhs.GetASTContext() == rhs.GetASTContext() && lhs.GetOpaqueQualType() == rhs.GetOpaqueQualType(); + return lhs.GetTypeSystem() == rhs.GetTypeSystem() && lhs.GetOpaqueQualType() == rhs.GetOpaqueQualType(); } bool lldb_private::operator != (const lldb_private::ClangASTType &lhs, const lldb_private::ClangASTType &rhs) { - return lhs.GetASTContext() != rhs.GetASTContext() || lhs.GetOpaqueQualType() != rhs.GetOpaqueQualType(); + return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueQualType() != rhs.GetOpaqueQualType(); } Index: source/Symbol/Type.cpp =================================================================== --- source/Symbol/Type.cpp +++ source/Symbol/Type.cpp @@ -491,6 +491,7 @@ bool Type::ResolveClangType (ResolveState clang_type_resolve_state) { + // TODO: This needs to consider the correct type system to use. Type *encoding_type = nullptr; if (!m_clang_type.IsValid()) { @@ -511,20 +512,21 @@ break; case eEncodingIsConstUID: - m_clang_type = encoding_type->GetClangForwardType().AddConstModifier(); + m_clang_type = ClangASTContext::AddConstModifier(encoding_type->GetClangForwardType()); break; case eEncodingIsRestrictUID: - m_clang_type = encoding_type->GetClangForwardType().AddRestrictModifier(); + m_clang_type = ClangASTContext::AddRestrictModifier(encoding_type->GetClangForwardType()); break; case eEncodingIsVolatileUID: - m_clang_type = encoding_type->GetClangForwardType().AddVolatileModifier(); + m_clang_type = ClangASTContext::AddVolatileModifier(encoding_type->GetClangForwardType()); break; case eEncodingIsTypedefUID: - m_clang_type = encoding_type->GetClangForwardType().CreateTypedefType (GetName().AsCString(), - GetSymbolFile()->GetClangDeclContextContainingTypeUID(GetID())); + m_clang_type = ClangASTContext::CreateTypedefType (encoding_type->GetClangForwardType(), + GetName().AsCString(), + GetSymbolFile()->GetClangDeclContextContainingTypeUID(GetID())); m_name.Clear(); break; @@ -533,11 +535,11 @@ break; case eEncodingIsLValueReferenceUID: - m_clang_type = encoding_type->GetClangForwardType().GetLValueReferenceType(); + m_clang_type = ClangASTContext::GetLValueReferenceType(encoding_type->GetClangForwardType()); break; case eEncodingIsRValueReferenceUID: - m_clang_type = encoding_type->GetClangForwardType().GetRValueReferenceType(); + m_clang_type = ClangASTContext::GetRValueReferenceType(encoding_type->GetClangForwardType()); break; default: @@ -556,20 +558,21 @@ break; case eEncodingIsConstUID: - m_clang_type = void_clang_type.AddConstModifier (); + m_clang_type = ClangASTContext::AddConstModifier (void_clang_type); break; case eEncodingIsRestrictUID: - m_clang_type = void_clang_type.AddRestrictModifier (); + m_clang_type = ClangASTContext::AddRestrictModifier (void_clang_type); break; case eEncodingIsVolatileUID: - m_clang_type = void_clang_type.AddVolatileModifier (); + m_clang_type = ClangASTContext::AddVolatileModifier (void_clang_type); break; case eEncodingIsTypedefUID: - m_clang_type = void_clang_type.CreateTypedefType (GetName().AsCString(), - GetSymbolFile()->GetClangDeclContextContainingTypeUID(GetID())); + m_clang_type = ClangASTContext::CreateTypedefType (void_clang_type, + GetName().AsCString(), + GetSymbolFile()->GetClangDeclContextContainingTypeUID(GetID())); break; case eEncodingIsPointerUID: @@ -577,11 +580,11 @@ break; case eEncodingIsLValueReferenceUID: - m_clang_type = void_clang_type.GetLValueReferenceType (); + m_clang_type = ClangASTContext::GetLValueReferenceType(void_clang_type); break; case eEncodingIsRValueReferenceUID: - m_clang_type = void_clang_type.GetRValueReferenceType (); + m_clang_type = ClangASTContext::GetRValueReferenceType(void_clang_type); break; default: @@ -735,7 +738,7 @@ // those don't have any information. We could extend this to only return true for "full // definitions" if we can figure that out. - if (m_clang_type.IsObjCObjectOrInterfaceType() && GetByteSize() != 0) + if (ClangASTContext::IsObjCObjectOrInterfaceType(m_clang_type) && GetByteSize() != 0) return true; else return false; @@ -1182,7 +1185,7 @@ { if (m_dynamic_type.IsValid()) { - return TypeImpl(m_static_type.GetReferenceType(), m_dynamic_type.GetLValueReferenceType()); + return TypeImpl(m_static_type.GetReferenceType(), ClangASTContext::GetLValueReferenceType(m_dynamic_type)); } return TypeImpl(m_static_type.GetReferenceType()); } @@ -1265,8 +1268,8 @@ return ClangASTType(); } -clang::ASTContext * -TypeImpl::GetClangASTContext (bool prefer_dynamic) +TypeSystem * +TypeImpl::GetTypeSystem (bool prefer_dynamic) { ModuleSP module_sp; if (CheckModule (module_sp)) @@ -1274,9 +1277,9 @@ if (prefer_dynamic) { if (m_dynamic_type.IsValid()) - return m_dynamic_type.GetASTContext(); + return m_dynamic_type.GetTypeSystem(); } - return m_static_type.GetClangASTContext(); + return m_static_type.GetClangASTType().GetTypeSystem(); } return NULL; } @@ -1387,7 +1390,7 @@ if (m_type) return m_type.GetFunctionReturnType(); if (m_objc_method_decl) - return ClangASTType(&m_objc_method_decl->getASTContext(),m_objc_method_decl->getReturnType().getAsOpaquePtr()); + return ClangASTType(&m_objc_method_decl->getASTContext(), m_objc_method_decl->getReturnType()); return ClangASTType(); } @@ -1409,7 +1412,7 @@ if (m_objc_method_decl) { if (idx < m_objc_method_decl->param_size()) - return ClangASTType(&m_objc_method_decl->getASTContext(), m_objc_method_decl->parameters()[idx]->getOriginalType().getAsOpaquePtr()); + return ClangASTType(&m_objc_method_decl->getASTContext(), m_objc_method_decl->parameters()[idx]->getOriginalType()); } return ClangASTType(); } Index: source/Symbol/TypeSystem.cpp =================================================================== --- /dev/null +++ source/Symbol/TypeSystem.cpp @@ -0,0 +1,20 @@ +// +// TypeSystem.cpp +// lldb +// +// Created by Ryan Brown on 3/29/15. +// +// + +#include "lldb/Symbol/TypeSystem.h" + +using namespace lldb_private; + +TypeSystem::TypeSystem() +{ +} + +TypeSystem::~TypeSystem() +{ + +} Index: source/Symbol/Variable.cpp =================================================================== --- source/Symbol/Variable.cpp +++ source/Symbol/Variable.cpp @@ -582,13 +582,13 @@ { // We are in a type parsing child members - const uint32_t num_bases = clang_type.GetNumDirectBaseClasses(); + const uint32_t num_bases = ClangASTContext::GetNumDirectBaseClasses(clang_type); if (num_bases > 0) { for (uint32_t i = 0; i < num_bases; ++i) { - ClangASTType base_class_type (clang_type.GetDirectBaseClassAtIndex (i, nullptr)); + ClangASTType base_class_type (ClangASTContext::GetDirectBaseClassAtIndex(clang_type, i, nullptr)); PrivateAutoCompleteMembers (frame, partial_member_name, @@ -600,13 +600,13 @@ } } - const uint32_t num_vbases = clang_type.GetNumVirtualBaseClasses(); + const uint32_t num_vbases = ClangASTContext::GetNumVirtualBaseClasses(clang_type); if (num_vbases > 0) { for (uint32_t i = 0; i < num_vbases; ++i) { - ClangASTType vbase_class_type (clang_type.GetVirtualBaseClassAtIndex(i,nullptr)); + ClangASTType vbase_class_type (ClangASTContext::GetVirtualBaseClassAtIndex(clang_type, i,nullptr)); PrivateAutoCompleteMembers (frame, partial_member_name, Index: source/Target/ObjCLanguageRuntime.cpp =================================================================== --- source/Target/ObjCLanguageRuntime.cpp +++ source/Target/ObjCLanguageRuntime.cpp @@ -136,7 +136,7 @@ { TypeSP type_sp (types.GetTypeAtIndex(i)); - if (type_sp->GetClangForwardType().IsObjCObjectOrInterfaceType()) + if (ClangASTContext::IsObjCObjectOrInterfaceType(type_sp->GetClangForwardType())) { if (type_sp->IsCompleteObjCClass()) { @@ -648,7 +648,7 @@ ObjCLanguageRuntime::GetTypeBitSize (const ClangASTType& clang_type, uint64_t &size) { - void *opaque_ptr = clang_type.GetQualType().getAsOpaquePtr(); + void *opaque_ptr = clang_type.GetOpaqueQualType(); size = m_type_size_cache.Lookup(opaque_ptr); // an ObjC object will at least have an ISA, so 0 is definitely not OK if (size > 0)