def process_member_definitions(cls, member_definitions):
        """
        The incoming member_definitions contains the class attributes (with their values) that are
        used to define the flag members. This method can do anything to the incoming list and has to
        return a final set of flag definitions that assigns bits to the members. The returned member
        definitions can be completely different or unrelated to the incoming ones.
        :param member_definitions: A list of (name, data) tuples.
        :return: An iterable of iterables yielding 3 items: name, bits, data
        """
        members = []
        auto_flags = []
        all_bits = 0
        for name, data in member_definitions:
            bits, data = cls.flag_attribute_value_to_bits_and_data(name, data)
            if bits is UNDEFINED:
                auto_flags.append(len(members))
                members.append((name, data))
            elif is_valid_bits_value(bits):
                all_bits |= bits
                members.append((name, bits, data))
            else:
                raise TypeError("Expected an int value as the bits of flag '%s', received %r" % (name, bits))

        # auto-assigning unused bits to members without custom defined bits
        bit = 1
        for index in auto_flags:
            while bit & all_bits:
                bit <<= 1
            name, data = members[index]
            members[index] = name, bit, data
            bit <<= 1

        return members
The incoming member_definitions contains the class attributes (with their values) that are
        used to define the flag members. This method can do anything to the incoming list and has to
        return a final set of flag definitions that assigns bits to the members. The returned member
        definitions can be completely different or unrelated to the incoming ones.
        :param member_definitions: A list of (name, data) tuples.
        :return: An iterable of iterables yielding 3 items: name, bits, data