//===-- SWIG Interface for SBType -------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

namespace lldb {

    %feature("docstring",
"Represents a member of a type.") SBTypeMember;

class SBTypeMember
{
public:
    SBTypeMember ();

    SBTypeMember (const lldb::SBTypeMember& rhs);

    ~SBTypeMember();

    bool
    IsValid() const;

    explicit operator bool() const;

    const char *
    GetName ();

    lldb::SBType
    GetType ();

    uint64_t
    GetOffsetInBytes();

    uint64_t
    GetOffsetInBits();

    bool
    IsBitfield();

    uint32_t
    GetBitfieldSizeInBits();

    STRING_EXTENSION_LEVEL(SBTypeMember, lldb::eDescriptionLevelBrief)

#ifdef SWIGPYTHON
    %pythoncode %{
        name = property(GetName, None, doc='''A read only property that returns the name for this member as a string.''')
        type = property(GetType, None, doc='''A read only property that returns an lldb object that represents the type (lldb.SBType) for this member.''')
        byte_offset = property(GetOffsetInBytes, None, doc='''A read only property that returns offset in bytes for this member as an integer.''')
        bit_offset = property(GetOffsetInBits, None, doc='''A read only property that returns offset in bits for this member as an integer.''')
        is_bitfield = property(IsBitfield, None, doc='''A read only property that returns true if this member is a bitfield.''')
        bitfield_bit_size = property(GetBitfieldSizeInBits, None, doc='''A read only property that returns the bitfield size in bits for this member as an integer, or zero if this member is not a bitfield.''')
    %}
#endif

protected:
    std::unique_ptr<lldb_private::TypeMemberImpl> m_opaque_ap;
};

%feature("docstring",
"Represents a member function of a type."
) SBTypeMemberFunction;
class SBTypeMemberFunction
{
public:
    SBTypeMemberFunction ();

    SBTypeMemberFunction (const lldb::SBTypeMemberFunction& rhs);

    ~SBTypeMemberFunction();

    bool
    IsValid() const;

    explicit operator bool() const;

    const char *
    GetName ();

    const char *
    GetDemangledName ();

    const char *
    GetMangledName ();

    lldb::SBType
    GetType ();

    lldb::SBType
    GetReturnType ();

    uint32_t
    GetNumberOfArguments ();

    lldb::SBType
    GetArgumentTypeAtIndex (uint32_t);

    lldb::MemberFunctionKind
    GetKind();

    bool
    GetDescription (lldb::SBStream &description,
                    lldb::DescriptionLevel description_level);

    STRING_EXTENSION_LEVEL(SBTypeMemberFunction, lldb::eDescriptionLevelBrief)
protected:
    lldb::TypeMemberFunctionImplSP m_opaque_sp;
};

%feature("docstring",
"Represents a data type in lldb.

The actual characteristics of each type are defined by the semantics of the
programming language and the specific language implementation that was used
to compile the target program. See the language-specific notes in the
documentation of each method.

SBType instances can be obtained by a variety of methods.
`SBTarget.FindFirstType` and `SBModule.FindFirstType` can be used to create
`SBType` representations of types in executables/libraries with debug
information. For some languages such as C, C++ and Objective-C it is possible
to create new types by evaluating expressions that define a new type.

Note that most `SBType` properties are computed independently of any runtime
information so for dynamic languages the functionality can be very limited.
`SBValue` can be used to represent runtime values which then can be more
accurately queried for certain information such as byte size.


SBType supports the eq/ne operator. For example,::

    //main.cpp:

    class Task {
    public:
        int id;
        Task *next;
        Task(int i, Task *n):
            id(i),
            next(n)
        {}
    };

    int main (int argc, char const *argv[])
    {
        Task *task_head = new Task(-1, NULL);
        Task *task1 = new Task(1, NULL);
        Task *task2 = new Task(2, NULL);
        Task *task3 = new Task(3, NULL); // Orphaned.
        Task *task4 = new Task(4, NULL);
        Task *task5 = new Task(5, NULL);

        task_head->next = task1;
        task1->next = task2;
        task2->next = task4;
        task4->next = task5;

        int total = 0;
        Task *t = task_head;
        while (t != NULL) {
            if (t->id >= 0)
                ++total;
            t = t->next;
        }
        printf('We have a total number of %d tasks\\n', total);

        // This corresponds to an empty task list.
        Task *empty_task_head = new Task(-1, NULL);

        return 0; // Break at this line
    }

    # find_type.py:

            # Get the type 'Task'.
            task_type = target.FindFirstType('Task')
            self.assertTrue(task_type)

            # Get the variable 'task_head'.
            frame0.FindVariable('task_head')
            task_head_type = task_head.GetType()
            self.assertTrue(task_head_type.IsPointerType())

            # task_head_type is 'Task *'.
            task_pointer_type = task_type.GetPointerType()
            self.assertTrue(task_head_type == task_pointer_type)

            # Get the child mmember 'id' from 'task_head'.
            id = task_head.GetChildMemberWithName('id')
            id_type = id.GetType()

            # SBType.GetBasicType() takes an enum 'BasicType' (lldb-enumerations.h).
            int_type = id_type.GetBasicType(lldb.eBasicTypeInt)
            # id_type and int_type should be the same type!
            self.assertTrue(id_type == int_type)

") SBType;
class SBType
{
public:
    SBType ();

    SBType (const lldb::SBType &rhs);

    ~SBType ();

    bool
    IsValid();

    explicit operator bool() const;


    %feature("docstring",
    "Returns the number of bytes a variable with the given types occupies in memory.

    Returns ``0`` if the size can't be determined.

    If a type occupies ``N`` bytes + ``M`` bits in memory, this function returns
    the rounded up amount of bytes (i.e., if ``M`` is ``0``,
    this function returns ``N`` and otherwise ``N + 1``).

    Language-specific behaviour:

    * C: The output is expected to match the value of ``sizeof(Type)``. If
      ``sizeof(Type)`` is not a valid expression for the given type, the
      function returns ``0``.
    * C++: Same as in C.
    * Objective-C: Same as in C. For Objective-C classes this always returns
      `0`` as the actual size depends on runtime information.
    ") GetByteSize;
    uint64_t
    GetByteSize();


    %feature("docstring",
    "Returns true if this type is a pointer type.

    Language-specific behaviour:

    * C: Returns true for C pointer types (or typedefs of these types).
    * C++: Pointer types include the C pointer types as well as pointers to data
      mebers or member functions.
    * Objective-C: Pointer types include the C pointer types. ``id``, ``Class``
      and pointers to blocks are also considered pointer types.
    ") IsPointerType;
    bool
    IsPointerType();

    %feature("docstring",
    "Returns true if this type is a reference type.

    Language-specific behaviour:

    * C: Returns false for all types.
    * C++: Both l-value and r-value references are considered reference types.
    * Objective-C: Returns false for all types.
    ") IsReferenceType;
    bool
    IsReferenceType();

    %feature("docstring",
    "Returns true if this type is a function type.

    Language-specific behaviour:

    * C: Returns true for types that represent functions. Note that function
      pointers are not function types (but their `GetPointeeType()` are function
      types).
    * C++: Same as in C.
    * Objective-C: Returns false for all types.
    ") IsPolymorphicClass;
    bool
    IsFunctionType ();

    %feature("docstring",
    "Returns true if this type is a polymorphic type.

    Language-specific behaviour:

    * C: Returns false for all types.
    * C++: Returns true if the type is a class type that contains at least one
      virtual member function or if at least one of its base classes is
      considered a polymorphic type.
    * Objective-C: Returns false for all types.
    ") IsPolymorphicClass;
    bool
    IsPolymorphicClass ();

    %feature("docstring",
    "Returns true if this type is an array type.

    Language-specific behaviour:

    * C: Returns true if the types is an array type. This includes incomplete
      array types ``T[]`` and array types with integer (``T[1]``) or variable
      length (``T[some_variable]``). Pointer types are not considered arrays.
    * C++: Includes C's array types and dependent array types (i.e., array types
      in templates which size depends on template arguments).
    * Objective-C: Same as in C.
    ") IsArrayType;
    bool
    IsArrayType ();

    %feature("docstring",
    "Returns true if this type is a vector type.

    Language-specific behaviour:

    * C: Returns true if the types is a vector type created with
      GCC's ``vector_size`` or Clang's ``ext_vector_type`` feature.
    * C++: Same as in C.
    * Objective-C: Same as in C.
    ") IsVectorType;
    bool
    IsVectorType ();

    %feature("docstring",
    "Returns true if this type is a typedef.

    Language-specific behaviour:

    * C: Returns true if the type is a C typedef.
    * C++: Same as in C. Also treats type aliases as typedefs.
    * Objective-C: Same as in C.
    ") IsTypedefType;
    bool
    IsTypedefType ();

    %feature("docstring",
    "Returns true if this type is an anonymous type.

    Language-specific behaviour:

    * C: Returns true for anonymous unions. Also returns true for
      anonymous structs (which are a GNU language extension).
    * C++: Same as in C.
    * Objective-C: Same as in C.
    ") IsAnonymousType;
    bool
    IsAnonymousType ();

    %feature("docstring",
    "Returns true if this type is a scoped enum.

    Language-specific behaviour:

    * C: Returns false for all types.
    * C++: Return true only for C++11 scoped enums.
    * Objective-C: Returns false for all types.
    ") IsScopedEnumerationType;
    bool
    IsScopedEnumerationType ();

    %feature("docstring",
    "Returns true if this type is an aggregate type.

    Language-specific behaviour:

    * C: Returns true for struct values, arrays, and vectors.
    * C++: Same a C. Also includes class instances.
    * Objective-C: Same as C. Also includes class instances.
    ") IsAggregateType;
    bool
    IsAggregateType ();

    %feature("docstring",
    "Returns a type that represents a pointer to this type.

    If the type system of the current language can't represent a pointer to this
    type or this type is invalid, an invalid `SBType` is returned.

    Language-specific behaviour:

    * C: Returns the pointer type of this type.
    * C++: Same as in C.
    * Objective-C: Same as in C.
    ") GetPointerType;
    lldb::SBType
    GetPointerType();

    %feature("docstring",
    "Returns the underlying pointee type.

    If this type is a pointer type as specified by `IsPointerType` then this
    returns the underlying type. If this is not a pointer type or an invalid
    `SBType` then this returns an invalid `SBType`.

    Language-specific behaviour:

    * C: Returns the underlying type for for C pointer types or typedefs of
      these types). For example, ``int *`` will return ``int``.
    * C++: Same as in C. Returns an `SBType` representation for data members/
      member functions in case the `SBType` is a pointer to data member or
      pointer to member function.
    * Objective-C: Same as in C. The pointee type of ``id`` and ``Class`` is
      an invalid `SBType`. The pointee type of pointers Objective-C types is an
      `SBType` for the non-pointer type of the respective type. For example,
      ``NSString *`` will return ``NSString`` as a pointee type.
    ") GetPointeeType;
    lldb::SBType
    GetPointeeType();

    %feature("docstring",
    "Returns a type that represents a reference to this type.

    If the type system of the current language can't represent a reference to
    this type, an invalid `SBType` is returned.

    Language-specific behaviour:

    * C: Currently assumes the type system is C++ and returns an l-value
      reference type. For example, ``int`` will return ``int&``. This behavior
      is likely to change in the future and shouldn't be relied on.
    * C++: Same as in C.
    * Objective-C: Same as in C.
    ") GetReferenceType;
    lldb::SBType
    GetReferenceType();

    %feature("docstring",
    "Returns the underlying type of a typedef.

    If this type is a typedef as designated by `IsTypedefType`, then the
    underlying type is being returned. Otherwise an invalid `SBType` is
    returned.

    Language-specific behaviour:

    * C: Returns the underlying type of a typedef type.
    * C++: Same as in C. For type aliases, the underlying type is returned.
    * Objective-C: Same as in C.
    ") GetTypedefedType;
    lldb::SBType
    SBType::GetTypedefedType();

    %feature("docstring",
    "Returns the underlying type of a reference type.

    If this type is a reference as designated by `IsReferenceType`, then the
    underlying type is being returned. Otherwise an invalid `SBType` is
    returned.

    Language-specific behaviour:

    * C: Always returns an invalid type.
    * C++: For l-value and r-value references the underlying type is returned.
      For example, ``int &`` will return ``int``.
    * Objective-C: Same as in C.
    ") GetDereferencedType;
    lldb::SBType
    GetDereferencedType();

    %feature("docstring",
    "Returns the unqualified version of this type.

    Language-specific behaviour:

    * C: If this type with any const or volatile specifier removed.
    * C++: Same as in C.
    * Objective-C: Same as in C.
    ") GetUnqualifiedType;
    lldb::SBType
    GetUnqualifiedType();

    lldb::SBType
    GetCanonicalType();

    %feature("docstring",
    "Returns the underlying integer type if this is an enumeration type.

    If this type is an invalid `SBType` or not an enumeration type an invalid
    `SBType` is returned.

    Language-specific behaviour:

    * C: Returns the underlying type for enums.
    * C++: Same as in C but also returns the underlying type for scoped enums.
    * Objective-C: Same as in C.
    ") GetEnumerationIntegerType;
    lldb::SBType
    GetEnumerationIntegerType();

    %feature("docstring",
    "Returns the array element type if this type is an array type.

    Otherwise returns an invalid `SBType` if this type is invalid or not an
    array type.

    Language-specific behaviour:

    * C: If this is an array type (see `IsArrayType`) such as ``T[]``, returns
      the element type.
    * C++: Same as in C.
    * Objective-C: Same as in C.

    See also `IsArrayType`.
    ") GetArrayElementType;
    lldb::SBType
    GetArrayElementType ();

    %feature("docstring",
    "Returns the array type with the given constant size.

    Language-specific behaviour:

    * C: Returns a constant-size array `T[size]` for any non-void type.
    * C++: Same as in C.
    * Objective-C: Same as in C.

    See also `IsArrayType` and `GetArrayElementType`.
    ") GetArrayType;
    lldb::SBType
    GetArrayType (uint64_t size);

    %feature("docstring",
    "Returns the vector element type if this type is a vector type.

    Otherwise returns an invalid `SBType` if this type is invalid or not a
    vector type.

    Language-specific behaviour:

    * C: If this is a vector type (see `IsVectorType`), returns the element
      type.
    * C++: Same as in C.
    * Objective-C: Same as in C.

    See also `IsVectorType`.
    ") GetVectorElementType;
    lldb::SBType
    GetVectorElementType ();

    %feature("docstring",
    "Returns the `BasicType` value that is most appropriate to this type.

    Returns `eBasicTypeInvalid` if no appropriate `BasicType` was found or this
    type is invalid. See the `BasicType` documentation for the language-specific m
    aning of each `BasicType` value.

    **Overload behaviour:** When called with a `BasicType` parameter, the
    following behaviour applies:

    Returns the `SBType` that represents the passed `BasicType` value. Returns
    an invalid `SBType` if no fitting `SBType` could be created.

    Language-specific behaviour:

    * C: Returns the respective builtin type. Note that some types
      (e.g. ``__uint128_t``) might even be successfully created even if they are
      not available on the target platform. C++ and Objective-C specific types
      might also be created even if the target program is not written in C++ or
      Objective-C.
    * C++: Same as in C.
    * Objective-C: Same as in C.
    ");
    lldb::BasicType
    GetBasicType();

    lldb::SBType
    GetBasicType (lldb::BasicType type);

    %feature("docstring",
    "Returns the number of fields of this type.

    Returns ``0`` if this type does not have fields.

    Language-specific behaviour:

    * C: Returns the number of fields if the type is a struct. If the type
      contains an anonymous struct/union it only counts as a single field (even
      if the struct/union contains several fields).
    * C++: Returns the number of non-static fields if the type is a
      struct/class. If the type contains an anonymous struct/union it only
      counts as a single field (even if the struct/union contains several
      fields). The fields of any base classes are not included in the count.
    * Objective-C: Same as in C for structs. For Objective-C classes the number
      of ivars is returned.

    See also `GetFieldAtIndex`.
    ") GetNumberOfFields;
    uint32_t
    GetNumberOfFields ();

    %feature("docstring",
    "Returns the number of base/parent classes of this type.

    Returns ``0`` if this type doesn't have any base classes.

    Language-specific behaviour:

    * C: Returns always ``0``.
    * C++: The number of direct non-virtual base classes if this type is
      a class.
    * Objective-C: The number of super classes for Objective-C classes.
      As Objective-C doesn't have multiple inheritance this is usually returns 1
      except for NSObject.
    ") GetNumberOfDirectBaseClasses;
    uint32_t
    GetNumberOfDirectBaseClasses ();

    %feature("docstring",
    "Returns the number of virtual base/parent classes of this type

    Returns ``0`` if this type doesn't have any base classes.

    Language-specific behaviour:

    * C: Returns always ``0``.
    * C++: The number of direct virtual base classes if this type is a
      class.
    * Objective-C: Returns always ``0``.
    ") GetNumberOfVirtualBaseClasses;
    uint32_t
    GetNumberOfVirtualBaseClasses ();

    %feature("docstring",
    "Returns the field at the given index.

    Returns an invalid `SBType` if the index is out of range or the current
    type doesn't have any fields.

    Language-specific behaviour:

    * C: Returns the field with the given index for struct types. Fields are
      ordered/indexed starting from ``0`` for the first field in a struct (as
      declared in the definition).
    * C++: Returns the non-static field with the given index for struct types.
      Fields are ordered/indexed starting from ``0`` for the first field in a
      struct (as declared in the definition).
    * Objective-C: Same as in C for structs. For Objective-C classes the ivar
      with the given index is returned. ivars are indexed starting from ``0``.
    ") GetFieldAtIndex;
    lldb::SBTypeMember
    GetFieldAtIndex (uint32_t idx);

    %feature("docstring",
    "Returns the direct base class as indexed by `GetNumberOfDirectBaseClasses`.

    Returns an invalid SBTypeMember if the index is invalid or this SBType is
    invalid.
    ") GetDirectBaseClassAtIndex;
    lldb::SBTypeMember
    GetDirectBaseClassAtIndex (uint32_t idx);

    %feature("docstring",
    "Returns the virtual base class as indexed by
    `GetNumberOfVirtualBaseClasses`.

    Returns an invalid SBTypeMember if the index is invalid or this SBType is
    invalid.
    ") GetVirtualBaseClassAtIndex;
    lldb::SBTypeMember
    GetVirtualBaseClassAtIndex (uint32_t idx);

    lldb::SBTypeEnumMemberList
    GetEnumMembers();
    %feature("docstring",
    "Returns the `SBModule` this `SBType` belongs to.

    Returns no `SBModule` if this type does not belong to any specific
    `SBModule` or this `SBType` is invalid. An invalid `SBModule` might also
    indicate that once came from an `SBModule` but LLDB could no longer
    determine the original module.
    ") GetModule;
    lldb::SBModule
    GetModule();

    %feature("autodoc", "GetName() -> string") GetName;
    %feature("docstring",
    "Returns the name of this type.

    Returns an empty string if an error occurred or this type is invalid.

    Use this function when trying to match a specific type by name in a script.
    The names returned by this function try to uniquely identify a name but
    conflicts can occur (for example, if a C++ program contains two different
    classes with the same name in different translation units. `GetName` can
    return the same name for both class types.)


    Language-specific behaviour:

    * C: The name of the type. For structs the ``struct`` prefix is omitted.
    * C++: Returns the qualified name of the type (including anonymous/inline
      namespaces and all template arguments).
    * Objective-C: Same as in C.
    ") GetName;
    const char*
    GetName();

    %feature("autodoc", "GetDisplayTypeName() -> string") GetDisplayTypeName;
    %feature("docstring",
    "Returns the name of this type in a user-friendly format.

    Returns an empty string if an error occurred or this type is invalid.

    Use this function when displaying a type name to the user.

    Language-specific behaviour:

    * C: Returns the type name. For structs the ``struct`` prefix is omitted.
    * C++: Returns the qualified name. Anonymous/inline namespaces are omitted.
      Template arguments that match their default value might also be hidden
      (this functionality depends on whether LLDB can determine the template's
      default arguments).
    * Objective-C: Same as in C.
    ") GetDisplayTypeName;
    const char *
    GetDisplayTypeName ();

    %feature("autodoc", "GetTypeClass() -> TypeClass") GetTypeClass;
    %feature("docstring",
    "Returns the `TypeClass` for this type.

    Returns an `eTypeClassInvalid` if this `SBType` is invalid.

    See `TypeClass` for the language-specific meaning of each `TypeClass` value.
    ") GetTypeClass;
    lldb::TypeClass
    GetTypeClass ();

    %feature("docstring",
    "Returns the number of template arguments of this type.

    Returns ``0`` if this type is not a template.

    Language-specific behaviour:

    * C: Always returns ``0``.
    * C++: If this type is a class template instantiation then this returns the
      number of template parameters that were used in this instantiation. This i
      cludes both explicit and implicit template parameters.
    * Objective-C: Always returns ``0``.
    ") GetNumberOfTemplateArguments;
    uint32_t
    GetNumberOfTemplateArguments ();

    %feature("docstring",
    "Returns the type of the template argument with the given index.

    Returns an invalid `SBType` if there is no template argument with the given
    index or this type is not a template. The first template  argument has the
    index ``0``.

    Language-specific behaviour:

    * C: Always returns an invalid SBType.
    * C++: If this type is a class template instantiation and the template
      parameter with the given index is a type template parameter, then this
      returns the type of that parameter. Otherwise returns an invalid `SBType`.
    * Objective-C: Always returns an invalid SBType.
    ") GetTemplateArgumentType;
    lldb::SBType
    GetTemplateArgumentType (uint32_t idx);

    %feature("docstring",
    "Returns the kind of the template argument with the given index.

    Returns `eTemplateArgumentKindNull` if there is no template argument
    with the given index or this type is not a template. The first template
    argument has the index ``0``.

    Language-specific behaviour:

    * C: Always returns `eTemplateArgumentKindNull`.
    * C++: If this type is a class template instantiation then this returns
      the appropriate `TemplateArgument` value for the parameter with the given
      index. See the documentation of `TemplateArgument` for how certain C++
      template parameter kinds are mapped to `TemplateArgument` values.
    * Objective-C: Always returns `eTemplateArgumentKindNull`.
    ") GetTemplateArgumentKind;
    lldb::TemplateArgumentKind
    GetTemplateArgumentKind (uint32_t idx);

    %feature("docstring",
    "Returns the return type if this type represents a function.

    Returns an invalid `SBType` if this type is not a function type or invalid.

    Language-specific behaviour:

    * C: For functions return the return type. Returns an invalid `SBType` if
      this type is a function pointer type.
    * C++: Same as in C for functions and instantiated template functions.
      Member functions are also considered functions. For functions that have
      their return type specified by a placeholder type specifier (``auto``)
      this returns the deduced return type.
    * Objective-C: Same as in C for functions. For Objective-C methods this
      returns the return type of the method.
    ") GetFunctionReturnType;
    lldb::SBType
    GetFunctionReturnType ();

    %feature("docstring",
    "Returns the list of argument types if this type represents a function.

    Returns an invalid `SBType` if this type is not a function type or invalid.

    Language-specific behaviour:

    * C: For functions return the types of each parameter. Returns an invalid
      `SBType` if this type is a function pointer. For variadic functions this
      just returns the list of parameters before the variadic arguments.
    * C++: Same as in C for functions and instantiated template functions.
      Member functions are also considered functions.
    * Objective-C: Always returns an invalid SBType for Objective-C methods.
    ") GetFunctionArgumentTypes;
    lldb::SBTypeList
    GetFunctionArgumentTypes ();

    %feature("docstring",
    "Returns the number of member functions of this type.

    Returns ``0`` if an error occurred or this type is invalid.

    Language-specific behaviour:

    * C: Always returns ``0``.
    * C++: If this type represents a struct/class, then the number of
      member functions (static and non-static) is returned. The count includes
      constructors and destructors (both explicit and implicit). Member
      functions of base classes are not included in the count.
    * Objective-C: If this type represents a struct/class, then the
      number of methods is returned. Methods in categories or super classes
      are not counted.
    ") GetNumberOfMemberFunctions;
    uint32_t
    GetNumberOfMemberFunctions ();

    %feature("docstring",
    "Returns the member function of this type with the given index.

    Returns an invalid `SBTypeMemberFunction` if the index is invalid or this
    type is invalid.

    Language-specific behaviour:

    * C: Always returns an invalid `SBTypeMemberFunction`.
    * C++: Returns the member function or constructor/destructor with the given
      index.
    * Objective-C: Returns the method with the given index.

    See `GetNumberOfMemberFunctions` for what functions can be queried by this
    function.
    ") GetMemberFunctionAtIndex;
    lldb::SBTypeMemberFunction
    GetMemberFunctionAtIndex (uint32_t idx);

    %feature("docstring",
    "Returns true if the type is completely defined.

    Language-specific behaviour:

    * C: Returns false for struct types that were only forward declared in the
      type's `SBTarget`/`SBModule`. Otherwise returns true.
    * C++: Returns false for template/non-template struct/class types and
      scoped enums that were only forward declared inside the type's
      `SBTarget`/`SBModule`. Otherwise returns true.
    * Objective-C: Follows the same behavior as C for struct types. Objective-C
      classes are considered complete unless they were only forward declared via
      ``@class ClassName`` in the type's `SBTarget`/`SBModule`. Otherwise
      returns true.
    ") IsTypeComplete;
    bool
    IsTypeComplete ();

    %feature("docstring",
    "Returns the `TypeFlags` values for this type.

    See the respective `TypeFlags` values for what values can be set. Returns an
    integer in which each `TypeFlags` value is represented by a bit. Specific
    flags can be checked via Python's bitwise operators. For example, the
    `eTypeIsInteger` flag can be checked like this:

    ``(an_sb_type.GetTypeFlags() & lldb.eTypeIsInteger) != 0``

    If this type is invalid this returns ``0``.

    See the different values for `TypeFlags` for the language-specific meanings
    of each `TypeFlags` value.
    ") GetTypeFlags;
    uint32_t
    GetTypeFlags ();

    bool operator==(lldb::SBType &rhs);

    bool operator!=(lldb::SBType &rhs);

    STRING_EXTENSION_LEVEL(SBType, lldb::eDescriptionLevelBrief)

#ifdef SWIGPYTHON
    %pythoncode %{
        def template_arg_array(self):
            num_args = self.num_template_args
            if num_args:
                template_args = []
                for i in range(num_args):
                    template_args.append(self.GetTemplateArgumentType(i))
                return template_args
            return None

        module = property(GetModule, None, doc='''A read only property that returns the module in which type is defined.''')
        name = property(GetName, None, doc='''A read only property that returns the name for this type as a string.''')
        size = property(GetByteSize, None, doc='''A read only property that returns size in bytes for this type as an integer.''')
        is_pointer = property(IsPointerType, None, doc='''A read only property that returns a boolean value that indicates if this type is a pointer type.''')
        is_reference = property(IsReferenceType, None, doc='''A read only property that returns a boolean value that indicates if this type is a reference type.''')
        is_reference = property(IsReferenceType, None, doc='''A read only property that returns a boolean value that indicates if this type is a function type.''')
        num_fields = property(GetNumberOfFields, None, doc='''A read only property that returns number of fields in this type as an integer.''')
        num_bases = property(GetNumberOfDirectBaseClasses, None, doc='''A read only property that returns number of direct base classes in this type as an integer.''')
        num_vbases = property(GetNumberOfVirtualBaseClasses, None, doc='''A read only property that returns number of virtual base classes in this type as an integer.''')
        num_template_args = property(GetNumberOfTemplateArguments, None, doc='''A read only property that returns number of template arguments in this type as an integer.''')
        template_args = property(template_arg_array, None, doc='''A read only property that returns a list() of lldb.SBType objects that represent all template arguments in this type.''')
        type = property(GetTypeClass, None, doc='''A read only property that returns an lldb enumeration value (see enumerations that start with "lldb.eTypeClass") that represents a classification for this type.''')
        is_complete = property(IsTypeComplete, None, doc='''A read only property that returns a boolean value that indicates if this type is a complete type (True) or a forward declaration (False).''')

        def get_bases_array(self):
            '''An accessor function that returns a list() that contains all direct base classes in a lldb.SBType object.'''
            bases = []
            for idx in range(self.GetNumberOfDirectBaseClasses()):
                bases.append(self.GetDirectBaseClassAtIndex(idx))
            return bases

        def get_vbases_array(self):
            '''An accessor function that returns a list() that contains all fields in a lldb.SBType object.'''
            vbases = []
            for idx in range(self.GetNumberOfVirtualBaseClasses()):
                vbases.append(self.GetVirtualBaseClassAtIndex(idx))
            return vbases

        def get_fields_array(self):
            '''An accessor function that returns a list() that contains all fields in a lldb.SBType object.'''
            fields = []
            for idx in range(self.GetNumberOfFields()):
                fields.append(self.GetFieldAtIndex(idx))
            return fields

        def get_members_array(self):
            '''An accessor function that returns a list() that contains all members (base classes and fields) in a lldb.SBType object in ascending bit offset order.'''
            members = []
            bases = self.get_bases_array()
            fields = self.get_fields_array()
            vbases = self.get_vbases_array()
            for base in bases:
                bit_offset = base.bit_offset
                added = False
                for idx, member in enumerate(members):
                    if member.bit_offset > bit_offset:
                        members.insert(idx, base)
                        added = True
                        break
                if not added:
                    members.append(base)
            for vbase in vbases:
                bit_offset = vbase.bit_offset
                added = False
                for idx, member in enumerate(members):
                    if member.bit_offset > bit_offset:
                        members.insert(idx, vbase)
                        added = True
                        break
                if not added:
                    members.append(vbase)
            for field in fields:
                bit_offset = field.bit_offset
                added = False
                for idx, member in enumerate(members):
                    if member.bit_offset > bit_offset:
                        members.insert(idx, field)
                        added = True
                        break
                if not added:
                    members.append(field)
            return members

        def get_enum_members_array(self):
            '''An accessor function that returns a list() that contains all enum members in an lldb.SBType object.'''
            enum_members_list = []
            sb_enum_members = self.GetEnumMembers()
            for idx in range(sb_enum_members.GetSize()):
                enum_members_list.append(sb_enum_members.GetTypeEnumMemberAtIndex(idx))
            return enum_members_list

        bases = property(get_bases_array, None, doc='''A read only property that returns a list() of lldb.SBTypeMember objects that represent all of the direct base classes for this type.''')
        vbases = property(get_vbases_array, None, doc='''A read only property that returns a list() of lldb.SBTypeMember objects that represent all of the virtual base classes for this type.''')
        fields = property(get_fields_array, None, doc='''A read only property that returns a list() of lldb.SBTypeMember objects that represent all of the fields for this type.''')
        members = property(get_members_array, None, doc='''A read only property that returns a list() of all lldb.SBTypeMember objects that represent all of the base classes, virtual base classes and fields for this type in ascending bit offset order.''')
        enum_members = property(get_enum_members_array, None, doc='''A read only property that returns a list() of all lldb.SBTypeEnumMember objects that represent the enum members for this type.''')
        %}
#endif

};

%feature("docstring",
"Represents a list of :py:class:`SBType` s.

The FindTypes() method of :py:class:`SBTarget`/:py:class:`SBModule` returns a SBTypeList.

SBTypeList supports :py:class:`SBType` iteration. For example,

.. code-block:: cpp

    // main.cpp:

    class Task {
    public:
        int id;
        Task *next;
        Task(int i, Task *n):
            id(i),
            next(n)
        {}
    };

.. code-block:: python

    # find_type.py:

    # Get the type 'Task'.
    type_list = target.FindTypes('Task')
    self.assertTrue(len(type_list) == 1)
    # To illustrate the SBType iteration.
    for type in type_list:
        # do something with type

") SBTypeList;
class SBTypeList
{
public:
    SBTypeList();

    bool
    IsValid();

    explicit operator bool() const;

    void
    Append (lldb::SBType type);

    lldb::SBType
    GetTypeAtIndex (uint32_t index);

    uint32_t
    GetSize();

    ~SBTypeList();

#ifdef SWIGPYTHON
    %pythoncode%{
    def __iter__(self):
        '''Iterate over all types in a lldb.SBTypeList object.'''
        return lldb_iter(self, 'GetSize', 'GetTypeAtIndex')

    def __len__(self):
        '''Return the number of types in a lldb.SBTypeList object.'''
        return self.GetSize()
    %}
#endif
};

} // namespace lldb
