diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
commit | 14f1b3e8826ce43b978db93a62d1166055db5394 (patch) | |
tree | 0a00ad8d3498783fe0193f3b656bca17c4c8697d /source/Symbol | |
parent | 4ee8c119c71a06dcad1e0fecc8c675e480e59337 (diff) | |
download | src-14f1b3e8826ce43b978db93a62d1166055db5394.tar.gz src-14f1b3e8826ce43b978db93a62d1166055db5394.zip |
Vendor import of lldb trunk r290819:vendor/lldb/lldb-trunk-r290819
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=311128
svn path=/vendor/lldb/lldb-trunk-r290819/; revision=311129; tag=vendor/lldb/lldb-trunk-r290819
Diffstat (limited to 'source/Symbol')
38 files changed, 25061 insertions, 27406 deletions
diff --git a/source/Symbol/ArmUnwindInfo.cpp b/source/Symbol/ArmUnwindInfo.cpp index 95207cbe320d..19951498c1d7 100644 --- a/source/Symbol/ArmUnwindInfo.cpp +++ b/source/Symbol/ArmUnwindInfo.cpp @@ -9,13 +9,13 @@ #include <vector> +#include "Utility/ARM_DWARF_Registers.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Host/Endian.h" #include "lldb/Symbol/ArmUnwindInfo.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/UnwindPlan.h" -#include "Utility/ARM_DWARF_Registers.h" /* * Unwind information reader and parser for the ARM exception handling ABI @@ -31,415 +31,341 @@ using namespace lldb; using namespace lldb_private; // Converts a prel31 avlue to lldb::addr_t with sign extension -static addr_t -Prel31ToAddr(uint32_t prel31) -{ - addr_t res = prel31; - if (prel31 & (1<<30)) - res |= 0xffffffff80000000ULL; - return res; +static addr_t Prel31ToAddr(uint32_t prel31) { + addr_t res = prel31; + if (prel31 & (1 << 30)) + res |= 0xffffffff80000000ULL; + return res; } -ArmUnwindInfo::ArmExidxEntry::ArmExidxEntry(uint32_t f, lldb::addr_t a, uint32_t d) : - file_address(f), address(a), data(d) -{ -} +ArmUnwindInfo::ArmExidxEntry::ArmExidxEntry(uint32_t f, lldb::addr_t a, + uint32_t d) + : file_address(f), address(a), data(d) {} -bool -ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry& other) const -{ - return address < other.address; +bool ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry &other) const { + return address < other.address; } -ArmUnwindInfo::ArmUnwindInfo(const ObjectFile& objfile, - SectionSP& arm_exidx, - SectionSP& arm_extab) : - m_byte_order(objfile.GetByteOrder()), - m_arm_exidx_sp(arm_exidx), - m_arm_extab_sp(arm_extab) -{ - objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data); - objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data); - - addr_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress(); - - offset_t offset = 0; - while (m_arm_exidx_data.ValidOffset(offset)) - { - lldb::addr_t file_addr = exidx_base_addr + offset; - lldb::addr_t addr = exidx_base_addr + - (addr_t)offset + - Prel31ToAddr(m_arm_exidx_data.GetU32(&offset)); - uint32_t data = m_arm_exidx_data.GetU32(&offset); - m_exidx_entries.emplace_back(file_addr, addr, data); - } - - // Sort the entries in the exidx section. The entries should be sorted inside the section but - // some old compiler isn't sorted them. - std::sort(m_exidx_entries.begin(), m_exidx_entries.end()); +ArmUnwindInfo::ArmUnwindInfo(const ObjectFile &objfile, SectionSP &arm_exidx, + SectionSP &arm_extab) + : m_byte_order(objfile.GetByteOrder()), m_arm_exidx_sp(arm_exidx), + m_arm_extab_sp(arm_extab) { + objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data); + objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data); + + addr_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress(); + + offset_t offset = 0; + while (m_arm_exidx_data.ValidOffset(offset)) { + lldb::addr_t file_addr = exidx_base_addr + offset; + lldb::addr_t addr = exidx_base_addr + (addr_t)offset + + Prel31ToAddr(m_arm_exidx_data.GetU32(&offset)); + uint32_t data = m_arm_exidx_data.GetU32(&offset); + m_exidx_entries.emplace_back(file_addr, addr, data); + } + + // Sort the entries in the exidx section. The entries should be sorted inside + // the section but + // some old compiler isn't sorted them. + std::sort(m_exidx_entries.begin(), m_exidx_entries.end()); } -ArmUnwindInfo::~ArmUnwindInfo() -{ -} +ArmUnwindInfo::~ArmUnwindInfo() {} // Read a byte from the unwind instruction stream with the given offset. -// Custom function is required because have to red in order of significance within their containing +// Custom function is required because have to red in order of significance +// within their containing // word (most significant byte first) and in increasing word address order. -uint8_t -ArmUnwindInfo::GetByteAtOffset(const uint32_t* data, uint16_t offset) const -{ - uint32_t value = data[offset / 4]; - if (m_byte_order != endian::InlHostByteOrder()) - value = llvm::ByteSwap_32(value); - return (value >> ((3 - (offset % 4)) * 8)) & 0xff; +uint8_t ArmUnwindInfo::GetByteAtOffset(const uint32_t *data, + uint16_t offset) const { + uint32_t value = data[offset / 4]; + if (m_byte_order != endian::InlHostByteOrder()) + value = llvm::ByteSwap_32(value); + return (value >> ((3 - (offset % 4)) * 8)) & 0xff; } -uint64_t -ArmUnwindInfo::GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_offset) const -{ - uint64_t result = 0; - uint8_t shift = 0; - while (offset < max_offset) - { - uint8_t byte = GetByteAtOffset(data, offset++); - result |= (uint64_t)(byte & 0x7f) << shift; - if ((byte & 0x80) == 0) - break; - shift += 7; - } - return result; +uint64_t ArmUnwindInfo::GetULEB128(const uint32_t *data, uint16_t &offset, + uint16_t max_offset) const { + uint64_t result = 0; + uint8_t shift = 0; + while (offset < max_offset) { + uint8_t byte = GetByteAtOffset(data, offset++); + result |= (uint64_t)(byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + return result; } -bool -ArmUnwindInfo::GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan) -{ - const uint32_t* data = (const uint32_t*)GetExceptionHandlingTableEntry(addr); - if (data == nullptr) - return false; // No unwind information for the function - - if (data[0] == 0x1) - return false; // EXIDX_CANTUNWIND - - uint16_t byte_count = 0; - uint16_t byte_offset = 0; - if (data[0] & 0x80000000) - { - switch ((data[0] >> 24) & 0x0f) - { - case 0: - byte_count = 4; - byte_offset = 1; - break; - case 1: - case 2: - byte_count = 4 * ((data[0] >> 16) & 0xff) + 4; - byte_offset = 2; - break; - default: - // Unhandled personality routine index - return false; - } - } - else - { - byte_count = 4 * ((data[1] >> 24) & 0xff) + 8; - byte_offset = 5; +bool ArmUnwindInfo::GetUnwindPlan(Target &target, const Address &addr, + UnwindPlan &unwind_plan) { + const uint32_t *data = (const uint32_t *)GetExceptionHandlingTableEntry(addr); + if (data == nullptr) + return false; // No unwind information for the function + + if (data[0] == 0x1) + return false; // EXIDX_CANTUNWIND + + uint16_t byte_count = 0; + uint16_t byte_offset = 0; + if (data[0] & 0x80000000) { + switch ((data[0] >> 24) & 0x0f) { + case 0: + byte_count = 4; + byte_offset = 1; + break; + case 1: + case 2: + byte_count = 4 * ((data[0] >> 16) & 0xff) + 4; + byte_offset = 2; + break; + default: + // Unhandled personality routine index + return false; } - - uint8_t vsp_reg = dwarf_sp; - int32_t vsp = 0; - std::vector<std::pair<uint32_t, int32_t>> register_offsets; // register -> (offset from vsp_reg) - - while (byte_offset < byte_count) - { - uint8_t byte1 = GetByteAtOffset(data, byte_offset++); - if ((byte1&0xc0) == 0x00) - { - // 00xxxxxx - // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive - vsp += ((byte1 & 0x3f) << 2) + 4; - } - else if ((byte1&0xc0) == 0x40) - { - // 01xxxxxx - // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive - vsp -= ((byte1 & 0x3f) << 2) + 4; - } - else if ((byte1&0xf0) == 0x80) - { - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - if (byte1 == 0x80 && byte2 == 0) - { - // 10000000 00000000 - // Refuse to unwind (for example, out of a cleanup) (see remark a) - return false; - } - else - { - // 1000iiii iiiiiiii (i not all 0) - // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see remark b) - uint16_t regs = ((byte1&0x0f) << 8) | byte2; - for (uint8_t i = 0; i < 12; ++i) - { - if (regs & (1<<i)) - { - register_offsets.emplace_back(dwarf_r4 + i, vsp); - vsp += 4; - } - } - } - } - else if ((byte1&0xff) == 0x9d) - { - // 10011101 - // Reserved as prefix for ARM register to register moves - return false; - } - else if ((byte1&0xff) == 0x9f) - { - // 10011111 - // Reserved as prefix for Intel Wireless MMX register to register moves - return false; - } - else if ((byte1&0xf0) == 0x90) - { - // 1001nnnn (nnnn != 13,15) - // Set vsp = r[nnnn] - vsp_reg = dwarf_r0 + (byte1&0x0f); - } - else if ((byte1&0xf8) == 0xa0) - { - // 10100nnn - // Pop r4-r[4+nnn] - uint8_t n = byte1&0x7; - for (uint8_t i = 0; i <= n; ++i) - { - register_offsets.emplace_back(dwarf_r4 + i, vsp); - vsp += 4; - } - } - else if ((byte1&0xf8) == 0xa8) - { - // 10101nnn - // Pop r4-r[4+nnn], r14 - uint8_t n = byte1&0x7; - for (uint8_t i = 0; i <= n; ++i) - { - register_offsets.emplace_back(dwarf_r4 + i, vsp); - vsp += 4; - } - - register_offsets.emplace_back(dwarf_lr, vsp); - vsp += 4; - } - else if ((byte1&0xff) == 0xb0) - { - // 10110000 - // Finish (see remark c) - break; - } - else if ((byte1&0xff) == 0xb1) - { - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - if ((byte2&0xff) == 0x00) - { - // 10110001 00000000 - // Spare (see remark f) - return false; - } - else if ((byte2&0xf0) == 0x00) - { - // 10110001 0000iiii (i not all 0) - // Pop integer registers under mask {r3, r2, r1, r0} - for (uint8_t i = 0; i < 4; ++i) - { - if (byte2 & (1<<i)) - { - register_offsets.emplace_back(dwarf_r0 + i, vsp); - vsp += 4; - } - } - } - else - { - // 10110001 xxxxyyyy - // Spare (xxxx != 0000) - return false; - } - } - else if ((byte1&0xff) == 0xb2) - { - // 10110010 uleb128 - // vsp = vsp + 0x204+ (uleb128 << 2) - uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count); - vsp += 0x204 + (uleb128 << 2); - } - else if ((byte1&0xff) == 0xb3) - { - // 10110011 sssscccc - // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDX (see remark d) - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - uint8_t s = (byte2&0xf0) >> 4; - uint8_t c = (byte2&0x0f) >> 0; - for (uint8_t i = 0; i <= c; ++i) - { - register_offsets.emplace_back(dwarf_d0 + s + i, vsp); - vsp += 8; - } + } else { + byte_count = 4 * ((data[1] >> 24) & 0xff) + 8; + byte_offset = 5; + } + + uint8_t vsp_reg = dwarf_sp; + int32_t vsp = 0; + std::vector<std::pair<uint32_t, int32_t>> + register_offsets; // register -> (offset from vsp_reg) + + while (byte_offset < byte_count) { + uint8_t byte1 = GetByteAtOffset(data, byte_offset++); + if ((byte1 & 0xc0) == 0x00) { + // 00xxxxxx + // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive + vsp += ((byte1 & 0x3f) << 2) + 4; + } else if ((byte1 & 0xc0) == 0x40) { + // 01xxxxxx + // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive + vsp -= ((byte1 & 0x3f) << 2) + 4; + } else if ((byte1 & 0xf0) == 0x80) { + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + if (byte1 == 0x80 && byte2 == 0) { + // 10000000 00000000 + // Refuse to unwind (for example, out of a cleanup) (see remark a) + return false; + } else { + // 1000iiii iiiiiiii (i not all 0) + // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see + // remark b) + uint16_t regs = ((byte1 & 0x0f) << 8) | byte2; + for (uint8_t i = 0; i < 12; ++i) { + if (regs & (1 << i)) { + register_offsets.emplace_back(dwarf_r4 + i, vsp); vsp += 4; + } } - else if ((byte1&0xfc) == 0xb4) - { - // 101101nn - // Spare (was Pop FPA) - return false; - } - else if ((byte1&0xf8) == 0xb8) - { - // 10111nnn - // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDX (see remark d) - uint8_t n = byte1&0x07; - for (uint8_t i = 0; i <= n; ++i) - { - register_offsets.emplace_back(dwarf_d8 + i, vsp); - vsp += 8; - } + } + } else if ((byte1 & 0xff) == 0x9d) { + // 10011101 + // Reserved as prefix for ARM register to register moves + return false; + } else if ((byte1 & 0xff) == 0x9f) { + // 10011111 + // Reserved as prefix for Intel Wireless MMX register to register moves + return false; + } else if ((byte1 & 0xf0) == 0x90) { + // 1001nnnn (nnnn != 13,15) + // Set vsp = r[nnnn] + vsp_reg = dwarf_r0 + (byte1 & 0x0f); + } else if ((byte1 & 0xf8) == 0xa0) { + // 10100nnn + // Pop r4-r[4+nnn] + uint8_t n = byte1 & 0x7; + for (uint8_t i = 0; i <= n; ++i) { + register_offsets.emplace_back(dwarf_r4 + i, vsp); + vsp += 4; + } + } else if ((byte1 & 0xf8) == 0xa8) { + // 10101nnn + // Pop r4-r[4+nnn], r14 + uint8_t n = byte1 & 0x7; + for (uint8_t i = 0; i <= n; ++i) { + register_offsets.emplace_back(dwarf_r4 + i, vsp); + vsp += 4; + } + + register_offsets.emplace_back(dwarf_lr, vsp); + vsp += 4; + } else if ((byte1 & 0xff) == 0xb0) { + // 10110000 + // Finish (see remark c) + break; + } else if ((byte1 & 0xff) == 0xb1) { + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + if ((byte2 & 0xff) == 0x00) { + // 10110001 00000000 + // Spare (see remark f) + return false; + } else if ((byte2 & 0xf0) == 0x00) { + // 10110001 0000iiii (i not all 0) + // Pop integer registers under mask {r3, r2, r1, r0} + for (uint8_t i = 0; i < 4; ++i) { + if (byte2 & (1 << i)) { + register_offsets.emplace_back(dwarf_r0 + i, vsp); vsp += 4; + } } - else if ((byte1&0xf8) == 0xc0) - { - // 11000nnn (nnn != 6,7) - // Intel Wireless MMX pop wR[10]-wR[10+nnn] - - // 11000110 sssscccc - // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e) - - // 11000111 00000000 - // Spare - - // 11000111 0000iiii - // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0} - - // 11000111 xxxxyyyy - // Spare (xxxx != 0000) - - return false; - } - else if ((byte1&0xff) == 0xc8) - { - // 11001000 sssscccc - // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as if) by FSTMFDD (see remarks d,e) - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - uint8_t s = (byte2&0xf0) >> 4; - uint8_t c = (byte2&0x0f) >> 0; - for (uint8_t i = 0; i <= c; ++i) - { - register_offsets.emplace_back(dwarf_d16 + s + i, vsp); - vsp += 8; - } - } - else if ((byte1&0xff) == 0xc9) - { - // 11001001 sssscccc - // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDD (see remark d) - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - uint8_t s = (byte2&0xf0) >> 4; - uint8_t c = (byte2&0x0f) >> 0; - for (uint8_t i = 0; i <= c; ++i) - { - register_offsets.emplace_back(dwarf_d0 + s + i, vsp); - vsp += 8; - } - } - else if ((byte1&0xf8) == 0xc8) - { - // 11001yyy - // Spare (yyy != 000, 001) - return false; - } - else if ((byte1&0xf8) == 0xc0) - { - // 11010nnn - // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDD (see remark d) - uint8_t n = byte1&0x07; - for (uint8_t i = 0; i <= n; ++i) - { - register_offsets.emplace_back(dwarf_d8 + i, vsp); - vsp += 8; - } - } - else if ((byte1&0xc0) == 0xc0) - { - // 11xxxyyy Spare (xxx != 000, 001, 010) - return false; - } - else - { - return false; - } - } - - UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>(); - row->SetOffset(0); - row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp); - - bool have_location_for_pc = false; - for (const auto& offset : register_offsets) - { - have_location_for_pc |= offset.first == dwarf_pc; - row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp, true); - } - - if (!have_location_for_pc) - { - UnwindPlan::Row::RegisterLocation lr_location; - if (row->GetRegisterInfo(dwarf_lr, lr_location)) - row->SetRegisterInfo(dwarf_pc, lr_location); - else - row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false); + } else { + // 10110001 xxxxyyyy + // Spare (xxxx != 0000) + return false; + } + } else if ((byte1 & 0xff) == 0xb2) { + // 10110010 uleb128 + // vsp = vsp + 0x204+ (uleb128 << 2) + uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count); + vsp += 0x204 + (uleb128 << 2); + } else if ((byte1 & 0xff) == 0xb3) { + // 10110011 sssscccc + // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if) + // by FSTMFDX (see remark d) + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + uint8_t s = (byte2 & 0xf0) >> 4; + uint8_t c = (byte2 & 0x0f) >> 0; + for (uint8_t i = 0; i <= c; ++i) { + register_offsets.emplace_back(dwarf_d0 + s + i, vsp); + vsp += 8; + } + vsp += 4; + } else if ((byte1 & 0xfc) == 0xb4) { + // 101101nn + // Spare (was Pop FPA) + return false; + } else if ((byte1 & 0xf8) == 0xb8) { + // 10111nnn + // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by + // FSTMFDX (see remark d) + uint8_t n = byte1 & 0x07; + for (uint8_t i = 0; i <= n; ++i) { + register_offsets.emplace_back(dwarf_d8 + i, vsp); + vsp += 8; + } + vsp += 4; + } else if ((byte1 & 0xf8) == 0xc0) { + // 11000nnn (nnn != 6,7) + // Intel Wireless MMX pop wR[10]-wR[10+nnn] + + // 11000110 sssscccc + // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e) + + // 11000111 00000000 + // Spare + + // 11000111 0000iiii + // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0} + + // 11000111 xxxxyyyy + // Spare (xxxx != 0000) + + return false; + } else if ((byte1 & 0xff) == 0xc8) { + // 11001000 sssscccc + // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as + // if) by FSTMFDD (see remarks d,e) + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + uint8_t s = (byte2 & 0xf0) >> 4; + uint8_t c = (byte2 & 0x0f) >> 0; + for (uint8_t i = 0; i <= c; ++i) { + register_offsets.emplace_back(dwarf_d16 + s + i, vsp); + vsp += 8; + } + } else if ((byte1 & 0xff) == 0xc9) { + // 11001001 sssscccc + // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) + // by FSTMFDD (see remark d) + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + uint8_t s = (byte2 & 0xf0) >> 4; + uint8_t c = (byte2 & 0x0f) >> 0; + for (uint8_t i = 0; i <= c; ++i) { + register_offsets.emplace_back(dwarf_d0 + s + i, vsp); + vsp += 8; + } + } else if ((byte1 & 0xf8) == 0xc8) { + // 11001yyy + // Spare (yyy != 000, 001) + return false; + } else if ((byte1 & 0xf8) == 0xc0) { + // 11010nnn + // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by + // FSTMFDD (see remark d) + uint8_t n = byte1 & 0x07; + for (uint8_t i = 0; i <= n; ++i) { + register_offsets.emplace_back(dwarf_d8 + i, vsp); + vsp += 8; + } + } else if ((byte1 & 0xc0) == 0xc0) { + // 11xxxyyy Spare (xxx != 000, 001, 010) + return false; + } else { + return false; } + } + + UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>(); + row->SetOffset(0); + row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp); + + bool have_location_for_pc = false; + for (const auto &offset : register_offsets) { + have_location_for_pc |= offset.first == dwarf_pc; + row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp, + true); + } + + if (!have_location_for_pc) { + UnwindPlan::Row::RegisterLocation lr_location; + if (row->GetRegisterInfo(dwarf_lr, lr_location)) + row->SetRegisterInfo(dwarf_pc, lr_location); + else + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false); + } - unwind_plan.AppendRow(row); - unwind_plan.SetSourceName ("ARM.exidx unwind info"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetRegisterKind (eRegisterKindDWARF); + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("ARM.exidx unwind info"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); - return true; + return true; } -const uint8_t* -ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address& addr) -{ - auto it = std::upper_bound(m_exidx_entries.begin(), - m_exidx_entries.end(), - ArmExidxEntry{0, addr.GetFileAddress(), 0}); - if (it == m_exidx_entries.begin()) - return nullptr; - --it; +const uint8_t * +ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address &addr) { + auto it = std::upper_bound(m_exidx_entries.begin(), m_exidx_entries.end(), + ArmExidxEntry{0, addr.GetFileAddress(), 0}); + if (it == m_exidx_entries.begin()) + return nullptr; + --it; - if (it->data == 0x1) - return nullptr; // EXIDX_CANTUNWIND + if (it->data == 0x1) + return nullptr; // EXIDX_CANTUNWIND - if (it->data & 0x80000000) - return (const uint8_t*)&it->data; + if (it->data & 0x80000000) + return (const uint8_t *)&it->data; - addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data); - return m_arm_extab_data.GetDataStart() + (data_file_addr - m_arm_extab_sp->GetFileAddress()); + addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data); + return m_arm_extab_data.GetDataStart() + + (data_file_addr - m_arm_extab_sp->GetFileAddress()); } diff --git a/source/Symbol/Block.cpp b/source/Symbol/Block.cpp index 9d50c5cb7c9a..6c4c28d1f7f7 100644 --- a/source/Symbol/Block.cpp +++ b/source/Symbol/Block.cpp @@ -20,628 +20,486 @@ using namespace lldb; using namespace lldb_private; -Block::Block(lldb::user_id_t uid) : - UserID(uid), - m_parent_scope (nullptr), - m_children (), - m_ranges (), - m_inlineInfoSP (), - m_variable_list_sp (), - m_parsed_block_info (false), - m_parsed_block_variables (false), - m_parsed_child_blocks (false) -{ -} - -Block::~Block () -{ -} - -void -Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel level, Target *target) const -{ - *s << "id = " << ((const UserID&)*this); - - size_t num_ranges = m_ranges.GetSize(); - if (num_ranges > 0) - { - - addr_t base_addr = LLDB_INVALID_ADDRESS; - if (target) - base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(target); - if (base_addr == LLDB_INVALID_ADDRESS) - base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); - - s->Printf(", range%s = ", num_ranges > 1 ? "s" : ""); - for (size_t i=0; i<num_ranges; ++i) - { - const Range &range = m_ranges.GetEntryRef(i); - s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); - } - } - - if (m_inlineInfoSP.get() != nullptr) - { - bool show_fullpaths = (level == eDescriptionLevelVerbose); - m_inlineInfoSP->Dump(s, show_fullpaths); +Block::Block(lldb::user_id_t uid) + : UserID(uid), m_parent_scope(nullptr), m_children(), m_ranges(), + m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false), + m_parsed_block_variables(false), m_parsed_child_blocks(false) {} + +Block::~Block() {} + +void Block::GetDescription(Stream *s, Function *function, + lldb::DescriptionLevel level, Target *target) const { + *s << "id = " << ((const UserID &)*this); + + size_t num_ranges = m_ranges.GetSize(); + if (num_ranges > 0) { + + addr_t base_addr = LLDB_INVALID_ADDRESS; + if (target) + base_addr = + function->GetAddressRange().GetBaseAddress().GetLoadAddress(target); + if (base_addr == LLDB_INVALID_ADDRESS) + base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); + + s->Printf(", range%s = ", num_ranges > 1 ? "s" : ""); + for (size_t i = 0; i < num_ranges; ++i) { + const Range &range = m_ranges.GetEntryRef(i); + s->AddressRange(base_addr + range.GetRangeBase(), + base_addr + range.GetRangeEnd(), 4); } -} - -void -Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const -{ - if (depth < 0) - { - Block *parent = GetParent(); - if (parent) - { - // We have a depth that is less than zero, print our parent blocks - // first - parent->Dump(s, base_addr, depth + 1, show_context); - } + } + + if (m_inlineInfoSP.get() != nullptr) { + bool show_fullpaths = (level == eDescriptionLevelVerbose); + m_inlineInfoSP->Dump(s, show_fullpaths); + } +} + +void Block::Dump(Stream *s, addr_t base_addr, int32_t depth, + bool show_context) const { + if (depth < 0) { + Block *parent = GetParent(); + if (parent) { + // We have a depth that is less than zero, print our parent blocks + // first + parent->Dump(s, base_addr, depth + 1, show_context); } + } + + s->Printf("%p: ", static_cast<const void *>(this)); + s->Indent(); + *s << "Block" << static_cast<const UserID &>(*this); + const Block *parent_block = GetParent(); + if (parent_block) { + s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID()); + } + if (m_inlineInfoSP.get() != nullptr) { + bool show_fullpaths = false; + m_inlineInfoSP->Dump(s, show_fullpaths); + } + + if (!m_ranges.IsEmpty()) { + *s << ", ranges ="; - s->Printf("%p: ", static_cast<const void*>(this)); - s->Indent(); - *s << "Block" << static_cast<const UserID&>(*this); - const Block* parent_block = GetParent(); - if (parent_block) - { - s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID()); - } - if (m_inlineInfoSP.get() != nullptr) - { - bool show_fullpaths = false; - m_inlineInfoSP->Dump(s, show_fullpaths); - } - - if (!m_ranges.IsEmpty()) - { - *s << ", ranges ="; - - size_t num_ranges = m_ranges.GetSize(); - for (size_t i=0; i<num_ranges; ++i) - { - const Range &range = m_ranges.GetEntryRef(i); - if (parent_block != nullptr && parent_block->Contains(range) == false) - *s << '!'; - else - *s << ' '; - s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); - } + size_t num_ranges = m_ranges.GetSize(); + for (size_t i = 0; i < num_ranges; ++i) { + const Range &range = m_ranges.GetEntryRef(i); + if (parent_block != nullptr && parent_block->Contains(range) == false) + *s << '!'; + else + *s << ' '; + s->AddressRange(base_addr + range.GetRangeBase(), + base_addr + range.GetRangeEnd(), 4); } - s->EOL(); + } + s->EOL(); - if (depth > 0) - { - s->IndentMore(); + if (depth > 0) { + s->IndentMore(); - if (m_variable_list_sp.get()) - { - m_variable_list_sp->Dump(s, show_context); - } - - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - (*pos)->Dump(s, base_addr, depth - 1, show_context); - - s->IndentLess(); + if (m_variable_list_sp.get()) { + m_variable_list_sp->Dump(s, show_context); } -} - - -Block * -Block::FindBlockByID (user_id_t block_id) -{ - if (block_id == GetID()) - return this; - - Block *matching_block = nullptr; collection::const_iterator pos, end = m_children.end(); for (pos = m_children.begin(); pos != end; ++pos) - { - matching_block = (*pos)->FindBlockByID (block_id); - if (matching_block) - break; - } - return matching_block; -} - -void -Block::CalculateSymbolContext (SymbolContext* sc) -{ - if (m_parent_scope) - m_parent_scope->CalculateSymbolContext(sc); - sc->block = this; -} + (*pos)->Dump(s, base_addr, depth - 1, show_context); -lldb::ModuleSP -Block::CalculateSymbolContextModule () -{ - if (m_parent_scope) - return m_parent_scope->CalculateSymbolContextModule (); - return lldb::ModuleSP(); + s->IndentLess(); + } } -CompileUnit * -Block::CalculateSymbolContextCompileUnit () -{ - if (m_parent_scope) - return m_parent_scope->CalculateSymbolContextCompileUnit (); - return nullptr; -} +Block *Block::FindBlockByID(user_id_t block_id) { + if (block_id == GetID()) + return this; -Function * -Block::CalculateSymbolContextFunction () -{ - if (m_parent_scope) - return m_parent_scope->CalculateSymbolContextFunction (); - return nullptr; + Block *matching_block = nullptr; + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) { + matching_block = (*pos)->FindBlockByID(block_id); + if (matching_block) + break; + } + return matching_block; } -Block * -Block::CalculateSymbolContextBlock () -{ - return this; +void Block::CalculateSymbolContext(SymbolContext *sc) { + if (m_parent_scope) + m_parent_scope->CalculateSymbolContext(sc); + sc->block = this; } -void -Block::DumpSymbolContext(Stream *s) -{ - Function *function = CalculateSymbolContextFunction(); - if (function) - function->DumpSymbolContext(s); - s->Printf(", Block{0x%8.8" PRIx64 "}", GetID()); -} - -void -Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr) -{ - if (!m_ranges.IsEmpty()) - { - size_t num_ranges = m_ranges.GetSize(); - for (size_t i=0; i<num_ranges; ++i) - { - const Range &range = m_ranges.GetEntryRef(i); - s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); - } - } +lldb::ModuleSP Block::CalculateSymbolContextModule() { + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextModule(); + return lldb::ModuleSP(); } -bool -Block::Contains (addr_t range_offset) const -{ - return m_ranges.FindEntryThatContains(range_offset) != nullptr; -} - -bool -Block::Contains (const Block *block) const -{ - if (this == block) - return false; // This block doesn't contain itself... - - // Walk the parent chain for "block" and see if any if them match this block - const Block *block_parent; - for (block_parent = block->GetParent(); - block_parent != nullptr; - block_parent = block_parent->GetParent()) - { - if (this == block_parent) - return true; // One of the parents of "block" is this object! - } - return false; +CompileUnit *Block::CalculateSymbolContextCompileUnit() { + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextCompileUnit(); + return nullptr; } -bool -Block::Contains (const Range& range) const -{ - return m_ranges.FindEntryThatContains (range) != nullptr; +Function *Block::CalculateSymbolContextFunction() { + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextFunction(); + return nullptr; } -Block * -Block::GetParent () const -{ - if (m_parent_scope) - return m_parent_scope->CalculateSymbolContextBlock(); - return nullptr; -} +Block *Block::CalculateSymbolContextBlock() { return this; } -Block * -Block::GetContainingInlinedBlock () -{ - if (GetInlinedFunctionInfo()) - return this; - return GetInlinedParent (); +void Block::DumpSymbolContext(Stream *s) { + Function *function = CalculateSymbolContextFunction(); + if (function) + function->DumpSymbolContext(s); + s->Printf(", Block{0x%8.8" PRIx64 "}", GetID()); } -Block * -Block::GetInlinedParent () -{ - Block *parent_block = GetParent (); - if (parent_block) - { - if (parent_block->GetInlinedFunctionInfo()) - return parent_block; - else - return parent_block->GetInlinedParent(); +void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) { + if (!m_ranges.IsEmpty()) { + size_t num_ranges = m_ranges.GetSize(); + for (size_t i = 0; i < num_ranges; ++i) { + const Range &range = m_ranges.GetEntryRef(i); + s->AddressRange(base_addr + range.GetRangeBase(), + base_addr + range.GetRangeEnd(), 4); } - return nullptr; + } } - -bool -Block::GetRangeContainingOffset (const addr_t offset, Range &range) -{ - const Range *range_ptr = m_ranges.FindEntryThatContains (offset); - if (range_ptr) - { - range = *range_ptr; - return true; - } - range.Clear(); - return false; +bool Block::Contains(addr_t range_offset) const { + return m_ranges.FindEntryThatContains(range_offset) != nullptr; } +bool Block::Contains(const Block *block) const { + if (this == block) + return false; // This block doesn't contain itself... -bool -Block::GetRangeContainingAddress (const Address& addr, AddressRange &range) -{ - Function *function = CalculateSymbolContextFunction(); - if (function) - { - const AddressRange &func_range = function->GetAddressRange(); - if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) - { - const addr_t addr_offset = addr.GetOffset(); - const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); - if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) - { - addr_t offset = addr_offset - func_offset; - - const Range *range_ptr = m_ranges.FindEntryThatContains (offset); - - if (range_ptr) - { - range.GetBaseAddress() = func_range.GetBaseAddress(); - range.GetBaseAddress().SetOffset(func_offset + range_ptr->GetRangeBase()); - range.SetByteSize(range_ptr->GetByteSize()); - return true; - } - } - } - } - range.Clear(); - return false; + // Walk the parent chain for "block" and see if any if them match this block + const Block *block_parent; + for (block_parent = block->GetParent(); block_parent != nullptr; + block_parent = block_parent->GetParent()) { + if (this == block_parent) + return true; // One of the parents of "block" is this object! + } + return false; } -bool -Block::GetRangeContainingLoadAddress (lldb::addr_t load_addr, Target &target, AddressRange &range) -{ - Address load_address; - load_address.SetLoadAddress(load_addr, &target); - AddressRange containing_range; - return GetRangeContainingAddress(load_address, containing_range); +bool Block::Contains(const Range &range) const { + return m_ranges.FindEntryThatContains(range) != nullptr; } +Block *Block::GetParent() const { + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextBlock(); + return nullptr; +} -uint32_t -Block::GetRangeIndexContainingAddress (const Address& addr) -{ - Function *function = CalculateSymbolContextFunction(); - if (function) - { - const AddressRange &func_range = function->GetAddressRange(); - if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) - { - const addr_t addr_offset = addr.GetOffset(); - const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); - if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) - { - addr_t offset = addr_offset - func_offset; - return m_ranges.FindEntryIndexThatContains (offset); - } +Block *Block::GetContainingInlinedBlock() { + if (GetInlinedFunctionInfo()) + return this; + return GetInlinedParent(); +} + +Block *Block::GetInlinedParent() { + Block *parent_block = GetParent(); + if (parent_block) { + if (parent_block->GetInlinedFunctionInfo()) + return parent_block; + else + return parent_block->GetInlinedParent(); + } + return nullptr; +} + +bool Block::GetRangeContainingOffset(const addr_t offset, Range &range) { + const Range *range_ptr = m_ranges.FindEntryThatContains(offset); + if (range_ptr) { + range = *range_ptr; + return true; + } + range.Clear(); + return false; +} + +bool Block::GetRangeContainingAddress(const Address &addr, + AddressRange &range) { + Function *function = CalculateSymbolContextFunction(); + if (function) { + const AddressRange &func_range = function->GetAddressRange(); + if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) { + const addr_t addr_offset = addr.GetOffset(); + const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); + if (addr_offset >= func_offset && + addr_offset < func_offset + func_range.GetByteSize()) { + addr_t offset = addr_offset - func_offset; + + const Range *range_ptr = m_ranges.FindEntryThatContains(offset); + + if (range_ptr) { + range.GetBaseAddress() = func_range.GetBaseAddress(); + range.GetBaseAddress().SetOffset(func_offset + + range_ptr->GetRangeBase()); + range.SetByteSize(range_ptr->GetByteSize()); + return true; } + } } - return UINT32_MAX; -} - -bool -Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range) -{ - if (range_idx < m_ranges.GetSize()) - { - Function *function = CalculateSymbolContextFunction(); - if (function) - { - const Range &vm_range = m_ranges.GetEntryRef(range_idx); - range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress(); - range.GetBaseAddress().Slide(vm_range.GetRangeBase ()); - range.SetByteSize (vm_range.GetByteSize()); - return true; - } + } + range.Clear(); + return false; +} + +bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr, + Target &target, AddressRange &range) { + Address load_address; + load_address.SetLoadAddress(load_addr, &target); + AddressRange containing_range; + return GetRangeContainingAddress(load_address, containing_range); +} + +uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) { + Function *function = CalculateSymbolContextFunction(); + if (function) { + const AddressRange &func_range = function->GetAddressRange(); + if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) { + const addr_t addr_offset = addr.GetOffset(); + const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); + if (addr_offset >= func_offset && + addr_offset < func_offset + func_range.GetByteSize()) { + addr_t offset = addr_offset - func_offset; + return m_ranges.FindEntryIndexThatContains(offset); + } } - return false; + } + return UINT32_MAX; } -bool -Block::GetStartAddress (Address &addr) -{ - if (m_ranges.IsEmpty()) - return false; - +bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) { + if (range_idx < m_ranges.GetSize()) { Function *function = CalculateSymbolContextFunction(); - if (function) - { - addr = function->GetAddressRange().GetBaseAddress(); - addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase ()); - return true; + if (function) { + const Range &vm_range = m_ranges.GetEntryRef(range_idx); + range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress(); + range.GetBaseAddress().Slide(vm_range.GetRangeBase()); + range.SetByteSize(vm_range.GetByteSize()); + return true; } - return false; + } + return false; } -void -Block::FinalizeRanges () -{ - m_ranges.Sort(); - m_ranges.CombineConsecutiveRanges (); -} - -void -Block::AddRange (const Range& range) -{ - Block *parent_block = GetParent (); - if (parent_block && !parent_block->Contains(range)) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS)); - if (log) - { - ModuleSP module_sp (m_parent_scope->CalculateSymbolContextModule()); - Function *function = m_parent_scope->CalculateSymbolContextFunction(); - const addr_t function_file_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); - const addr_t block_start_addr = function_file_addr + range.GetRangeBase (); - const addr_t block_end_addr = function_file_addr + range.GetRangeEnd (); - Type *func_type = function->GetType(); - - const Declaration &func_decl = func_type->GetDeclaration(); - if (func_decl.GetLine()) - { - log->Printf ("warning: %s:%u block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s", - func_decl.GetFile().GetPath().c_str(), - func_decl.GetLine(), - GetID(), - (uint32_t)m_ranges.GetSize(), - block_start_addr, - block_end_addr, - parent_block->GetID(), - function->GetID(), - module_sp->GetFileSpec().GetPath().c_str()); - } - else - { - log->Printf ("warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s", - GetID(), - (uint32_t)m_ranges.GetSize(), - block_start_addr, - block_end_addr, - parent_block->GetID(), - function->GetID(), - module_sp->GetFileSpec().GetPath().c_str()); - } - } - parent_block->AddRange (range); +bool Block::GetStartAddress(Address &addr) { + if (m_ranges.IsEmpty()) + return false; + + Function *function = CalculateSymbolContextFunction(); + if (function) { + addr = function->GetAddressRange().GetBaseAddress(); + addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase()); + return true; + } + return false; +} + +void Block::FinalizeRanges() { + m_ranges.Sort(); + m_ranges.CombineConsecutiveRanges(); +} + +void Block::AddRange(const Range &range) { + Block *parent_block = GetParent(); + if (parent_block && !parent_block->Contains(range)) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); + if (log) { + ModuleSP module_sp(m_parent_scope->CalculateSymbolContextModule()); + Function *function = m_parent_scope->CalculateSymbolContextFunction(); + const addr_t function_file_addr = + function->GetAddressRange().GetBaseAddress().GetFileAddress(); + const addr_t block_start_addr = function_file_addr + range.GetRangeBase(); + const addr_t block_end_addr = function_file_addr + range.GetRangeEnd(); + Type *func_type = function->GetType(); + + const Declaration &func_decl = func_type->GetDeclaration(); + if (func_decl.GetLine()) { + log->Printf("warning: %s:%u block {0x%8.8" PRIx64 + "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 + ") which is not contained in parent block {0x%8.8" PRIx64 + "} in function {0x%8.8" PRIx64 "} from %s", + func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(), + GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr, + block_end_addr, parent_block->GetID(), function->GetID(), + module_sp->GetFileSpec().GetPath().c_str()); + } else { + log->Printf("warning: block {0x%8.8" PRIx64 + "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 + ") which is not contained in parent block {0x%8.8" PRIx64 + "} in function {0x%8.8" PRIx64 "} from %s", + GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr, + block_end_addr, parent_block->GetID(), function->GetID(), + module_sp->GetFileSpec().GetPath().c_str()); + } } - m_ranges.Append(range); + parent_block->AddRange(range); + } + m_ranges.Append(range); } // Return the current number of bytes that this object occupies in memory -size_t -Block::MemorySize() const -{ - size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range); - if (m_inlineInfoSP.get()) - mem_size += m_inlineInfoSP->MemorySize(); - if (m_variable_list_sp.get()) - mem_size += m_variable_list_sp->MemorySize(); - return mem_size; - -} - -void -Block::AddChild(const BlockSP &child_block_sp) -{ - if (child_block_sp) - { - child_block_sp->SetParentScope (this); - m_children.push_back (child_block_sp); +size_t Block::MemorySize() const { + size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range); + if (m_inlineInfoSP.get()) + mem_size += m_inlineInfoSP->MemorySize(); + if (m_variable_list_sp.get()) + mem_size += m_variable_list_sp->MemorySize(); + return mem_size; +} + +void Block::AddChild(const BlockSP &child_block_sp) { + if (child_block_sp) { + child_block_sp->SetParentScope(this); + m_children.push_back(child_block_sp); + } +} + +void Block::SetInlinedFunctionInfo(const char *name, const char *mangled, + const Declaration *decl_ptr, + const Declaration *call_decl_ptr) { + m_inlineInfoSP.reset( + new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); +} + +VariableListSP Block::GetBlockVariableList(bool can_create) { + if (m_parsed_block_variables == false) { + if (m_variable_list_sp.get() == nullptr && can_create) { + m_parsed_block_variables = true; + SymbolContext sc; + CalculateSymbolContext(&sc); + assert(sc.module_sp); + sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); } + } + return m_variable_list_sp; } -void -Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) -{ - m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); -} +uint32_t +Block::AppendBlockVariables(bool can_create, bool get_child_block_variables, + bool stop_if_child_block_is_inlined_function, + const std::function<bool(Variable *)> &filter, + VariableList *variable_list) { + uint32_t num_variables_added = 0; + VariableList *block_var_list = GetBlockVariableList(can_create).get(); + if (block_var_list) { + for (size_t i = 0; i < block_var_list->GetSize(); ++i) { + VariableSP variable = block_var_list->GetVariableAtIndex(i); + if (filter(variable.get())) { + num_variables_added++; + variable_list->AddVariable(variable); + } + } + } + if (get_child_block_variables) { + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) { + Block *child_block = pos->get(); + if (stop_if_child_block_is_inlined_function == false || + child_block->GetInlinedFunctionInfo() == nullptr) { + num_variables_added += child_block->AppendBlockVariables( + can_create, get_child_block_variables, + stop_if_child_block_is_inlined_function, filter, variable_list); + } + } + } + return num_variables_added; +} + +uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables, + bool stop_if_block_is_inlined_function, + const std::function<bool(Variable *)> &filter, + VariableList *variable_list) { + uint32_t num_variables_added = 0; + VariableListSP variable_list_sp(GetBlockVariableList(can_create)); + + bool is_inlined_function = GetInlinedFunctionInfo() != nullptr; + if (variable_list_sp) { + for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) { + VariableSP variable = variable_list_sp->GetVariableAtIndex(i); + if (filter(variable.get())) { + num_variables_added++; + variable_list->AddVariable(variable); + } + } + } + if (get_parent_variables) { + if (stop_if_block_is_inlined_function && is_inlined_function) + return num_variables_added; -VariableListSP -Block::GetBlockVariableList (bool can_create) -{ - if (m_parsed_block_variables == false) - { - if (m_variable_list_sp.get() == nullptr && can_create) - { - m_parsed_block_variables = true; - SymbolContext sc; - CalculateSymbolContext(&sc); - assert(sc.module_sp); - sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); - } - } - return m_variable_list_sp; + Block *parent_block = GetParent(); + if (parent_block) + num_variables_added += parent_block->AppendVariables( + can_create, get_parent_variables, stop_if_block_is_inlined_function, + filter, variable_list); + } + return num_variables_added; } -uint32_t -Block::AppendBlockVariables (bool can_create, - bool get_child_block_variables, - bool stop_if_child_block_is_inlined_function, - const std::function<bool(Variable*)>& filter, - VariableList *variable_list) -{ - uint32_t num_variables_added = 0; - VariableList *block_var_list = GetBlockVariableList (can_create).get(); - if (block_var_list) - { - for (size_t i = 0; i < block_var_list->GetSize(); ++i) - { - VariableSP variable = block_var_list->GetVariableAtIndex(i); - if (filter(variable.get())) - { - num_variables_added++; - variable_list->AddVariable(variable); - } - } - } +CompilerDeclContext Block::GetDeclContext() { + ModuleSP module_sp = CalculateSymbolContextModule(); - if (get_child_block_variables) - { - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - { - Block *child_block = pos->get(); - if (stop_if_child_block_is_inlined_function == false || - child_block->GetInlinedFunctionInfo() == nullptr) - { - num_variables_added += child_block->AppendBlockVariables (can_create, - get_child_block_variables, - stop_if_child_block_is_inlined_function, - filter, - variable_list); - } - } - } - return num_variables_added; -} + if (module_sp) { + SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); -uint32_t -Block::AppendVariables -( - bool can_create, - bool get_parent_variables, - bool stop_if_block_is_inlined_function, - const std::function<bool(Variable*)>& filter, - VariableList *variable_list -) -{ - uint32_t num_variables_added = 0; - VariableListSP variable_list_sp(GetBlockVariableList(can_create)); - - bool is_inlined_function = GetInlinedFunctionInfo() != nullptr; - if (variable_list_sp) - { - for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) - { - VariableSP variable = variable_list_sp->GetVariableAtIndex(i); - if (filter(variable.get())) - { - num_variables_added++; - variable_list->AddVariable(variable); - } - } - } + if (sym_vendor) { + SymbolFile *sym_file = sym_vendor->GetSymbolFile(); - if (get_parent_variables) - { - if (stop_if_block_is_inlined_function && is_inlined_function) - return num_variables_added; - - Block* parent_block = GetParent(); - if (parent_block) - num_variables_added += parent_block->AppendVariables(can_create, - get_parent_variables, - stop_if_block_is_inlined_function, - filter, - variable_list); - } - return num_variables_added; -} - -CompilerDeclContext -Block::GetDeclContext() -{ - ModuleSP module_sp = CalculateSymbolContextModule (); - - if (module_sp) - { - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); - - if (sym_vendor) - { - SymbolFile *sym_file = sym_vendor->GetSymbolFile(); - - if (sym_file) - return sym_file->GetDeclContextForUID (GetID()); - } - } - return CompilerDeclContext(); -} - -void -Block::SetBlockInfoHasBeenParsed (bool b, bool set_children) -{ - m_parsed_block_info = b; - if (set_children) - { - m_parsed_child_blocks = true; - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - (*pos)->SetBlockInfoHasBeenParsed (b, true); + if (sym_file) + return sym_file->GetDeclContextForUID(GetID()); } + } + return CompilerDeclContext(); } -void -Block::SetDidParseVariables (bool b, bool set_children) -{ - m_parsed_block_variables = b; - if (set_children) - { - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - (*pos)->SetDidParseVariables (b, true); - } +void Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) { + m_parsed_block_info = b; + if (set_children) { + m_parsed_child_blocks = true; + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + (*pos)->SetBlockInfoHasBeenParsed(b, true); + } } +void Block::SetDidParseVariables(bool b, bool set_children) { + m_parsed_block_variables = b; + if (set_children) { + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + (*pos)->SetDidParseVariables(b, true); + } +} -Block * -Block::GetSibling() const -{ - if (m_parent_scope) - { - Block *parent_block = GetParent(); - if (parent_block) - return parent_block->GetSiblingForChild (this); - } - return nullptr; +Block *Block::GetSibling() const { + if (m_parent_scope) { + Block *parent_block = GetParent(); + if (parent_block) + return parent_block->GetSiblingForChild(this); + } + return nullptr; } // A parent of child blocks can be asked to find a sibling block given // one of its child blocks -Block * -Block::GetSiblingForChild (const Block *child_block) const -{ - if (!m_children.empty()) - { - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - { - if (pos->get() == child_block) - { - if (++pos != end) - return pos->get(); - break; - } - } +Block *Block::GetSiblingForChild(const Block *child_block) const { + if (!m_children.empty()) { + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) { + if (pos->get() == child_block) { + if (++pos != end) + return pos->get(); + break; + } } - return nullptr; + } + return nullptr; } - diff --git a/source/Symbol/CMakeLists.txt b/source/Symbol/CMakeLists.txt index 320a780dc98e..c5f7be73f4bf 100644 --- a/source/Symbol/CMakeLists.txt +++ b/source/Symbol/CMakeLists.txt @@ -21,6 +21,7 @@ add_lldb_library(lldbSymbol LineEntry.cpp LineTable.cpp ObjectFile.cpp + OCamlASTContext.cpp Symbol.cpp SymbolContext.cpp SymbolFile.cpp diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp index 02882ef2ef4d..caebd0ce8c6b 100644 --- a/source/Symbol/ClangASTContext.cpp +++ b/source/Symbol/ClangASTContext.cpp @@ -9,6 +9,9 @@ #include "lldb/Symbol/ClangASTContext.h" +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatVariadic.h" + // C Includes // C++ Includes #include <mutex> // std::once @@ -17,7 +20,7 @@ // Other libraries and framework includes -// Clang headers like to use NDEBUG inside of them to enable/disable debug +// Clang headers like to use NDEBUG inside of them to enable/disable debug // related features using "#ifndef NDEBUG" preprocessor blocks to do one thing // or another. This is bad because it means that if clang was built in release // mode, it assumes that you are building in release mode which is not always @@ -103,2087 +106,2077 @@ using namespace lldb_private; using namespace llvm; using namespace clang; -namespace -{ - static inline bool ClangASTContextSupportsLanguage (lldb::LanguageType language) - { - return language == eLanguageTypeUnknown || // Clang is the default type system - Language::LanguageIsC (language) || - Language::LanguageIsCPlusPlus (language) || - Language::LanguageIsObjC (language) || - // Use Clang for Rust until there is a proper language plugin for it - language == eLanguageTypeRust || - language == eLanguageTypeExtRenderScript; +namespace { +static inline bool +ClangASTContextSupportsLanguage(lldb::LanguageType language) { + return language == eLanguageTypeUnknown || // Clang is the default type system + Language::LanguageIsC(language) || + Language::LanguageIsCPlusPlus(language) || + Language::LanguageIsObjC(language) || + Language::LanguageIsPascal(language) || + // Use Clang for Rust until there is a proper language plugin for it + language == eLanguageTypeRust || + language == eLanguageTypeExtRenderScript || + // Use Clang for D until there is a proper language plugin for it + language == eLanguageTypeD; +} +} + +typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, ClangASTContext *> + ClangASTMap; + +static ClangASTMap &GetASTMap() { + static ClangASTMap *g_map_ptr = nullptr; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_map_ptr = new ClangASTMap(); // leaked on purpose to avoid spins + }); + return *g_map_ptr; +} + +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; -typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, ClangASTContext*> ClangASTMap; + 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; -static ClangASTMap & -GetASTMap() -{ - static ClangASTMap *g_map_ptr = nullptr; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_map_ptr = new ClangASTMap(); // leaked on purpose to avoid spins - }); - return *g_map_ptr; -} + 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::AccessSpecifier -ClangASTContext::ConvertAccessTypeToAccessSpecifier (AccessType access) -{ - switch (access) - { - default: break; - case eAccessNone: return AS_none; - case eAccessPublic: return AS_public; - case eAccessPrivate: return AS_private; - case eAccessProtected: return AS_protected; - } +ClangASTContext::ConvertAccessTypeToAccessSpecifier(AccessType access) { + switch (access) { + default: + break; + case eAccessNone: return AS_none; + case eAccessPublic: + return AS_public; + case eAccessPrivate: + return AS_private; + case eAccessProtected: + return AS_protected; + } + return AS_none; +} + +static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { + // FIXME: Cleanup per-file based stuff. + + // Set some properties which depend solely on the input kind; it would be nice + // to move these to the language standard, and have the driver resolve the + // input kind + language standard. + if (IK == IK_Asm) { + Opts.AsmPreprocessor = 1; + } else if (IK == IK_ObjC || IK == IK_ObjCXX || IK == IK_PreprocessedObjC || + IK == IK_PreprocessedObjCXX) { + Opts.ObjC1 = Opts.ObjC2 = 1; + } + + LangStandard::Kind LangStd = LangStandard::lang_unspecified; + + if (LangStd == LangStandard::lang_unspecified) { + // Based on the base language, pick one. + switch (IK) { + case IK_None: + case IK_AST: + case IK_LLVM_IR: + case IK_RenderScript: + assert(!"Invalid input kind!"); + case IK_OpenCL: + LangStd = LangStandard::lang_opencl; + break; + case IK_CUDA: + case IK_PreprocessedCuda: + LangStd = LangStandard::lang_cuda; + break; + case IK_Asm: + case IK_C: + case IK_PreprocessedC: + case IK_ObjC: + case IK_PreprocessedObjC: + LangStd = LangStandard::lang_gnu99; + break; + case IK_CXX: + case IK_PreprocessedCXX: + case IK_ObjCXX: + case IK_PreprocessedObjCXX: + LangStd = LangStandard::lang_gnucxx98; + break; + } + } + + const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); + Opts.LineComment = Std.hasLineComments(); + Opts.C99 = Std.isC99(); + Opts.CPlusPlus = Std.isCPlusPlus(); + Opts.CPlusPlus11 = Std.isCPlusPlus11(); + Opts.Digraphs = Std.hasDigraphs(); + Opts.GNUMode = Std.isGNUMode(); + Opts.GNUInline = !Std.isC99(); + Opts.HexFloats = Std.hasHexFloats(); + Opts.ImplicitInt = Std.hasImplicitInt(); + + Opts.WChar = true; + + // OpenCL has some additional defaults. + if (LangStd == LangStandard::lang_opencl) { + Opts.OpenCL = 1; + Opts.AltiVec = 1; + Opts.CXXOperatorNames = 1; + Opts.LaxVectorConversions = 1; + } + + // OpenCL and C++ both have bool, true, false keywords. + Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; + + // if (Opts.CPlusPlus) + // Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names); + // + // if (Args.hasArg(OPT_fobjc_gc_only)) + // Opts.setGCMode(LangOptions::GCOnly); + // else if (Args.hasArg(OPT_fobjc_gc)) + // Opts.setGCMode(LangOptions::HybridGC); + // + // if (Args.hasArg(OPT_print_ivar_layout)) + // Opts.ObjCGCBitmapPrint = 1; + // + // if (Args.hasArg(OPT_faltivec)) + // Opts.AltiVec = 1; + // + // if (Args.hasArg(OPT_pthread)) + // Opts.POSIXThreads = 1; + // + // llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility, + // "default"); + // if (Vis == "default") + Opts.setValueVisibilityMode(DefaultVisibility); + // else if (Vis == "hidden") + // Opts.setVisibilityMode(LangOptions::Hidden); + // else if (Vis == "protected") + // Opts.setVisibilityMode(LangOptions::Protected); + // else + // Diags.Report(diag::err_drv_invalid_value) + // << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis; + + // Opts.OverflowChecking = Args.hasArg(OPT_ftrapv); + + // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs + // is specified, or -std is set to a conforming mode. + Opts.Trigraphs = !Opts.GNUMode; + // if (Args.hasArg(OPT_trigraphs)) + // Opts.Trigraphs = 1; + // + // Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers, + // OPT_fno_dollars_in_identifiers, + // !Opts.AsmPreprocessor); + // Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings); + // Opts.Microsoft = Args.hasArg(OPT_fms_extensions); + // Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); + // if (Args.hasArg(OPT_fno_lax_vector_conversions)) + // Opts.LaxVectorConversions = 0; + // Opts.Exceptions = Args.hasArg(OPT_fexceptions); + // Opts.RTTI = !Args.hasArg(OPT_fno_rtti); + // Opts.Blocks = Args.hasArg(OPT_fblocks); + Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault(); + // Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); + // Opts.Freestanding = Args.hasArg(OPT_ffreestanding); + // Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; + // Opts.AssumeSaneOperatorNew = + // !Args.hasArg(OPT_fno_assume_sane_operator_new); + // Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); + // Opts.AccessControl = Args.hasArg(OPT_faccess_control); + // Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); + // Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno); + // Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, + // 99, + // Diags); + // Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); + // Opts.ObjCConstantStringClass = getLastArgValue(Args, + // OPT_fconstant_string_class); + // Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi); + // Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior); + // Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); + // Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); + // Opts.Static = Args.hasArg(OPT_static_define); + Opts.OptimizeSize = 0; + + // FIXME: Eliminate this dependency. + // unsigned Opt = + // Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags); + // Opts.Optimize = Opt != 0; + unsigned Opt = 0; + + // This is the __NO_INLINE__ define, which just depends on things like the + // optimization level and -fno-inline, not actually whether the backend has + // inlining enabled. + // + // FIXME: This is affected by other options (-fno-inline). + Opts.NoInlineDefine = !Opt; + + // unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); + // switch (SSP) { + // default: + // Diags.Report(diag::err_drv_invalid_value) + // << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << + // SSP; + // break; + // case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break; + // case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break; + // case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break; + // } +} + +ClangASTContext::ClangASTContext(const char *target_triple) + : TypeSystem(TypeSystem::eKindClang), m_target_triple(), m_ast_ap(), + m_language_options_ap(), m_source_manager_ap(), m_diagnostics_engine_ap(), + m_target_options_rp(), m_target_info_ap(), m_identifier_table_ap(), + m_selector_table_ap(), m_builtins_ap(), m_callback_tag_decl(nullptr), + m_callback_objc_decl(nullptr), m_callback_baton(nullptr), + m_pointer_byte_size(0), m_ast_owned(false) { + if (target_triple && target_triple[0]) + SetTargetTriple(target_triple); } -static void -ParseLangArgs (LangOptions &Opts, InputKind IK, const char* triple) -{ - // FIXME: Cleanup per-file based stuff. - - // Set some properties which depend solely on the input kind; it would be nice - // to move these to the language standard, and have the driver resolve the - // input kind + language standard. - if (IK == IK_Asm) { - Opts.AsmPreprocessor = 1; - } else if (IK == IK_ObjC || - IK == IK_ObjCXX || - IK == IK_PreprocessedObjC || - IK == IK_PreprocessedObjCXX) { - Opts.ObjC1 = Opts.ObjC2 = 1; - } - - LangStandard::Kind LangStd = LangStandard::lang_unspecified; - - if (LangStd == LangStandard::lang_unspecified) { - // Based on the base language, pick one. - switch (IK) { - case IK_None: - case IK_AST: - case IK_LLVM_IR: - assert (!"Invalid input kind!"); - case IK_OpenCL: - LangStd = LangStandard::lang_opencl; - break; - case IK_CUDA: - case IK_PreprocessedCuda: - LangStd = LangStandard::lang_cuda; - break; - case IK_Asm: - case IK_C: - case IK_PreprocessedC: - case IK_ObjC: - case IK_PreprocessedObjC: - LangStd = LangStandard::lang_gnu99; - break; - case IK_CXX: - case IK_PreprocessedCXX: - case IK_ObjCXX: - case IK_PreprocessedObjCXX: - LangStd = LangStandard::lang_gnucxx98; - break; +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +ClangASTContext::~ClangASTContext() { Finalize(); } + +ConstString ClangASTContext::GetPluginNameStatic() { + return ConstString("clang"); +} + +ConstString ClangASTContext::GetPluginName() { + return ClangASTContext::GetPluginNameStatic(); +} + +uint32_t ClangASTContext::GetPluginVersion() { return 1; } + +lldb::TypeSystemSP ClangASTContext::CreateInstance(lldb::LanguageType language, + lldb_private::Module *module, + Target *target) { + if (ClangASTContextSupportsLanguage(language)) { + ArchSpec arch; + if (module) + arch = module->GetArchitecture(); + else if (target) + arch = target->GetArchitecture(); + + if (arch.IsValid()) { + ArchSpec fixed_arch = arch; + // LLVM wants this to be set to iOS or MacOSX; if we're working on + // a bare-boards type image, change the triple for llvm's benefit. + if (fixed_arch.GetTriple().getVendor() == llvm::Triple::Apple && + fixed_arch.GetTriple().getOS() == llvm::Triple::UnknownOS) { + if (fixed_arch.GetTriple().getArch() == llvm::Triple::arm || + fixed_arch.GetTriple().getArch() == llvm::Triple::aarch64 || + fixed_arch.GetTriple().getArch() == llvm::Triple::thumb) { + fixed_arch.GetTriple().setOS(llvm::Triple::IOS); + } else { + fixed_arch.GetTriple().setOS(llvm::Triple::MacOSX); + } + } + + if (module) { + std::shared_ptr<ClangASTContext> ast_sp(new ClangASTContext); + if (ast_sp) { + ast_sp->SetArchitecture(fixed_arch); } + return ast_sp; + } else if (target && target->IsValid()) { + std::shared_ptr<ClangASTContextForExpressions> ast_sp( + new ClangASTContextForExpressions(*target)); + if (ast_sp) { + ast_sp->SetArchitecture(fixed_arch); + ast_sp->m_scratch_ast_source_ap.reset( + new ClangASTSource(target->shared_from_this())); + ast_sp->m_scratch_ast_source_ap->InstallASTContext( + ast_sp->getASTContext()); + llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source( + ast_sp->m_scratch_ast_source_ap->CreateProxy()); + ast_sp->SetExternalSource(proxy_ast_source); + return ast_sp; + } + } } + } + return lldb::TypeSystemSP(); +} - const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); - Opts.LineComment = Std.hasLineComments(); - Opts.C99 = Std.isC99(); - Opts.CPlusPlus = Std.isCPlusPlus(); - Opts.CPlusPlus11 = Std.isCPlusPlus11(); - Opts.Digraphs = Std.hasDigraphs(); - Opts.GNUMode = Std.isGNUMode(); - Opts.GNUInline = !Std.isC99(); - Opts.HexFloats = Std.hasHexFloats(); - Opts.ImplicitInt = Std.hasImplicitInt(); - - Opts.WChar = true; - - // OpenCL has some additional defaults. - if (LangStd == LangStandard::lang_opencl) { - Opts.OpenCL = 1; - Opts.AltiVec = 1; - Opts.CXXOperatorNames = 1; - Opts.LaxVectorConversions = 1; - } - - // OpenCL and C++ both have bool, true, false keywords. - Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; - -// if (Opts.CPlusPlus) -// Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names); -// -// if (Args.hasArg(OPT_fobjc_gc_only)) -// Opts.setGCMode(LangOptions::GCOnly); -// else if (Args.hasArg(OPT_fobjc_gc)) -// Opts.setGCMode(LangOptions::HybridGC); -// -// if (Args.hasArg(OPT_print_ivar_layout)) -// Opts.ObjCGCBitmapPrint = 1; -// -// if (Args.hasArg(OPT_faltivec)) -// Opts.AltiVec = 1; -// -// if (Args.hasArg(OPT_pthread)) -// Opts.POSIXThreads = 1; -// -// llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility, -// "default"); -// if (Vis == "default") - Opts.setValueVisibilityMode(DefaultVisibility); -// else if (Vis == "hidden") -// Opts.setVisibilityMode(LangOptions::Hidden); -// else if (Vis == "protected") -// Opts.setVisibilityMode(LangOptions::Protected); -// else -// Diags.Report(diag::err_drv_invalid_value) -// << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis; - -// Opts.OverflowChecking = Args.hasArg(OPT_ftrapv); - - // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs - // is specified, or -std is set to a conforming mode. - Opts.Trigraphs = !Opts.GNUMode; -// if (Args.hasArg(OPT_trigraphs)) -// Opts.Trigraphs = 1; -// -// Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers, -// OPT_fno_dollars_in_identifiers, -// !Opts.AsmPreprocessor); -// Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings); -// Opts.Microsoft = Args.hasArg(OPT_fms_extensions); -// Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); -// if (Args.hasArg(OPT_fno_lax_vector_conversions)) -// Opts.LaxVectorConversions = 0; -// Opts.Exceptions = Args.hasArg(OPT_fexceptions); -// Opts.RTTI = !Args.hasArg(OPT_fno_rtti); -// Opts.Blocks = Args.hasArg(OPT_fblocks); - Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault(); -// Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); -// Opts.Freestanding = Args.hasArg(OPT_ffreestanding); -// Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; -// Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); -// Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); -// Opts.AccessControl = Args.hasArg(OPT_faccess_control); -// Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); -// Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno); -// Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99, -// Diags); -// Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); -// Opts.ObjCConstantStringClass = getLastArgValue(Args, -// OPT_fconstant_string_class); -// Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi); -// Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior); -// Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); -// Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); -// Opts.Static = Args.hasArg(OPT_static_define); - Opts.OptimizeSize = 0; - - // FIXME: Eliminate this dependency. -// unsigned Opt = -// Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags); -// Opts.Optimize = Opt != 0; - unsigned Opt = 0; - - // This is the __NO_INLINE__ define, which just depends on things like the - // optimization level and -fno-inline, not actually whether the backend has - // inlining enabled. - // - // FIXME: This is affected by other options (-fno-inline). - Opts.NoInlineDefine = !Opt; - -// unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); -// switch (SSP) { -// default: -// Diags.Report(diag::err_drv_invalid_value) -// << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP; -// break; -// case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break; -// case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break; -// case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break; -// } -} - - -ClangASTContext::ClangASTContext (const char *target_triple) : - TypeSystem (TypeSystem::eKindClang), - m_target_triple (), - m_ast_ap (), - m_language_options_ap (), - m_source_manager_ap (), - m_diagnostics_engine_ap (), - m_target_options_rp (), - m_target_info_ap (), - m_identifier_table_ap (), - m_selector_table_ap (), - m_builtins_ap (), - m_callback_tag_decl (nullptr), - m_callback_objc_decl (nullptr), - m_callback_baton (nullptr), - m_pointer_byte_size (0), - m_ast_owned (false) -{ - if (target_triple && target_triple[0]) - SetTargetTriple (target_triple); +void ClangASTContext::EnumerateSupportedLanguages( + std::set<lldb::LanguageType> &languages_for_types, + std::set<lldb::LanguageType> &languages_for_expressions) { + static std::vector<lldb::LanguageType> s_supported_languages_for_types( + {lldb::eLanguageTypeC89, lldb::eLanguageTypeC, lldb::eLanguageTypeC11, + lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeC99, + lldb::eLanguageTypeObjC, lldb::eLanguageTypeObjC_plus_plus, + lldb::eLanguageTypeC_plus_plus_03, lldb::eLanguageTypeC_plus_plus_11, + lldb::eLanguageTypeC11, lldb::eLanguageTypeC_plus_plus_14}); + + static std::vector<lldb::LanguageType> s_supported_languages_for_expressions( + {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC_plus_plus, + lldb::eLanguageTypeC_plus_plus_03, lldb::eLanguageTypeC_plus_plus_11, + lldb::eLanguageTypeC_plus_plus_14}); + + languages_for_types.insert(s_supported_languages_for_types.begin(), + s_supported_languages_for_types.end()); + languages_for_expressions.insert( + s_supported_languages_for_expressions.begin(), + s_supported_languages_for_expressions.end()); } -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -ClangASTContext::~ClangASTContext() -{ - Finalize(); +void ClangASTContext::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "clang base AST context plug-in", + CreateInstance, EnumerateSupportedLanguages); } -ConstString -ClangASTContext::GetPluginNameStatic() -{ - return ConstString("clang"); +void ClangASTContext::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); } -ConstString -ClangASTContext::GetPluginName() -{ - return ClangASTContext::GetPluginNameStatic(); +void ClangASTContext::Finalize() { + if (m_ast_ap.get()) { + GetASTMap().Erase(m_ast_ap.get()); + if (!m_ast_owned) + m_ast_ap.release(); + } + + m_builtins_ap.reset(); + m_selector_table_ap.reset(); + m_identifier_table_ap.reset(); + m_target_info_ap.reset(); + m_target_options_rp.reset(); + m_diagnostics_engine_ap.reset(); + m_source_manager_ap.reset(); + m_language_options_ap.reset(); + m_ast_ap.reset(); + m_scratch_ast_source_ap.reset(); } -uint32_t -ClangASTContext::GetPluginVersion() -{ - return 1; +void ClangASTContext::Clear() { + m_ast_ap.reset(); + m_language_options_ap.reset(); + m_source_manager_ap.reset(); + m_diagnostics_engine_ap.reset(); + m_target_options_rp.reset(); + m_target_info_ap.reset(); + m_identifier_table_ap.reset(); + m_selector_table_ap.reset(); + m_builtins_ap.reset(); + m_pointer_byte_size = 0; } -lldb::TypeSystemSP -ClangASTContext::CreateInstance (lldb::LanguageType language, - lldb_private::Module *module, - Target *target) -{ - if (ClangASTContextSupportsLanguage(language)) - { - ArchSpec arch; - if (module) - arch = module->GetArchitecture(); - else if (target) - arch = target->GetArchitecture(); - - if (arch.IsValid()) - { - ArchSpec fixed_arch = arch; - // LLVM wants this to be set to iOS or MacOSX; if we're working on - // a bare-boards type image, change the triple for llvm's benefit. - if (fixed_arch.GetTriple().getVendor() == llvm::Triple::Apple && - fixed_arch.GetTriple().getOS() == llvm::Triple::UnknownOS) - { - if (fixed_arch.GetTriple().getArch() == llvm::Triple::arm || - fixed_arch.GetTriple().getArch() == llvm::Triple::aarch64 || - fixed_arch.GetTriple().getArch() == llvm::Triple::thumb) - { - fixed_arch.GetTriple().setOS(llvm::Triple::IOS); - } - else - { - fixed_arch.GetTriple().setOS(llvm::Triple::MacOSX); - } - } +const char *ClangASTContext::GetTargetTriple() { + return m_target_triple.c_str(); +} - if (module) - { - std::shared_ptr<ClangASTContext> ast_sp(new ClangASTContext); - if (ast_sp) - { - ast_sp->SetArchitecture (fixed_arch); - } - return ast_sp; - } - else if (target && target->IsValid()) - { - std::shared_ptr<ClangASTContextForExpressions> ast_sp(new ClangASTContextForExpressions(*target)); - if (ast_sp) - { - ast_sp->SetArchitecture(fixed_arch); - ast_sp->m_scratch_ast_source_ap.reset (new ClangASTSource(target->shared_from_this())); - ast_sp->m_scratch_ast_source_ap->InstallASTContext(ast_sp->getASTContext()); - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(ast_sp->m_scratch_ast_source_ap->CreateProxy()); - ast_sp->SetExternalSource(proxy_ast_source); - return ast_sp; - } - } - } - } - return lldb::TypeSystemSP(); -} - -void -ClangASTContext::EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions) -{ - static std::vector<lldb::LanguageType> s_supported_languages_for_types({ - lldb::eLanguageTypeC89, - lldb::eLanguageTypeC, - lldb::eLanguageTypeC11, - lldb::eLanguageTypeC_plus_plus, - lldb::eLanguageTypeC99, - lldb::eLanguageTypeObjC, - lldb::eLanguageTypeObjC_plus_plus, - lldb::eLanguageTypeC_plus_plus_03, - lldb::eLanguageTypeC_plus_plus_11, - lldb::eLanguageTypeC11, - lldb::eLanguageTypeC_plus_plus_14}); - - static std::vector<lldb::LanguageType> s_supported_languages_for_expressions({ - lldb::eLanguageTypeC_plus_plus, - lldb::eLanguageTypeObjC_plus_plus, - lldb::eLanguageTypeC_plus_plus_03, - lldb::eLanguageTypeC_plus_plus_11, - lldb::eLanguageTypeC_plus_plus_14}); - - languages_for_types.insert(s_supported_languages_for_types.begin(), s_supported_languages_for_types.end()); - languages_for_expressions.insert(s_supported_languages_for_expressions.begin(), s_supported_languages_for_expressions.end()); -} - - -void -ClangASTContext::Initialize() -{ - PluginManager::RegisterPlugin (GetPluginNameStatic(), - "clang base AST context plug-in", - CreateInstance, - EnumerateSupportedLanguages); -} - -void -ClangASTContext::Terminate() -{ - PluginManager::UnregisterPlugin (CreateInstance); -} - -void -ClangASTContext::Finalize() -{ - if (m_ast_ap.get()) - { - GetASTMap().Erase(m_ast_ap.get()); - if (!m_ast_owned) - m_ast_ap.release(); - } - - m_builtins_ap.reset(); - m_selector_table_ap.reset(); - m_identifier_table_ap.reset(); - m_target_info_ap.reset(); - m_target_options_rp.reset(); - m_diagnostics_engine_ap.reset(); - m_source_manager_ap.reset(); - m_language_options_ap.reset(); - m_ast_ap.reset(); - m_scratch_ast_source_ap.reset(); -} - -void -ClangASTContext::Clear() -{ - m_ast_ap.reset(); - m_language_options_ap.reset(); - m_source_manager_ap.reset(); - m_diagnostics_engine_ap.reset(); - m_target_options_rp.reset(); - m_target_info_ap.reset(); - m_identifier_table_ap.reset(); - m_selector_table_ap.reset(); - m_builtins_ap.reset(); - m_pointer_byte_size = 0; -} - -const char * -ClangASTContext::GetTargetTriple () -{ - return m_target_triple.c_str(); -} - -void -ClangASTContext::SetTargetTriple (const char *target_triple) -{ - Clear(); - m_target_triple.assign(target_triple); -} - -void -ClangASTContext::SetArchitecture (const ArchSpec &arch) -{ - SetTargetTriple(arch.GetTriple().str().c_str()); -} - -bool -ClangASTContext::HasExternalSource () -{ - ASTContext *ast = getASTContext(); - if (ast) - return ast->getExternalSource () != nullptr; - return false; +void ClangASTContext::SetTargetTriple(const char *target_triple) { + Clear(); + m_target_triple.assign(target_triple); } -void -ClangASTContext::SetExternalSource (llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_ap) -{ - ASTContext *ast = getASTContext(); - if (ast) - { - ast->setExternalSource (ast_source_ap); - ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(true); - //ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(true); - } +void ClangASTContext::SetArchitecture(const ArchSpec &arch) { + SetTargetTriple(arch.GetTriple().str().c_str()); } -void -ClangASTContext::RemoveExternalSource () -{ - ASTContext *ast = getASTContext(); - - if (ast) - { - llvm::IntrusiveRefCntPtr<ExternalASTSource> empty_ast_source_ap; - ast->setExternalSource (empty_ast_source_ap); - ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false); - //ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false); - } -} - -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(), - *getSelectorTable(), - *getBuiltinContext())); - - m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false); - - // This can be NULL if we don't know anything about the architecture or if the - // target for an architecture isn't enabled in the llvm/clang that we built - TargetInfo *target_info = getTargetInfo(); - if (target_info) - m_ast_ap->InitBuiltinTypes(*target_info); - - if ((m_callback_tag_decl || m_callback_objc_decl) && m_callback_baton) - { - m_ast_ap->getTranslationUnitDecl()->setHasExternalLexicalStorage(); - //m_ast_ap->getTranslationUnitDecl()->setHasExternalVisibleStorage(); - } - - GetASTMap().Insert(m_ast_ap.get(), this); +bool ClangASTContext::HasExternalSource() { + ASTContext *ast = getASTContext(); + if (ast) + return ast->getExternalSource() != nullptr; + return false; +} + +void ClangASTContext::SetExternalSource( + llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_ap) { + ASTContext *ast = getASTContext(); + if (ast) { + ast->setExternalSource(ast_source_ap); + ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(true); + // ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(true); + } +} + +void ClangASTContext::RemoveExternalSource() { + ASTContext *ast = getASTContext(); + + if (ast) { + llvm::IntrusiveRefCntPtr<ExternalASTSource> empty_ast_source_ap; + ast->setExternalSource(empty_ast_source_ap); + ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false); + // ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false); + } +} - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (new ClangExternalASTSourceCallbacks (ClangASTContext::CompleteTagDecl, - ClangASTContext::CompleteObjCInterfaceDecl, - nullptr, - ClangASTContext::LayoutRecordType, - this)); - SetExternalSource (ast_source_ap); +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(), *getSelectorTable(), + *getBuiltinContext())); + + m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false); + + // This can be NULL if we don't know anything about the architecture or if + // the + // target for an architecture isn't enabled in the llvm/clang that we built + TargetInfo *target_info = getTargetInfo(); + if (target_info) + m_ast_ap->InitBuiltinTypes(*target_info); + + if ((m_callback_tag_decl || m_callback_objc_decl) && m_callback_baton) { + m_ast_ap->getTranslationUnitDecl()->setHasExternalLexicalStorage(); + // m_ast_ap->getTranslationUnitDecl()->setHasExternalVisibleStorage(); } - return m_ast_ap.get(); + + GetASTMap().Insert(m_ast_ap.get(), this); + + llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap( + new ClangExternalASTSourceCallbacks( + ClangASTContext::CompleteTagDecl, + ClangASTContext::CompleteObjCInterfaceDecl, nullptr, + ClangASTContext::LayoutRecordType, this)); + SetExternalSource(ast_source_ap); + } + return m_ast_ap.get(); } -ClangASTContext* -ClangASTContext::GetASTContext (clang::ASTContext* ast) -{ - ClangASTContext *clang_ast = GetASTMap().Lookup(ast); - return clang_ast; +ClangASTContext *ClangASTContext::GetASTContext(clang::ASTContext *ast) { + ClangASTContext *clang_ast = GetASTMap().Lookup(ast); + return clang_ast; } -Builtin::Context * -ClangASTContext::getBuiltinContext() -{ - if (m_builtins_ap.get() == nullptr) - m_builtins_ap.reset (new Builtin::Context()); - return m_builtins_ap.get(); +Builtin::Context *ClangASTContext::getBuiltinContext() { + if (m_builtins_ap.get() == nullptr) + m_builtins_ap.reset(new Builtin::Context()); + return m_builtins_ap.get(); } -IdentifierTable * -ClangASTContext::getIdentifierTable() -{ - if (m_identifier_table_ap.get() == nullptr) - m_identifier_table_ap.reset(new IdentifierTable (*ClangASTContext::getLanguageOptions(), nullptr)); - return m_identifier_table_ap.get(); +IdentifierTable *ClangASTContext::getIdentifierTable() { + if (m_identifier_table_ap.get() == nullptr) + m_identifier_table_ap.reset( + new IdentifierTable(*ClangASTContext::getLanguageOptions(), nullptr)); + return m_identifier_table_ap.get(); } -LangOptions * -ClangASTContext::getLanguageOptions() -{ - if (m_language_options_ap.get() == nullptr) - { - m_language_options_ap.reset(new LangOptions()); - ParseLangArgs(*m_language_options_ap, IK_ObjCXX, GetTargetTriple()); -// InitializeLangOptions(*m_language_options_ap, IK_ObjCXX); - } - return m_language_options_ap.get(); +LangOptions *ClangASTContext::getLanguageOptions() { + if (m_language_options_ap.get() == nullptr) { + m_language_options_ap.reset(new LangOptions()); + ParseLangArgs(*m_language_options_ap, IK_ObjCXX, GetTargetTriple()); + // InitializeLangOptions(*m_language_options_ap, IK_ObjCXX); + } + return m_language_options_ap.get(); } -SelectorTable * -ClangASTContext::getSelectorTable() -{ - if (m_selector_table_ap.get() == nullptr) - m_selector_table_ap.reset (new SelectorTable()); - return m_selector_table_ap.get(); +SelectorTable *ClangASTContext::getSelectorTable() { + if (m_selector_table_ap.get() == nullptr) + m_selector_table_ap.reset(new SelectorTable()); + return m_selector_table_ap.get(); } -clang::FileManager * -ClangASTContext::getFileManager() -{ - if (m_file_manager_ap.get() == nullptr) - { - clang::FileSystemOptions file_system_options; - m_file_manager_ap.reset(new clang::FileManager(file_system_options)); - } - return m_file_manager_ap.get(); +clang::FileManager *ClangASTContext::getFileManager() { + if (m_file_manager_ap.get() == nullptr) { + clang::FileSystemOptions file_system_options; + m_file_manager_ap.reset(new clang::FileManager(file_system_options)); + } + return m_file_manager_ap.get(); } -clang::SourceManager * -ClangASTContext::getSourceManager() -{ - if (m_source_manager_ap.get() == nullptr) - m_source_manager_ap.reset(new clang::SourceManager(*getDiagnosticsEngine(), *getFileManager())); - return m_source_manager_ap.get(); +clang::SourceManager *ClangASTContext::getSourceManager() { + if (m_source_manager_ap.get() == nullptr) + m_source_manager_ap.reset( + new clang::SourceManager(*getDiagnosticsEngine(), *getFileManager())); + return m_source_manager_ap.get(); } -clang::DiagnosticsEngine * -ClangASTContext::getDiagnosticsEngine() -{ - if (m_diagnostics_engine_ap.get() == nullptr) - { - llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs()); - m_diagnostics_engine_ap.reset(new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions())); - } - return m_diagnostics_engine_ap.get(); +clang::DiagnosticsEngine *ClangASTContext::getDiagnosticsEngine() { + if (m_diagnostics_engine_ap.get() == nullptr) { + llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs()); + m_diagnostics_engine_ap.reset( + new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions())); + } + return m_diagnostics_engine_ap.get(); } -clang::MangleContext * -ClangASTContext::getMangleContext() -{ - if (m_mangle_ctx_ap.get() == nullptr) - m_mangle_ctx_ap.reset (getASTContext()->createMangleContext()); - return m_mangle_ctx_ap.get(); +clang::MangleContext *ClangASTContext::getMangleContext() { + if (m_mangle_ctx_ap.get() == nullptr) + m_mangle_ctx_ap.reset(getASTContext()->createMangleContext()); + return m_mangle_ctx_ap.get(); } -class NullDiagnosticConsumer : public DiagnosticConsumer -{ +class NullDiagnosticConsumer : public DiagnosticConsumer { public: - NullDiagnosticConsumer () - { - m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); - } - - void - HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) - { - if (m_log) - { - llvm::SmallVector<char, 32> diag_str(10); - info.FormatDiagnostic(diag_str); - diag_str.push_back('\0'); - m_log->Printf("Compiler diagnostic: %s\n", diag_str.data()); - } - } - - DiagnosticConsumer *clone (DiagnosticsEngine &Diags) const - { - return new NullDiagnosticConsumer (); + NullDiagnosticConsumer() { + m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); + } + + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const clang::Diagnostic &info) { + if (m_log) { + llvm::SmallVector<char, 32> diag_str(10); + info.FormatDiagnostic(diag_str); + diag_str.push_back('\0'); + m_log->Printf("Compiler diagnostic: %s\n", diag_str.data()); } + } + + DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { + return new NullDiagnosticConsumer(); + } + private: - Log * m_log; + Log *m_log; }; -DiagnosticConsumer * -ClangASTContext::getDiagnosticConsumer() -{ - if (m_diagnostic_consumer_ap.get() == nullptr) - m_diagnostic_consumer_ap.reset(new NullDiagnosticConsumer); - - return m_diagnostic_consumer_ap.get(); -} +DiagnosticConsumer *ClangASTContext::getDiagnosticConsumer() { + if (m_diagnostic_consumer_ap.get() == nullptr) + m_diagnostic_consumer_ap.reset(new NullDiagnosticConsumer); -std::shared_ptr<clang::TargetOptions> & -ClangASTContext::getTargetOptions() { - if (m_target_options_rp.get() == nullptr && !m_target_triple.empty()) - { - m_target_options_rp = std::make_shared<clang::TargetOptions>(); - if (m_target_options_rp.get() != nullptr) - m_target_options_rp->Triple = m_target_triple; - } - return m_target_options_rp; + return m_diagnostic_consumer_ap.get(); } +std::shared_ptr<clang::TargetOptions> &ClangASTContext::getTargetOptions() { + if (m_target_options_rp.get() == nullptr && !m_target_triple.empty()) { + m_target_options_rp = std::make_shared<clang::TargetOptions>(); + if (m_target_options_rp.get() != nullptr) + m_target_options_rp->Triple = m_target_triple; + } + return m_target_options_rp; +} -TargetInfo * -ClangASTContext::getTargetInfo() -{ - // target_triple should be something like "x86_64-apple-macosx" - if (m_target_info_ap.get() == nullptr && !m_target_triple.empty()) - m_target_info_ap.reset (TargetInfo::CreateTargetInfo(*getDiagnosticsEngine(), getTargetOptions())); - return m_target_info_ap.get(); +TargetInfo *ClangASTContext::getTargetInfo() { + // target_triple should be something like "x86_64-apple-macosx" + if (m_target_info_ap.get() == nullptr && !m_target_triple.empty()) + m_target_info_ap.reset(TargetInfo::CreateTargetInfo(*getDiagnosticsEngine(), + getTargetOptions())); + return m_target_info_ap.get(); } #pragma mark Basic Types -static inline bool -QualTypeMatchesBitSize(const uint64_t bit_size, ASTContext *ast, QualType qual_type) -{ - uint64_t qual_type_bit_size = ast->getTypeSize(qual_type); - if (qual_type_bit_size == bit_size) - return true; - return false; +static inline bool QualTypeMatchesBitSize(const uint64_t bit_size, + ASTContext *ast, QualType qual_type) { + uint64_t qual_type_bit_size = ast->getTypeSize(qual_type); + if (qual_type_bit_size == bit_size) + return true; + return false; } CompilerType -ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (Encoding encoding, size_t bit_size) -{ - return ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (getASTContext(), encoding, bit_size); +ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding, + size_t bit_size) { + return ClangASTContext::GetBuiltinTypeForEncodingAndBitSize( + getASTContext(), encoding, bit_size); } -CompilerType -ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (ASTContext *ast, Encoding encoding, uint32_t bit_size) -{ - if (!ast) - return CompilerType(); - switch (encoding) - { - case eEncodingInvalid: - if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) - return CompilerType (ast, ast->VoidPtrTy); - break; - - case eEncodingUint: - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return CompilerType (ast, ast->UnsignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return CompilerType (ast, ast->UnsignedIntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return CompilerType (ast, ast->UnsignedLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return CompilerType (ast, ast->UnsignedLongLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return CompilerType (ast, ast->UnsignedInt128Ty); - break; - - case eEncodingSint: - if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return CompilerType (ast, ast->SignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return CompilerType (ast, ast->ShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return CompilerType (ast, ast->IntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return CompilerType (ast, ast->LongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return CompilerType (ast, ast->LongLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return CompilerType (ast, ast->Int128Ty); - break; - - case eEncodingIEEE754: - if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return CompilerType (ast, ast->FloatTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return CompilerType (ast, ast->DoubleTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return CompilerType (ast, ast->LongDoubleTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->HalfTy)) - return CompilerType (ast, ast->HalfTy); - break; - - case eEncodingVector: - // Sanity check that bit_size is a multiple of 8's. - if (bit_size && !(bit_size & 0x7u)) - return CompilerType (ast, ast->getExtVectorType (ast->UnsignedCharTy, bit_size/8)); - break; - } - +CompilerType ClangASTContext::GetBuiltinTypeForEncodingAndBitSize( + ASTContext *ast, Encoding encoding, uint32_t bit_size) { + if (!ast) return CompilerType(); + switch (encoding) { + case eEncodingInvalid: + if (QualTypeMatchesBitSize(bit_size, ast, ast->VoidPtrTy)) + return CompilerType(ast, ast->VoidPtrTy); + break; + + case eEncodingUint: + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy)) + return CompilerType(ast, ast->UnsignedLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy)) + return CompilerType(ast, ast->UnsignedLongLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty)) + return CompilerType(ast, ast->UnsignedInt128Ty); + break; + + case eEncodingSint: + if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy)) + return CompilerType(ast, ast->SignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy)) + return CompilerType(ast, ast->ShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy)) + return CompilerType(ast, ast->IntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongTy)) + return CompilerType(ast, ast->LongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy)) + return CompilerType(ast, ast->LongLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty)) + return CompilerType(ast, ast->Int128Ty); + break; + + case eEncodingIEEE754: + if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy)) + return CompilerType(ast, ast->FloatTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy)) + return CompilerType(ast, ast->DoubleTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy)) + return CompilerType(ast, ast->LongDoubleTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->HalfTy)) + return CompilerType(ast, ast->HalfTy); + break; + + case eEncodingVector: + // Sanity check that bit_size is a multiple of 8's. + if (bit_size && !(bit_size & 0x7u)) + return CompilerType( + ast, ast->getExtVectorType(ast->UnsignedCharTy, bit_size / 8)); + break; + } + + return CompilerType(); } - - lldb::BasicType -ClangASTContext::GetBasicTypeEnumeration (const ConstString &name) -{ - if (name) - { - typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap; - static TypeNameToBasicTypeMap g_type_map; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, [](){ - // "void" - g_type_map.Append(ConstString("void").GetCString(), eBasicTypeVoid); - - // "char" - g_type_map.Append(ConstString("char").GetCString(), eBasicTypeChar); - g_type_map.Append(ConstString("signed char").GetCString(), eBasicTypeSignedChar); - g_type_map.Append(ConstString("unsigned char").GetCString(), eBasicTypeUnsignedChar); - g_type_map.Append(ConstString("wchar_t").GetCString(), eBasicTypeWChar); - g_type_map.Append(ConstString("signed wchar_t").GetCString(), eBasicTypeSignedWChar); - g_type_map.Append(ConstString("unsigned wchar_t").GetCString(), eBasicTypeUnsignedWChar); - // "short" - g_type_map.Append(ConstString("short").GetCString(), eBasicTypeShort); - g_type_map.Append(ConstString("short int").GetCString(), eBasicTypeShort); - g_type_map.Append(ConstString("unsigned short").GetCString(), eBasicTypeUnsignedShort); - g_type_map.Append(ConstString("unsigned short int").GetCString(), eBasicTypeUnsignedShort); - - // "int" - g_type_map.Append(ConstString("int").GetCString(), eBasicTypeInt); - g_type_map.Append(ConstString("signed int").GetCString(), eBasicTypeInt); - g_type_map.Append(ConstString("unsigned int").GetCString(), eBasicTypeUnsignedInt); - g_type_map.Append(ConstString("unsigned").GetCString(), eBasicTypeUnsignedInt); - - // "long" - g_type_map.Append(ConstString("long").GetCString(), eBasicTypeLong); - g_type_map.Append(ConstString("long int").GetCString(), eBasicTypeLong); - g_type_map.Append(ConstString("unsigned long").GetCString(), eBasicTypeUnsignedLong); - g_type_map.Append(ConstString("unsigned long int").GetCString(), eBasicTypeUnsignedLong); - - // "long long" - g_type_map.Append(ConstString("long long").GetCString(), eBasicTypeLongLong); - g_type_map.Append(ConstString("long long int").GetCString(), eBasicTypeLongLong); - g_type_map.Append(ConstString("unsigned long long").GetCString(), eBasicTypeUnsignedLongLong); - g_type_map.Append(ConstString("unsigned long long int").GetCString(), eBasicTypeUnsignedLongLong); - - // "int128" - g_type_map.Append(ConstString("__int128_t").GetCString(), eBasicTypeInt128); - g_type_map.Append(ConstString("__uint128_t").GetCString(), eBasicTypeUnsignedInt128); - - // Miscellaneous - g_type_map.Append(ConstString("bool").GetCString(), eBasicTypeBool); - g_type_map.Append(ConstString("float").GetCString(), eBasicTypeFloat); - g_type_map.Append(ConstString("double").GetCString(), eBasicTypeDouble); - g_type_map.Append(ConstString("long double").GetCString(), eBasicTypeLongDouble); - g_type_map.Append(ConstString("id").GetCString(), eBasicTypeObjCID); - g_type_map.Append(ConstString("SEL").GetCString(), eBasicTypeObjCSel); - g_type_map.Append(ConstString("nullptr").GetCString(), eBasicTypeNullPtr); - g_type_map.Sort(); - }); - - return g_type_map.Find(name.GetCString(), eBasicTypeInvalid); - } - return eBasicTypeInvalid; -} +ClangASTContext::GetBasicTypeEnumeration(const ConstString &name) { + if (name) { + typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap; + static TypeNameToBasicTypeMap g_type_map; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + // "void" + g_type_map.Append(ConstString("void").GetStringRef(), eBasicTypeVoid); + + // "char" + g_type_map.Append(ConstString("char").GetStringRef(), eBasicTypeChar); + g_type_map.Append(ConstString("signed char").GetStringRef(), + eBasicTypeSignedChar); + g_type_map.Append(ConstString("unsigned char").GetStringRef(), + eBasicTypeUnsignedChar); + g_type_map.Append(ConstString("wchar_t").GetStringRef(), eBasicTypeWChar); + g_type_map.Append(ConstString("signed wchar_t").GetStringRef(), + eBasicTypeSignedWChar); + g_type_map.Append(ConstString("unsigned wchar_t").GetStringRef(), + eBasicTypeUnsignedWChar); + // "short" + g_type_map.Append(ConstString("short").GetStringRef(), eBasicTypeShort); + g_type_map.Append(ConstString("short int").GetStringRef(), + eBasicTypeShort); + g_type_map.Append(ConstString("unsigned short").GetStringRef(), + eBasicTypeUnsignedShort); + g_type_map.Append(ConstString("unsigned short int").GetStringRef(), + eBasicTypeUnsignedShort); + + // "int" + g_type_map.Append(ConstString("int").GetStringRef(), eBasicTypeInt); + g_type_map.Append(ConstString("signed int").GetStringRef(), + eBasicTypeInt); + g_type_map.Append(ConstString("unsigned int").GetStringRef(), + eBasicTypeUnsignedInt); + g_type_map.Append(ConstString("unsigned").GetStringRef(), + eBasicTypeUnsignedInt); + + // "long" + g_type_map.Append(ConstString("long").GetStringRef(), eBasicTypeLong); + g_type_map.Append(ConstString("long int").GetStringRef(), eBasicTypeLong); + g_type_map.Append(ConstString("unsigned long").GetStringRef(), + eBasicTypeUnsignedLong); + g_type_map.Append(ConstString("unsigned long int").GetStringRef(), + eBasicTypeUnsignedLong); + + // "long long" + g_type_map.Append(ConstString("long long").GetStringRef(), + eBasicTypeLongLong); + g_type_map.Append(ConstString("long long int").GetStringRef(), + eBasicTypeLongLong); + g_type_map.Append(ConstString("unsigned long long").GetStringRef(), + eBasicTypeUnsignedLongLong); + g_type_map.Append(ConstString("unsigned long long int").GetStringRef(), + eBasicTypeUnsignedLongLong); + + // "int128" + g_type_map.Append(ConstString("__int128_t").GetStringRef(), + eBasicTypeInt128); + g_type_map.Append(ConstString("__uint128_t").GetStringRef(), + eBasicTypeUnsignedInt128); + + // Miscellaneous + g_type_map.Append(ConstString("bool").GetStringRef(), eBasicTypeBool); + g_type_map.Append(ConstString("float").GetStringRef(), eBasicTypeFloat); + g_type_map.Append(ConstString("double").GetStringRef(), eBasicTypeDouble); + g_type_map.Append(ConstString("long double").GetStringRef(), + eBasicTypeLongDouble); + g_type_map.Append(ConstString("id").GetStringRef(), eBasicTypeObjCID); + g_type_map.Append(ConstString("SEL").GetStringRef(), eBasicTypeObjCSel); + g_type_map.Append(ConstString("nullptr").GetStringRef(), + eBasicTypeNullPtr); + g_type_map.Sort(); + }); -CompilerType -ClangASTContext::GetBasicType (ASTContext *ast, const ConstString &name) -{ - if (ast) - { - lldb::BasicType basic_type = ClangASTContext::GetBasicTypeEnumeration (name); - return ClangASTContext::GetBasicType (ast, basic_type); - } - return CompilerType(); + return g_type_map.Find(name.GetStringRef(), eBasicTypeInvalid); + } + return eBasicTypeInvalid; } -uint32_t -ClangASTContext::GetPointerByteSize () -{ - if (m_pointer_byte_size == 0) - m_pointer_byte_size = GetBasicType(lldb::eBasicTypeVoid).GetPointerType().GetByteSize(nullptr); - return m_pointer_byte_size; +CompilerType ClangASTContext::GetBasicType(ASTContext *ast, + const ConstString &name) { + if (ast) { + lldb::BasicType basic_type = ClangASTContext::GetBasicTypeEnumeration(name); + return ClangASTContext::GetBasicType(ast, basic_type); + } + return CompilerType(); } -CompilerType -ClangASTContext::GetBasicType (lldb::BasicType basic_type) -{ - return GetBasicType (getASTContext(), basic_type); +uint32_t ClangASTContext::GetPointerByteSize() { + if (m_pointer_byte_size == 0) + m_pointer_byte_size = GetBasicType(lldb::eBasicTypeVoid) + .GetPointerType() + .GetByteSize(nullptr); + return m_pointer_byte_size; } -CompilerType -ClangASTContext::GetBasicType (ASTContext *ast, lldb::BasicType basic_type) -{ - if (!ast) - return CompilerType(); - lldb::opaque_compiler_type_t clang_type = GetOpaqueCompilerType(ast, basic_type); - - if (clang_type) - return CompilerType(GetASTContext(ast), clang_type); - return CompilerType(); +CompilerType ClangASTContext::GetBasicType(lldb::BasicType basic_type) { + return GetBasicType(getASTContext(), basic_type); } +CompilerType ClangASTContext::GetBasicType(ASTContext *ast, + lldb::BasicType basic_type) { + if (!ast) + return CompilerType(); + lldb::opaque_compiler_type_t clang_type = + GetOpaqueCompilerType(ast, basic_type); -CompilerType -ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name, uint32_t dw_ate, uint32_t bit_size) -{ - ASTContext *ast = getASTContext(); - -#define streq(a,b) strcmp(a,b) == 0 - assert (ast != nullptr); - if (ast) - { - switch (dw_ate) - { - default: - break; - - case DW_ATE_address: - if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) - return CompilerType (ast, ast->VoidPtrTy); - break; - - case DW_ATE_boolean: - if (QualTypeMatchesBitSize (bit_size, ast, ast->BoolTy)) - return CompilerType (ast, ast->BoolTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return CompilerType (ast, ast->UnsignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return CompilerType (ast, ast->UnsignedIntTy); - break; - - case DW_ATE_lo_user: - // This has been seen to mean DW_AT_complex_integer - if (type_name) - { - if (::strstr(type_name, "complex")) - { - CompilerType complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("int", DW_ATE_signed, bit_size/2); - return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType(complex_int_clang_type))); - } - } - break; - - case DW_ATE_complex_float: - if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatComplexTy)) - return CompilerType (ast, ast->FloatComplexTy); - else if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleComplexTy)) - return CompilerType (ast, ast->DoubleComplexTy); - else if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleComplexTy)) - return CompilerType (ast, ast->LongDoubleComplexTy); - else - { - CompilerType complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("float", DW_ATE_float, bit_size/2); - return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType(complex_float_clang_type))); - } - break; - - case DW_ATE_float: - if (streq(type_name, "float") && QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return CompilerType (ast, ast->FloatTy); - if (streq(type_name, "double") && QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return CompilerType (ast, ast->DoubleTy); - if (streq(type_name, "long double") && QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return CompilerType (ast, ast->LongDoubleTy); - // Fall back to not requiring a name match - if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return CompilerType (ast, ast->FloatTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return CompilerType (ast, ast->DoubleTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return CompilerType (ast, ast->LongDoubleTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->HalfTy)) - return CompilerType (ast, ast->HalfTy); - break; - - case DW_ATE_signed: - if (type_name) - { - if (streq(type_name, "wchar_t") && - QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy) && - (getTargetInfo() && TargetInfo::isTypeSigned (getTargetInfo()->getWCharType()))) - return CompilerType (ast, ast->WCharTy); - if (streq(type_name, "void") && - QualTypeMatchesBitSize (bit_size, ast, ast->VoidTy)) - return CompilerType (ast, ast->VoidTy); - if (strstr(type_name, "long long") && - QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return CompilerType (ast, ast->LongLongTy); - if (strstr(type_name, "long") && - QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return CompilerType (ast, ast->LongTy); - if (strstr(type_name, "short") && - QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return CompilerType (ast, ast->ShortTy); - if (strstr(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return CompilerType (ast, ast->CharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return CompilerType (ast, ast->SignedCharTy); - } - if (strstr(type_name, "int")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return CompilerType (ast, ast->IntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return CompilerType (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 CompilerType (ast, ast->CharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return CompilerType (ast, ast->ShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return CompilerType (ast, ast->IntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return CompilerType (ast, ast->LongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return CompilerType (ast, ast->LongLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return CompilerType (ast, ast->Int128Ty); - break; + if (clang_type) + return CompilerType(GetASTContext(ast), clang_type); + return CompilerType(); +} - case DW_ATE_signed_char: - if (ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return CompilerType (ast, ast->CharTy); - } - if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return CompilerType (ast, ast->SignedCharTy); - break; - - case DW_ATE_unsigned: - if (type_name) - { - if (streq(type_name, "wchar_t")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy)) - { - if (!(getTargetInfo() && TargetInfo::isTypeSigned (getTargetInfo()->getWCharType()))) - return CompilerType (ast, ast->WCharTy); - } - } - if (strstr(type_name, "long long")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return CompilerType (ast, ast->UnsignedLongLongTy); - } - else if (strstr(type_name, "long")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return CompilerType (ast, ast->UnsignedLongTy); - } - else if (strstr(type_name, "short")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - } - else if (strstr(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return CompilerType (ast, ast->UnsignedCharTy); - } - else if (strstr(type_name, "int")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return CompilerType (ast, ast->UnsignedIntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return CompilerType (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 CompilerType (ast, ast->UnsignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return CompilerType (ast, ast->UnsignedIntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return CompilerType (ast, ast->UnsignedLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return CompilerType (ast, ast->UnsignedLongLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return CompilerType (ast, ast->UnsignedInt128Ty); - break; +CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize( + const char *type_name, uint32_t dw_ate, uint32_t bit_size) { + ASTContext *ast = getASTContext(); - case DW_ATE_unsigned_char: - if (!ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return CompilerType (ast, ast->CharTy); - } - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return CompilerType (ast, ast->UnsignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - break; - - case DW_ATE_imaginary_float: - break; - - case DW_ATE_UTF: - if (type_name) - { - if (streq(type_name, "char16_t")) - { - return CompilerType (ast, ast->Char16Ty); - } - else if (streq(type_name, "char32_t")) - { - return CompilerType (ast, ast->Char32Ty); - } - } - break; +#define streq(a, b) strcmp(a, b) == 0 + assert(ast != nullptr); + if (ast) { + switch (dw_ate) { + default: + break; + + case DW_ATE_address: + if (QualTypeMatchesBitSize(bit_size, ast, ast->VoidPtrTy)) + return CompilerType(ast, ast->VoidPtrTy); + break; + + case DW_ATE_boolean: + if (QualTypeMatchesBitSize(bit_size, ast, ast->BoolTy)) + return CompilerType(ast, ast->BoolTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + break; + + case DW_ATE_lo_user: + // This has been seen to mean DW_AT_complex_integer + if (type_name) { + if (::strstr(type_name, "complex")) { + CompilerType complex_int_clang_type = + GetBuiltinTypeForDWARFEncodingAndBitSize("int", DW_ATE_signed, + bit_size / 2); + return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType( + complex_int_clang_type))); } + } + break; + + case DW_ATE_complex_float: + if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatComplexTy)) + return CompilerType(ast, ast->FloatComplexTy); + else if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleComplexTy)) + return CompilerType(ast, ast->DoubleComplexTy); + else if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleComplexTy)) + return CompilerType(ast, ast->LongDoubleComplexTy); + else { + CompilerType complex_float_clang_type = + GetBuiltinTypeForDWARFEncodingAndBitSize("float", DW_ATE_float, + bit_size / 2); + return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType( + complex_float_clang_type))); + } + break; + + case DW_ATE_float: + if (streq(type_name, "float") && + QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy)) + return CompilerType(ast, ast->FloatTy); + if (streq(type_name, "double") && + QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy)) + return CompilerType(ast, ast->DoubleTy); + if (streq(type_name, "long double") && + QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy)) + return CompilerType(ast, ast->LongDoubleTy); + // Fall back to not requiring a name match + if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy)) + return CompilerType(ast, ast->FloatTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy)) + return CompilerType(ast, ast->DoubleTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy)) + return CompilerType(ast, ast->LongDoubleTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->HalfTy)) + return CompilerType(ast, ast->HalfTy); + break; + + case DW_ATE_signed: + if (type_name) { + if (streq(type_name, "wchar_t") && + QualTypeMatchesBitSize(bit_size, ast, ast->WCharTy) && + (getTargetInfo() && + TargetInfo::isTypeSigned(getTargetInfo()->getWCharType()))) + return CompilerType(ast, ast->WCharTy); + if (streq(type_name, "void") && + QualTypeMatchesBitSize(bit_size, ast, ast->VoidTy)) + return CompilerType(ast, ast->VoidTy); + if (strstr(type_name, "long long") && + QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy)) + return CompilerType(ast, ast->LongLongTy); + if (strstr(type_name, "long") && + QualTypeMatchesBitSize(bit_size, ast, ast->LongTy)) + return CompilerType(ast, ast->LongTy); + if (strstr(type_name, "short") && + QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy)) + return CompilerType(ast, ast->ShortTy); + if (strstr(type_name, "char")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy)) + return CompilerType(ast, ast->CharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy)) + return CompilerType(ast, ast->SignedCharTy); + } + if (strstr(type_name, "int")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy)) + return CompilerType(ast, ast->IntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty)) + return CompilerType(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 CompilerType(ast, ast->CharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy)) + return CompilerType(ast, ast->ShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy)) + return CompilerType(ast, ast->IntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongTy)) + return CompilerType(ast, ast->LongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy)) + return CompilerType(ast, ast->LongLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty)) + return CompilerType(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 CompilerType(ast, ast->CharTy); + } + if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy)) + return CompilerType(ast, ast->SignedCharTy); + break; + + case DW_ATE_unsigned: + if (type_name) { + if (streq(type_name, "wchar_t")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->WCharTy)) { + if (!(getTargetInfo() && + TargetInfo::isTypeSigned(getTargetInfo()->getWCharType()))) + return CompilerType(ast, ast->WCharTy); + } + } + if (strstr(type_name, "long long")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy)) + return CompilerType(ast, ast->UnsignedLongLongTy); + } else if (strstr(type_name, "long")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy)) + return CompilerType(ast, ast->UnsignedLongTy); + } else if (strstr(type_name, "short")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + } else if (strstr(type_name, "char")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + } else if (strstr(type_name, "int")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty)) + return CompilerType(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 CompilerType(ast, ast->UnsignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy)) + return CompilerType(ast, ast->UnsignedLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy)) + return CompilerType(ast, ast->UnsignedLongLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty)) + return CompilerType(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 CompilerType(ast, ast->CharTy); + } + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + break; + + case DW_ATE_imaginary_float: + break; + + case DW_ATE_UTF: + if (type_name) { + if (streq(type_name, "char16_t")) { + return CompilerType(ast, ast->Char16Ty); + } else if (streq(type_name, "char32_t")) { + return CompilerType(ast, ast->Char32Ty); + } + } + break; } - // This assert should fire for anything that we don't catch above so we know - // to fix any issues we run into. - if (type_name) - { - Host::SystemLog (Host::eSystemLogError, "error: need to add support for DW_TAG_base_type '%s' encoded with DW_ATE = 0x%x, bit_size = %u\n", type_name, dw_ate, bit_size); - } - else - { - Host::SystemLog (Host::eSystemLogError, "error: need to add support for DW_TAG_base_type encoded with DW_ATE = 0x%x, bit_size = %u\n", dw_ate, bit_size); - } - return CompilerType (); + } + // This assert should fire for anything that we don't catch above so we know + // to fix any issues we run into. + if (type_name) { + Host::SystemLog(Host::eSystemLogError, "error: need to add support for " + "DW_TAG_base_type '%s' encoded with " + "DW_ATE = 0x%x, bit_size = %u\n", + type_name, dw_ate, bit_size); + } else { + Host::SystemLog(Host::eSystemLogError, "error: need to add support for " + "DW_TAG_base_type encoded with " + "DW_ATE = 0x%x, bit_size = %u\n", + dw_ate, bit_size); + } + return CompilerType(); } -CompilerType -ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast) -{ - if (ast) - return CompilerType (ast, ast->UnknownAnyTy); - return CompilerType(); +CompilerType ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast) { + if (ast) + return CompilerType(ast, ast->UnknownAnyTy); + return CompilerType(); } -CompilerType -ClangASTContext::GetCStringType (bool is_const) -{ - ASTContext *ast = getASTContext(); - QualType char_type(ast->CharTy); - - if (is_const) - char_type.addConst(); - - return CompilerType (ast, ast->getPointerType(char_type)); +CompilerType ClangASTContext::GetCStringType(bool is_const) { + ASTContext *ast = getASTContext(); + QualType char_type(ast->CharTy); + + if (is_const) + char_type.addConst(); + + return CompilerType(ast, ast->getPointerType(char_type)); } clang::DeclContext * -ClangASTContext::GetTranslationUnitDecl (clang::ASTContext *ast) -{ - return ast->getTranslationUnitDecl(); -} - -clang::Decl * -ClangASTContext::CopyDecl (ASTContext *dst_ast, - ASTContext *src_ast, - clang::Decl *source_decl) -{ - FileSystemOptions file_system_options; - FileManager file_manager (file_system_options); - ASTImporter importer(*dst_ast, file_manager, - *src_ast, file_manager, - false); - - return importer.Import(source_decl); -} - -bool -ClangASTContext::AreTypesSame (CompilerType type1, - CompilerType type2, - bool ignore_qualifiers) -{ - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type1.GetTypeSystem()); - if (!ast || ast != type2.GetTypeSystem()) - return false; - - if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType()) - return true; +ClangASTContext::GetTranslationUnitDecl(clang::ASTContext *ast) { + return ast->getTranslationUnitDecl(); +} - QualType type1_qual = ClangUtil::GetQualType(type1); - QualType type2_qual = ClangUtil::GetQualType(type2); +clang::Decl *ClangASTContext::CopyDecl(ASTContext *dst_ast, ASTContext *src_ast, + clang::Decl *source_decl) { + FileSystemOptions file_system_options; + FileManager file_manager(file_system_options); + ASTImporter importer(*dst_ast, file_manager, *src_ast, file_manager, false); - if (ignore_qualifiers) - { - type1_qual = type1_qual.getUnqualifiedType(); - type2_qual = type2_qual.getUnqualifiedType(); - } - - return ast->getASTContext()->hasSameType (type1_qual, type2_qual); + return importer.Import(source_decl); } -CompilerType -ClangASTContext::GetTypeForDecl (clang::NamedDecl *decl) -{ - if (clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) - return GetTypeForDecl(interface_decl); - if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) - return GetTypeForDecl(tag_decl); - return CompilerType(); +bool ClangASTContext::AreTypesSame(CompilerType type1, CompilerType type2, + bool ignore_qualifiers) { + ClangASTContext *ast = + llvm::dyn_cast_or_null<ClangASTContext>(type1.GetTypeSystem()); + if (!ast || ast != type2.GetTypeSystem()) + return false; + + if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType()) + return true; + + QualType type1_qual = ClangUtil::GetQualType(type1); + QualType type2_qual = ClangUtil::GetQualType(type2); + + if (ignore_qualifiers) { + type1_qual = type1_qual.getUnqualifiedType(); + type2_qual = type2_qual.getUnqualifiedType(); + } + + return ast->getASTContext()->hasSameType(type1_qual, type2_qual); } +CompilerType ClangASTContext::GetTypeForDecl(clang::NamedDecl *decl) { + if (clang::ObjCInterfaceDecl *interface_decl = + llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) + return GetTypeForDecl(interface_decl); + if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) + return GetTypeForDecl(tag_decl); + return CompilerType(); +} -CompilerType -ClangASTContext::GetTypeForDecl (TagDecl *decl) -{ - // No need to call the getASTContext() accessor (which can create the AST - // if it isn't created yet, because we can't have created a decl in this - // AST if our AST didn't already exist... - ASTContext *ast = &decl->getASTContext(); - if (ast) - return CompilerType (ast, ast->getTagDeclType(decl)); - return CompilerType(); +CompilerType ClangASTContext::GetTypeForDecl(TagDecl *decl) { + // No need to call the getASTContext() accessor (which can create the AST + // if it isn't created yet, because we can't have created a decl in this + // AST if our AST didn't already exist... + ASTContext *ast = &decl->getASTContext(); + if (ast) + return CompilerType(ast, ast->getTagDeclType(decl)); + return CompilerType(); } -CompilerType -ClangASTContext::GetTypeForDecl (ObjCInterfaceDecl *decl) -{ - // No need to call the getASTContext() accessor (which can create the AST - // if it isn't created yet, because we can't have created a decl in this - // AST if our AST didn't already exist... - ASTContext *ast = &decl->getASTContext(); - if (ast) - return CompilerType (ast, ast->getObjCInterfaceType(decl)); - return CompilerType(); +CompilerType ClangASTContext::GetTypeForDecl(ObjCInterfaceDecl *decl) { + // No need to call the getASTContext() accessor (which can create the AST + // if it isn't created yet, because we can't have created a decl in this + // AST if our AST didn't already exist... + ASTContext *ast = &decl->getASTContext(); + if (ast) + return CompilerType(ast, ast->getObjCInterfaceType(decl)); + return CompilerType(); } #pragma mark Structure, Unions, Classes -CompilerType -ClangASTContext::CreateRecordType (DeclContext *decl_ctx, - AccessType access_type, - const char *name, - int kind, - LanguageType language, - ClangASTMetadata *metadata) -{ - ASTContext *ast = getASTContext(); - assert (ast != nullptr); - - if (decl_ctx == nullptr) - decl_ctx = ast->getTranslationUnitDecl(); - - - if (language == eLanguageTypeObjC || language == eLanguageTypeObjC_plus_plus) - { - bool isForwardDecl = true; - bool isInternal = false; - return CreateObjCClass (name, decl_ctx, isForwardDecl, isInternal, metadata); - } - - // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and - // we will need to update this code. I was told to currently always use - // the CXXRecordDecl class since we often don't know from debug information - // if something is struct or a class, so we default to always use the more - // complete definition just in case. - - bool is_anonymous = (!name) || (!name[0]); - - CXXRecordDecl *decl = CXXRecordDecl::Create (*ast, - (TagDecl::TagKind)kind, - decl_ctx, - SourceLocation(), - SourceLocation(), - is_anonymous ? nullptr : &ast->Idents.get(name)); - - if (is_anonymous) - decl->setAnonymousStructOrUnion(true); - - if (decl) - { - if (metadata) - SetMetadata(ast, decl, *metadata); +CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx, + AccessType access_type, + const char *name, int kind, + LanguageType language, + ClangASTMetadata *metadata) { + ASTContext *ast = getASTContext(); + assert(ast != nullptr); - if (access_type != eAccessNone) - decl->setAccess (ConvertAccessTypeToAccessSpecifier (access_type)); - - if (decl_ctx) - decl_ctx->addDecl (decl); + if (decl_ctx == nullptr) + decl_ctx = ast->getTranslationUnitDecl(); - return CompilerType(ast, ast->getTagDeclType(decl)); - } - return CompilerType(); -} + if (language == eLanguageTypeObjC || + language == eLanguageTypeObjC_plus_plus) { + bool isForwardDecl = true; + bool isInternal = false; + return CreateObjCClass(name, decl_ctx, isForwardDecl, isInternal, metadata); + } -static TemplateParameterList * -CreateTemplateParameterList (ASTContext *ast, - const ClangASTContext::TemplateParameterInfos &template_param_infos, - llvm::SmallVector<NamedDecl *, 8> &template_param_decls) -{ - const bool parameter_pack = false; - const bool is_typename = false; - const unsigned depth = 0; - const size_t num_template_params = template_param_infos.GetSize(); - for (size_t i=0; i<num_template_params; ++i) - { - const char *name = template_param_infos.names[i]; - - IdentifierInfo *identifier_info = nullptr; - if (name && name[0]) - identifier_info = &ast->Idents.get(name); - if (template_param_infos.args[i].getKind() == TemplateArgument::Integral) - { - template_param_decls.push_back (NonTypeTemplateParmDecl::Create (*ast, - ast->getTranslationUnitDecl(), // Is this the right decl context?, SourceLocation StartLoc, - SourceLocation(), - SourceLocation(), - depth, - i, - identifier_info, - template_param_infos.args[i].getIntegralType(), - parameter_pack, - nullptr)); - - } - else - { - template_param_decls.push_back (TemplateTypeParmDecl::Create (*ast, - ast->getTranslationUnitDecl(), // Is this the right decl context? - SourceLocation(), - SourceLocation(), - depth, - i, - identifier_info, - is_typename, - parameter_pack)); - } - } + // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and + // we will need to update this code. I was told to currently always use + // the CXXRecordDecl class since we often don't know from debug information + // if something is struct or a class, so we default to always use the more + // complete definition just in case. + + bool is_anonymous = (!name) || (!name[0]); - TemplateParameterList *template_param_list = TemplateParameterList::Create (*ast, - SourceLocation(), - SourceLocation(), - template_param_decls, - SourceLocation()); - return template_param_list; + CXXRecordDecl *decl = CXXRecordDecl::Create( + *ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), + SourceLocation(), is_anonymous ? nullptr : &ast->Idents.get(name)); + + if (is_anonymous) + decl->setAnonymousStructOrUnion(true); + + if (decl) { + if (metadata) + SetMetadata(ast, decl, *metadata); + + if (access_type != eAccessNone) + decl->setAccess(ConvertAccessTypeToAccessSpecifier(access_type)); + + if (decl_ctx) + decl_ctx->addDecl(decl); + + return CompilerType(ast, ast->getTagDeclType(decl)); + } + return CompilerType(); } -clang::FunctionTemplateDecl * -ClangASTContext::CreateFunctionTemplateDecl (clang::DeclContext *decl_ctx, - clang::FunctionDecl *func_decl, - const char *name, - const TemplateParameterInfos &template_param_infos) -{ -// /// \brief Create a function template node. - ASTContext *ast = getASTContext(); - - llvm::SmallVector<NamedDecl *, 8> template_param_decls; - - TemplateParameterList *template_param_list = CreateTemplateParameterList (ast, - template_param_infos, - template_param_decls); - FunctionTemplateDecl *func_tmpl_decl = FunctionTemplateDecl::Create (*ast, - decl_ctx, - func_decl->getLocation(), - func_decl->getDeclName(), - template_param_list, - func_decl); - - for (size_t i=0, template_param_decl_count = template_param_decls.size(); - i < template_param_decl_count; - ++i) - { - // TODO: verify which decl context we should put template_param_decls into.. - template_param_decls[i]->setDeclContext (func_decl); - } - - return func_tmpl_decl; -} - -void -ClangASTContext::CreateFunctionTemplateSpecializationInfo (FunctionDecl *func_decl, - clang::FunctionTemplateDecl *func_tmpl_decl, - const TemplateParameterInfos &infos) -{ - TemplateArgumentList template_args (TemplateArgumentList::OnStack, infos.args); - - func_decl->setFunctionTemplateSpecialization (func_tmpl_decl, - &template_args, - nullptr); -} - - -ClassTemplateDecl * -ClangASTContext::CreateClassTemplateDecl (DeclContext *decl_ctx, - lldb::AccessType access_type, - const char *class_name, - int kind, - const TemplateParameterInfos &template_param_infos) -{ - ASTContext *ast = getASTContext(); - - ClassTemplateDecl *class_template_decl = nullptr; - if (decl_ctx == nullptr) - decl_ctx = ast->getTranslationUnitDecl(); - - IdentifierInfo &identifier_info = ast->Idents.get(class_name); - DeclarationName decl_name (&identifier_info); +static TemplateParameterList *CreateTemplateParameterList( + ASTContext *ast, + const ClangASTContext::TemplateParameterInfos &template_param_infos, + llvm::SmallVector<NamedDecl *, 8> &template_param_decls) { + const bool parameter_pack = false; + const bool is_typename = false; + const unsigned depth = 0; + const size_t num_template_params = template_param_infos.GetSize(); + for (size_t i = 0; i < num_template_params; ++i) { + const char *name = template_param_infos.names[i]; + + IdentifierInfo *identifier_info = nullptr; + if (name && name[0]) + identifier_info = &ast->Idents.get(name); + if (template_param_infos.args[i].getKind() == TemplateArgument::Integral) { + template_param_decls.push_back(NonTypeTemplateParmDecl::Create( + *ast, + ast->getTranslationUnitDecl(), // Is this the right decl context?, + // SourceLocation StartLoc, + SourceLocation(), SourceLocation(), depth, i, identifier_info, + template_param_infos.args[i].getIntegralType(), parameter_pack, + nullptr)); + + } else { + template_param_decls.push_back(TemplateTypeParmDecl::Create( + *ast, + ast->getTranslationUnitDecl(), // Is this the right decl context? + SourceLocation(), SourceLocation(), depth, i, identifier_info, + is_typename, parameter_pack)); + } + } + + clang::Expr *const requires_clause = nullptr; // TODO: Concepts + TemplateParameterList *template_param_list = TemplateParameterList::Create( + *ast, SourceLocation(), SourceLocation(), template_param_decls, + SourceLocation(), requires_clause); + return template_param_list; +} + +clang::FunctionTemplateDecl *ClangASTContext::CreateFunctionTemplateDecl( + clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl, + const char *name, const TemplateParameterInfos &template_param_infos) { + // /// \brief Create a function template node. + ASTContext *ast = getASTContext(); + + llvm::SmallVector<NamedDecl *, 8> template_param_decls; + + TemplateParameterList *template_param_list = CreateTemplateParameterList( + ast, template_param_infos, template_param_decls); + FunctionTemplateDecl *func_tmpl_decl = FunctionTemplateDecl::Create( + *ast, decl_ctx, func_decl->getLocation(), func_decl->getDeclName(), + template_param_list, func_decl); + + for (size_t i = 0, template_param_decl_count = template_param_decls.size(); + i < template_param_decl_count; ++i) { + // TODO: verify which decl context we should put template_param_decls into.. + template_param_decls[i]->setDeclContext(func_decl); + } + + return func_tmpl_decl; +} + +void ClangASTContext::CreateFunctionTemplateSpecializationInfo( + FunctionDecl *func_decl, clang::FunctionTemplateDecl *func_tmpl_decl, + const TemplateParameterInfos &infos) { + TemplateArgumentList template_args(TemplateArgumentList::OnStack, infos.args); + + func_decl->setFunctionTemplateSpecialization(func_tmpl_decl, &template_args, + nullptr); +} - clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); - - for (NamedDecl *decl : result) - { - class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl); - if (class_template_decl) - return class_template_decl; - } - - llvm::SmallVector<NamedDecl *, 8> template_param_decls; - - TemplateParameterList *template_param_list = CreateTemplateParameterList (ast, - template_param_infos, - template_param_decls); - - CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create (*ast, - (TagDecl::TagKind)kind, - decl_ctx, // What decl context do we use here? TU? The actual decl context? - SourceLocation(), - SourceLocation(), - &identifier_info); - - for (size_t i=0, template_param_decl_count = template_param_decls.size(); - i < template_param_decl_count; - ++i) - { - template_param_decls[i]->setDeclContext (template_cxx_decl); - } - - // With templated classes, we say that a class is templated with - // specializations, but that the bare class has no functions. - //template_cxx_decl->startDefinition(); - //template_cxx_decl->completeDefinition(); - - class_template_decl = ClassTemplateDecl::Create (*ast, - decl_ctx, // What decl context do we use here? TU? The actual decl context? - SourceLocation(), - decl_name, - template_param_list, - template_cxx_decl, - nullptr); - +ClassTemplateDecl *ClangASTContext::CreateClassTemplateDecl( + DeclContext *decl_ctx, lldb::AccessType access_type, const char *class_name, + int kind, const TemplateParameterInfos &template_param_infos) { + ASTContext *ast = getASTContext(); + + ClassTemplateDecl *class_template_decl = nullptr; + if (decl_ctx == nullptr) + decl_ctx = ast->getTranslationUnitDecl(); + + IdentifierInfo &identifier_info = ast->Idents.get(class_name); + DeclarationName decl_name(&identifier_info); + + clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); + + for (NamedDecl *decl : result) { + class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl); if (class_template_decl) - { - if (access_type != eAccessNone) - class_template_decl->setAccess (ConvertAccessTypeToAccessSpecifier (access_type)); - - //if (TagDecl *ctx_tag_decl = dyn_cast<TagDecl>(decl_ctx)) - // CompleteTagDeclarationDefinition(GetTypeForDecl(ctx_tag_decl)); - - decl_ctx->addDecl (class_template_decl); - + return class_template_decl; + } + + llvm::SmallVector<NamedDecl *, 8> template_param_decls; + + TemplateParameterList *template_param_list = CreateTemplateParameterList( + ast, template_param_infos, template_param_decls); + + CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create( + *ast, (TagDecl::TagKind)kind, + decl_ctx, // What decl context do we use here? TU? The actual decl + // context? + SourceLocation(), SourceLocation(), &identifier_info); + + for (size_t i = 0, template_param_decl_count = template_param_decls.size(); + i < template_param_decl_count; ++i) { + template_param_decls[i]->setDeclContext(template_cxx_decl); + } + + // With templated classes, we say that a class is templated with + // specializations, but that the bare class has no functions. + // template_cxx_decl->startDefinition(); + // template_cxx_decl->completeDefinition(); + + class_template_decl = ClassTemplateDecl::Create( + *ast, + decl_ctx, // What decl context do we use here? TU? The actual decl + // context? + SourceLocation(), decl_name, template_param_list, template_cxx_decl, + nullptr); + + if (class_template_decl) { + if (access_type != eAccessNone) + class_template_decl->setAccess( + ConvertAccessTypeToAccessSpecifier(access_type)); + + // if (TagDecl *ctx_tag_decl = dyn_cast<TagDecl>(decl_ctx)) + // CompleteTagDeclarationDefinition(GetTypeForDecl(ctx_tag_decl)); + + decl_ctx->addDecl(class_template_decl); + #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(class_template_decl); + VerifyDecl(class_template_decl); #endif - } + } - return class_template_decl; + return class_template_decl; } - ClassTemplateSpecializationDecl * -ClangASTContext::CreateClassTemplateSpecializationDecl (DeclContext *decl_ctx, - ClassTemplateDecl *class_template_decl, - int kind, - const TemplateParameterInfos &template_param_infos) -{ - ASTContext *ast = getASTContext(); - ClassTemplateSpecializationDecl *class_template_specialization_decl = ClassTemplateSpecializationDecl::Create (*ast, - (TagDecl::TagKind)kind, - decl_ctx, - SourceLocation(), - SourceLocation(), - class_template_decl, - template_param_infos.args, - nullptr); - - class_template_specialization_decl->setSpecializationKind(TSK_ExplicitSpecialization); - - return class_template_specialization_decl; -} +ClangASTContext::CreateClassTemplateSpecializationDecl( + DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind, + const TemplateParameterInfos &template_param_infos) { + ASTContext *ast = getASTContext(); + ClassTemplateSpecializationDecl *class_template_specialization_decl = + ClassTemplateSpecializationDecl::Create( + *ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), + SourceLocation(), class_template_decl, template_param_infos.args, + nullptr); -CompilerType -ClangASTContext::CreateClassTemplateSpecializationType (ClassTemplateSpecializationDecl *class_template_specialization_decl) -{ - if (class_template_specialization_decl) - { - ASTContext *ast = getASTContext(); - if (ast) - return CompilerType(ast, ast->getTagDeclType(class_template_specialization_decl)); - } - return CompilerType(); + class_template_specialization_decl->setSpecializationKind( + TSK_ExplicitSpecialization); + + return class_template_specialization_decl; } -static inline bool -check_op_param (uint32_t op_kind, bool unary, bool binary, uint32_t num_params) -{ - // Special-case call since it can take any number of operands - if(op_kind == OO_Call) - return true; - - // The parameter count doesn't include "this" - if (num_params == 0) - return unary; - if (num_params == 1) - return binary; - else +CompilerType ClangASTContext::CreateClassTemplateSpecializationType( + ClassTemplateSpecializationDecl *class_template_specialization_decl) { + if (class_template_specialization_decl) { + ASTContext *ast = getASTContext(); + if (ast) + return CompilerType( + ast, ast->getTagDeclType(class_template_specialization_decl)); + } + return CompilerType(); +} + +static inline bool check_op_param(bool is_method, + clang::OverloadedOperatorKind op_kind, + bool unary, bool binary, + uint32_t num_params) { + // Special-case call since it can take any number of operands + if (op_kind == OO_Call) + return true; + + // The parameter count doesn't include "this" + if (is_method) + ++num_params; + if (num_params == 1) + return unary; + if (num_params == 2) + return binary; + else return false; } -bool -ClangASTContext::CheckOverloadedOperatorKindParameterCount (uint32_t op_kind, uint32_t num_params) -{ - switch (op_kind) - { - default: - break; - // C++ standard allows any number of arguments to new/delete - case OO_New: - case OO_Array_New: - case OO_Delete: - case OO_Array_Delete: - return true; - } - -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) case OO_##Name: return check_op_param (op_kind, Unary, Binary, num_params); - switch (op_kind) - { +bool ClangASTContext::CheckOverloadedOperatorKindParameterCount( + bool is_method, clang::OverloadedOperatorKind op_kind, + uint32_t num_params) { + switch (op_kind) { + default: + break; + // C++ standard allows any number of arguments to new/delete + case OO_New: + case OO_Array_New: + case OO_Delete: + case OO_Array_Delete: + return true; + } + +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + case OO_##Name: \ + return check_op_param(is_method, op_kind, Unary, Binary, num_params); + switch (op_kind) { #include "clang/Basic/OperatorKinds.def" - default: break; - } - return false; + default: + break; + } + return false; } clang::AccessSpecifier -ClangASTContext::UnifyAccessSpecifiers (clang::AccessSpecifier lhs, clang::AccessSpecifier rhs) -{ - // Make the access equal to the stricter of the field and the nested field's access - if (lhs == AS_none || rhs == AS_none) - return AS_none; - if (lhs == AS_private || rhs == AS_private) - return AS_private; - if (lhs == AS_protected || rhs == AS_protected) - return AS_protected; - return AS_public; +ClangASTContext::UnifyAccessSpecifiers(clang::AccessSpecifier lhs, + clang::AccessSpecifier rhs) { + // Make the access equal to the stricter of the field and the nested field's + // access + if (lhs == AS_none || rhs == AS_none) + return AS_none; + if (lhs == AS_private || rhs == AS_private) + return AS_private; + if (lhs == AS_protected || rhs == AS_protected) + return AS_protected; + return AS_public; } -bool -ClangASTContext::FieldIsBitfield (FieldDecl* field, uint32_t& bitfield_bit_size) -{ - return FieldIsBitfield(getASTContext(), field, bitfield_bit_size); +bool ClangASTContext::FieldIsBitfield(FieldDecl *field, + uint32_t &bitfield_bit_size) { + return FieldIsBitfield(getASTContext(), field, bitfield_bit_size); } -bool -ClangASTContext::FieldIsBitfield -( - ASTContext *ast, - FieldDecl* field, - uint32_t& bitfield_bit_size -) -{ - if (ast == nullptr || field == nullptr) - return false; +bool ClangASTContext::FieldIsBitfield(ASTContext *ast, FieldDecl *field, + uint32_t &bitfield_bit_size) { + if (ast == nullptr || field == nullptr) + return false; - if (field->isBitField()) - { - Expr* bit_width_expr = field->getBitWidth(); - if (bit_width_expr) - { - llvm::APSInt bit_width_apsint; - if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, *ast)) - { - bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX); - return true; - } - } + if (field->isBitField()) { + Expr *bit_width_expr = field->getBitWidth(); + if (bit_width_expr) { + llvm::APSInt bit_width_apsint; + if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, *ast)) { + bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX); + return true; + } } - return false; + } + return false; } -bool -ClangASTContext::RecordHasFields (const RecordDecl *record_decl) -{ - if (record_decl == nullptr) - return false; +bool ClangASTContext::RecordHasFields(const RecordDecl *record_decl) { + if (record_decl == nullptr) + return false; - if (!record_decl->field_empty()) - return true; + if (!record_decl->field_empty()) + return true; - // No fields, lets check this is a CXX record and check the base classes - const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl); - if (cxx_record_decl) - { - 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 CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl()); - if (RecordHasFields(base_class_decl)) - return true; - } + // No fields, lets check this is a CXX record and check the base classes + const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl); + if (cxx_record_decl) { + 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 CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>( + base_class->getType()->getAs<RecordType>()->getDecl()); + if (RecordHasFields(base_class_decl)) + return true; } - return false; + } + return false; } #pragma mark Objective C Classes -CompilerType -ClangASTContext::CreateObjCClass -( - const char *name, - DeclContext *decl_ctx, - bool isForwardDecl, - bool isInternal, - ClangASTMetadata *metadata -) -{ - ASTContext *ast = getASTContext(); - assert (ast != nullptr); - assert (name && name[0]); - if (decl_ctx == nullptr) - decl_ctx = ast->getTranslationUnitDecl(); - - ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create (*ast, - decl_ctx, - SourceLocation(), - &ast->Idents.get(name), - nullptr, - nullptr, - SourceLocation(), - /*isForwardDecl,*/ - isInternal); - - if (decl && metadata) - SetMetadata(ast, decl, *metadata); - - return CompilerType (ast, ast->getObjCInterfaceType(decl)); +CompilerType ClangASTContext::CreateObjCClass(const char *name, + DeclContext *decl_ctx, + bool isForwardDecl, + bool isInternal, + ClangASTMetadata *metadata) { + ASTContext *ast = getASTContext(); + assert(ast != nullptr); + assert(name && name[0]); + if (decl_ctx == nullptr) + decl_ctx = ast->getTranslationUnitDecl(); + + ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create( + *ast, decl_ctx, SourceLocation(), &ast->Idents.get(name), nullptr, + nullptr, SourceLocation(), + /*isForwardDecl,*/ + isInternal); + + if (decl && metadata) + SetMetadata(ast, decl, *metadata); + + return CompilerType(ast, ast->getObjCInterfaceType(decl)); } -static inline bool -BaseSpecifierIsEmpty (const CXXBaseSpecifier *b) -{ - return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == false; +static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) { + return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == + false; } uint32_t -ClangASTContext::GetNumBaseClasses (const CXXRecordDecl *cxx_record_decl, bool omit_empty_base_classes) -{ - uint32_t num_bases = 0; - if (cxx_record_decl) - { - if (omit_empty_base_classes) - { - 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 - if (omit_empty_base_classes) - { - if (BaseSpecifierIsEmpty (base_class)) - continue; - } - ++num_bases; - } +ClangASTContext::GetNumBaseClasses(const CXXRecordDecl *cxx_record_decl, + bool omit_empty_base_classes) { + uint32_t num_bases = 0; + if (cxx_record_decl) { + if (omit_empty_base_classes) { + 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 + if (omit_empty_base_classes) { + if (BaseSpecifierIsEmpty(base_class)) + continue; } - else - num_bases = cxx_record_decl->getNumBases(); - } - return num_bases; + ++num_bases; + } + } else + num_bases = cxx_record_decl->getNumBases(); + } + return num_bases; } - #pragma mark Namespace Declarations NamespaceDecl * -ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *decl_ctx) -{ - NamespaceDecl *namespace_decl = nullptr; - ASTContext *ast = getASTContext(); - TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl (); - if (decl_ctx == nullptr) - decl_ctx = translation_unit_decl; - - if (name) - { - IdentifierInfo &identifier_info = ast->Idents.get(name); - DeclarationName decl_name (&identifier_info); - clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); - for (NamedDecl *decl : result) - { - namespace_decl = dyn_cast<clang::NamespaceDecl>(decl); - if (namespace_decl) - return namespace_decl; - } - - namespace_decl = NamespaceDecl::Create(*ast, - decl_ctx, - false, - SourceLocation(), - SourceLocation(), - &identifier_info, - nullptr); - - decl_ctx->addDecl (namespace_decl); - } - else - { - if (decl_ctx == translation_unit_decl) - { - namespace_decl = translation_unit_decl->getAnonymousNamespace(); - if (namespace_decl) - return namespace_decl; - - namespace_decl = NamespaceDecl::Create(*ast, - decl_ctx, - false, - SourceLocation(), - SourceLocation(), - nullptr, - nullptr); - translation_unit_decl->setAnonymousNamespace (namespace_decl); - translation_unit_decl->addDecl (namespace_decl); - assert (namespace_decl == translation_unit_decl->getAnonymousNamespace()); - } - else - { - NamespaceDecl *parent_namespace_decl = cast<NamespaceDecl>(decl_ctx); - if (parent_namespace_decl) - { - namespace_decl = parent_namespace_decl->getAnonymousNamespace(); - if (namespace_decl) - return namespace_decl; - namespace_decl = NamespaceDecl::Create(*ast, - decl_ctx, - false, - SourceLocation(), - SourceLocation(), - nullptr, - nullptr); - parent_namespace_decl->setAnonymousNamespace (namespace_decl); - parent_namespace_decl->addDecl (namespace_decl); - assert (namespace_decl == parent_namespace_decl->getAnonymousNamespace()); - } - else - { - // BAD!!! - } - } - } +ClangASTContext::GetUniqueNamespaceDeclaration(const char *name, + DeclContext *decl_ctx) { + NamespaceDecl *namespace_decl = nullptr; + ASTContext *ast = getASTContext(); + TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl(); + if (decl_ctx == nullptr) + decl_ctx = translation_unit_decl; + + if (name) { + IdentifierInfo &identifier_info = ast->Idents.get(name); + DeclarationName decl_name(&identifier_info); + clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); + for (NamedDecl *decl : result) { + namespace_decl = dyn_cast<clang::NamespaceDecl>(decl); + if (namespace_decl) + return namespace_decl; + } + + namespace_decl = + NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(), + SourceLocation(), &identifier_info, nullptr); + + decl_ctx->addDecl(namespace_decl); + } else { + if (decl_ctx == translation_unit_decl) { + namespace_decl = translation_unit_decl->getAnonymousNamespace(); + if (namespace_decl) + return namespace_decl; + + namespace_decl = + NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(), + SourceLocation(), nullptr, nullptr); + translation_unit_decl->setAnonymousNamespace(namespace_decl); + translation_unit_decl->addDecl(namespace_decl); + assert(namespace_decl == translation_unit_decl->getAnonymousNamespace()); + } else { + NamespaceDecl *parent_namespace_decl = cast<NamespaceDecl>(decl_ctx); + if (parent_namespace_decl) { + namespace_decl = parent_namespace_decl->getAnonymousNamespace(); + if (namespace_decl) + return namespace_decl; + namespace_decl = + NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(), + SourceLocation(), nullptr, nullptr); + parent_namespace_decl->setAnonymousNamespace(namespace_decl); + parent_namespace_decl->addDecl(namespace_decl); + assert(namespace_decl == + parent_namespace_decl->getAnonymousNamespace()); + } else { + // BAD!!! + } + } + } #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(namespace_decl); + VerifyDecl(namespace_decl); #endif - return namespace_decl; + return namespace_decl; } -NamespaceDecl * -ClangASTContext::GetUniqueNamespaceDeclaration (clang::ASTContext *ast, - const char *name, - clang::DeclContext *decl_ctx) -{ - ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(ast); - if (ast_ctx == nullptr) - return nullptr; +NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration( + clang::ASTContext *ast, const char *name, clang::DeclContext *decl_ctx) { + ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(ast); + if (ast_ctx == nullptr) + return nullptr; - return ast_ctx->GetUniqueNamespaceDeclaration(name, decl_ctx); + return ast_ctx->GetUniqueNamespaceDeclaration(name, decl_ctx); } clang::BlockDecl * -ClangASTContext::CreateBlockDeclaration (clang::DeclContext *ctx) -{ - if (ctx != nullptr) - { - clang::BlockDecl *decl = clang::BlockDecl::Create(*getASTContext(), ctx, clang::SourceLocation()); - ctx->addDecl(decl); - return decl; - } +ClangASTContext::CreateBlockDeclaration(clang::DeclContext *ctx) { + if (ctx != nullptr) { + clang::BlockDecl *decl = clang::BlockDecl::Create(*getASTContext(), ctx, + clang::SourceLocation()); + ctx->addDecl(decl); + return decl; + } + return nullptr; +} + +clang::DeclContext *FindLCABetweenDecls(clang::DeclContext *left, + clang::DeclContext *right, + clang::DeclContext *root) { + if (root == nullptr) return nullptr; -} -clang::DeclContext * -FindLCABetweenDecls(clang::DeclContext *left, clang::DeclContext *right, clang::DeclContext *root) -{ - if (root == nullptr) - return nullptr; + std::set<clang::DeclContext *> path_left; + for (clang::DeclContext *d = left; d != nullptr; d = d->getParent()) + path_left.insert(d); - std::set<clang::DeclContext *> path_left; - for (clang::DeclContext *d = left; d != nullptr; d = d->getParent()) - path_left.insert(d); + for (clang::DeclContext *d = right; d != nullptr; d = d->getParent()) + if (path_left.find(d) != path_left.end()) + return d; - for (clang::DeclContext *d = right; d != nullptr; d = d->getParent()) - if (path_left.find(d) != path_left.end()) - return d; - - return nullptr; + return nullptr; } -clang::UsingDirectiveDecl * -ClangASTContext::CreateUsingDirectiveDeclaration (clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) -{ - if (decl_ctx != nullptr && ns_decl != nullptr) - { - clang::TranslationUnitDecl *translation_unit = (clang::TranslationUnitDecl *)GetTranslationUnitDecl(getASTContext()); - clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(*getASTContext(), - decl_ctx, - clang::SourceLocation(), - clang::SourceLocation(), - clang::NestedNameSpecifierLoc(), - clang::SourceLocation(), - ns_decl, - FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit)); - decl_ctx->addDecl(using_decl); - return using_decl; - } - return nullptr; +clang::UsingDirectiveDecl *ClangASTContext::CreateUsingDirectiveDeclaration( + clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) { + if (decl_ctx != nullptr && ns_decl != nullptr) { + clang::TranslationUnitDecl *translation_unit = + (clang::TranslationUnitDecl *)GetTranslationUnitDecl(getASTContext()); + clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create( + *getASTContext(), decl_ctx, clang::SourceLocation(), + clang::SourceLocation(), clang::NestedNameSpecifierLoc(), + clang::SourceLocation(), ns_decl, + FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit)); + decl_ctx->addDecl(using_decl); + return using_decl; + } + return nullptr; } clang::UsingDecl * -ClangASTContext::CreateUsingDeclaration (clang::DeclContext *current_decl_ctx, clang::NamedDecl *target) -{ - if (current_decl_ctx != nullptr && target != nullptr) - { - clang::UsingDecl *using_decl = clang::UsingDecl::Create(*getASTContext(), - current_decl_ctx, - clang::SourceLocation(), - clang::NestedNameSpecifierLoc(), - clang::DeclarationNameInfo(), - false); - clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(*getASTContext(), - current_decl_ctx, - clang::SourceLocation(), - using_decl, - target); - using_decl->addShadowDecl(shadow_decl); - current_decl_ctx->addDecl(using_decl); - return using_decl; - } - return nullptr; -} - -clang::VarDecl * -ClangASTContext::CreateVariableDeclaration (clang::DeclContext *decl_context, const char *name, clang::QualType type) -{ - if (decl_context != nullptr) - { - clang::VarDecl *var_decl = clang::VarDecl::Create(*getASTContext(), - decl_context, - clang::SourceLocation(), - clang::SourceLocation(), - name && name[0] ? &getASTContext()->Idents.getOwn(name) : nullptr, - type, - nullptr, - clang::SC_None); - var_decl->setAccess(clang::AS_public); - decl_context->addDecl(var_decl); - return var_decl; - } - return nullptr; +ClangASTContext::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx, + clang::NamedDecl *target) { + if (current_decl_ctx != nullptr && target != nullptr) { + clang::UsingDecl *using_decl = clang::UsingDecl::Create( + *getASTContext(), current_decl_ctx, clang::SourceLocation(), + clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false); + clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create( + *getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl, + target); + using_decl->addShadowDecl(shadow_decl); + current_decl_ctx->addDecl(using_decl); + return using_decl; + } + return nullptr; +} + +clang::VarDecl *ClangASTContext::CreateVariableDeclaration( + clang::DeclContext *decl_context, const char *name, clang::QualType type) { + if (decl_context != nullptr) { + clang::VarDecl *var_decl = clang::VarDecl::Create( + *getASTContext(), decl_context, clang::SourceLocation(), + clang::SourceLocation(), + name && name[0] ? &getASTContext()->Idents.getOwn(name) : nullptr, type, + nullptr, clang::SC_None); + var_decl->setAccess(clang::AS_public); + decl_context->addDecl(var_decl); + return var_decl; + } + return nullptr; } lldb::opaque_compiler_type_t -ClangASTContext::GetOpaqueCompilerType(clang::ASTContext *ast, lldb::BasicType basic_type) -{ - switch (basic_type) - { - case eBasicTypeVoid: - return ast->VoidTy.getAsOpaquePtr(); - case eBasicTypeChar: - return ast->CharTy.getAsOpaquePtr(); - case eBasicTypeSignedChar: - return ast->SignedCharTy.getAsOpaquePtr(); - case eBasicTypeUnsignedChar: - return ast->UnsignedCharTy.getAsOpaquePtr(); - case eBasicTypeWChar: - return ast->getWCharType().getAsOpaquePtr(); - case eBasicTypeSignedWChar: - return ast->getSignedWCharType().getAsOpaquePtr(); - case eBasicTypeUnsignedWChar: - return ast->getUnsignedWCharType().getAsOpaquePtr(); - case eBasicTypeChar16: - return ast->Char16Ty.getAsOpaquePtr(); - case eBasicTypeChar32: - return ast->Char32Ty.getAsOpaquePtr(); - case eBasicTypeShort: - return ast->ShortTy.getAsOpaquePtr(); - case eBasicTypeUnsignedShort: - return ast->UnsignedShortTy.getAsOpaquePtr(); - case eBasicTypeInt: - return ast->IntTy.getAsOpaquePtr(); - case eBasicTypeUnsignedInt: - return ast->UnsignedIntTy.getAsOpaquePtr(); - case eBasicTypeLong: - return ast->LongTy.getAsOpaquePtr(); - case eBasicTypeUnsignedLong: - return ast->UnsignedLongTy.getAsOpaquePtr(); - case eBasicTypeLongLong: - return ast->LongLongTy.getAsOpaquePtr(); - case eBasicTypeUnsignedLongLong: - return ast->UnsignedLongLongTy.getAsOpaquePtr(); - case eBasicTypeInt128: - return ast->Int128Ty.getAsOpaquePtr(); - case eBasicTypeUnsignedInt128: - return ast->UnsignedInt128Ty.getAsOpaquePtr(); - case eBasicTypeBool: - return ast->BoolTy.getAsOpaquePtr(); - case eBasicTypeHalf: - return ast->HalfTy.getAsOpaquePtr(); - case eBasicTypeFloat: - return ast->FloatTy.getAsOpaquePtr(); - case eBasicTypeDouble: - return ast->DoubleTy.getAsOpaquePtr(); - case eBasicTypeLongDouble: - return ast->LongDoubleTy.getAsOpaquePtr(); - case eBasicTypeFloatComplex: - return ast->FloatComplexTy.getAsOpaquePtr(); - case eBasicTypeDoubleComplex: - return ast->DoubleComplexTy.getAsOpaquePtr(); - case eBasicTypeLongDoubleComplex: - return ast->LongDoubleComplexTy.getAsOpaquePtr(); - case eBasicTypeObjCID: - return ast->getObjCIdType().getAsOpaquePtr(); - case eBasicTypeObjCClass: - return ast->getObjCClassType().getAsOpaquePtr(); - case eBasicTypeObjCSel: - return ast->getObjCSelType().getAsOpaquePtr(); - case eBasicTypeNullPtr: - return ast->NullPtrTy.getAsOpaquePtr(); - default: - return nullptr; - } +ClangASTContext::GetOpaqueCompilerType(clang::ASTContext *ast, + lldb::BasicType basic_type) { + switch (basic_type) { + case eBasicTypeVoid: + return ast->VoidTy.getAsOpaquePtr(); + case eBasicTypeChar: + return ast->CharTy.getAsOpaquePtr(); + case eBasicTypeSignedChar: + return ast->SignedCharTy.getAsOpaquePtr(); + case eBasicTypeUnsignedChar: + return ast->UnsignedCharTy.getAsOpaquePtr(); + case eBasicTypeWChar: + return ast->getWCharType().getAsOpaquePtr(); + case eBasicTypeSignedWChar: + return ast->getSignedWCharType().getAsOpaquePtr(); + case eBasicTypeUnsignedWChar: + return ast->getUnsignedWCharType().getAsOpaquePtr(); + case eBasicTypeChar16: + return ast->Char16Ty.getAsOpaquePtr(); + case eBasicTypeChar32: + return ast->Char32Ty.getAsOpaquePtr(); + case eBasicTypeShort: + return ast->ShortTy.getAsOpaquePtr(); + case eBasicTypeUnsignedShort: + return ast->UnsignedShortTy.getAsOpaquePtr(); + case eBasicTypeInt: + return ast->IntTy.getAsOpaquePtr(); + case eBasicTypeUnsignedInt: + return ast->UnsignedIntTy.getAsOpaquePtr(); + case eBasicTypeLong: + return ast->LongTy.getAsOpaquePtr(); + case eBasicTypeUnsignedLong: + return ast->UnsignedLongTy.getAsOpaquePtr(); + case eBasicTypeLongLong: + return ast->LongLongTy.getAsOpaquePtr(); + case eBasicTypeUnsignedLongLong: + return ast->UnsignedLongLongTy.getAsOpaquePtr(); + case eBasicTypeInt128: + return ast->Int128Ty.getAsOpaquePtr(); + case eBasicTypeUnsignedInt128: + return ast->UnsignedInt128Ty.getAsOpaquePtr(); + case eBasicTypeBool: + return ast->BoolTy.getAsOpaquePtr(); + case eBasicTypeHalf: + return ast->HalfTy.getAsOpaquePtr(); + case eBasicTypeFloat: + return ast->FloatTy.getAsOpaquePtr(); + case eBasicTypeDouble: + return ast->DoubleTy.getAsOpaquePtr(); + case eBasicTypeLongDouble: + return ast->LongDoubleTy.getAsOpaquePtr(); + case eBasicTypeFloatComplex: + return ast->FloatComplexTy.getAsOpaquePtr(); + case eBasicTypeDoubleComplex: + return ast->DoubleComplexTy.getAsOpaquePtr(); + case eBasicTypeLongDoubleComplex: + return ast->LongDoubleComplexTy.getAsOpaquePtr(); + case eBasicTypeObjCID: + return ast->getObjCIdType().getAsOpaquePtr(); + case eBasicTypeObjCClass: + return ast->getObjCClassType().getAsOpaquePtr(); + case eBasicTypeObjCSel: + return ast->getObjCSelType().getAsOpaquePtr(); + case eBasicTypeNullPtr: + return ast->NullPtrTy.getAsOpaquePtr(); + default: + return nullptr; + } } #pragma mark Function Types -FunctionDecl * -ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx, - const char *name, - const CompilerType &function_clang_type, - int storage, - bool is_inline) -{ - FunctionDecl *func_decl = nullptr; - ASTContext *ast = getASTContext(); - if (decl_ctx == nullptr) - decl_ctx = ast->getTranslationUnitDecl(); - - - const bool hasWrittenPrototype = true; - const bool isConstexprSpecified = false; +clang::DeclarationName +ClangASTContext::GetDeclarationName(const char *name, + const CompilerType &function_clang_type) { + if (!name || !name[0]) + return clang::DeclarationName(); + + clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS; + if (!IsOperator(name, op_kind) || op_kind == clang::NUM_OVERLOADED_OPERATORS) + return DeclarationName(&getASTContext()->Idents.get( + name)); // Not operator, but a regular function. + + // 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. + clang::QualType method_qual_type(ClangUtil::GetQualType(function_clang_type)); + const clang::FunctionProtoType *function_type = + llvm::dyn_cast<clang::FunctionProtoType>(method_qual_type.getTypePtr()); + if (function_type == nullptr) + return clang::DeclarationName(); + + const bool is_method = false; + const unsigned int num_params = function_type->getNumParams(); + if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount( + is_method, op_kind, num_params)) + return clang::DeclarationName(); + + return getASTContext()->DeclarationNames.getCXXOperatorName(op_kind); +} + +FunctionDecl *ClangASTContext::CreateFunctionDeclaration( + DeclContext *decl_ctx, const char *name, + const CompilerType &function_clang_type, int storage, bool is_inline) { + FunctionDecl *func_decl = nullptr; + ASTContext *ast = getASTContext(); + if (decl_ctx == nullptr) + decl_ctx = ast->getTranslationUnitDecl(); + + const bool hasWrittenPrototype = true; + const bool isConstexprSpecified = false; + + clang::DeclarationName declarationName = + GetDeclarationName(name, function_clang_type); + func_decl = FunctionDecl::Create( + *ast, decl_ctx, SourceLocation(), SourceLocation(), declarationName, + ClangUtil::GetQualType(function_clang_type), nullptr, + (clang::StorageClass)storage, is_inline, hasWrittenPrototype, + isConstexprSpecified); + if (func_decl) + decl_ctx->addDecl(func_decl); - if (name && name[0]) - { - func_decl = FunctionDecl::Create( - *ast, decl_ctx, SourceLocation(), SourceLocation(), DeclarationName(&ast->Idents.get(name)), - ClangUtil::GetQualType(function_clang_type), nullptr, (clang::StorageClass)storage, is_inline, - hasWrittenPrototype, isConstexprSpecified); - } - else - { - func_decl = - FunctionDecl::Create(*ast, decl_ctx, SourceLocation(), SourceLocation(), DeclarationName(), - ClangUtil::GetQualType(function_clang_type), nullptr, (clang::StorageClass)storage, - is_inline, hasWrittenPrototype, isConstexprSpecified); - } - if (func_decl) - decl_ctx->addDecl (func_decl); - #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(func_decl); + VerifyDecl(func_decl); #endif - - return func_decl; + + return func_decl; +} + +CompilerType ClangASTContext::CreateFunctionType( + ASTContext *ast, const CompilerType &result_type, const CompilerType *args, + unsigned num_args, bool is_variadic, unsigned type_quals) { + if (ast == nullptr) + return CompilerType(); // invalid AST + + if (!result_type || !ClangUtil::IsClangType(result_type)) + return CompilerType(); // invalid return type + + std::vector<QualType> qual_type_args; + if (num_args > 0 && args == nullptr) + return CompilerType(); // invalid argument array passed in + + // Verify that all arguments are valid and the right type + for (unsigned i = 0; i < num_args; ++i) { + if (args[i]) { + // Make sure we have a clang type in args[i] and not a type from another + // language whose name might match + const bool is_clang_type = ClangUtil::IsClangType(args[i]); + lldbassert(is_clang_type); + if (is_clang_type) + qual_type_args.push_back(ClangUtil::GetQualType(args[i])); + else + return CompilerType(); // invalid argument type (must be a clang type) + } else + return CompilerType(); // invalid argument type (empty) + } + + // TODO: Detect calling convention in DWARF? + FunctionProtoType::ExtProtoInfo proto_info; + proto_info.Variadic = is_variadic; + proto_info.ExceptionSpec = EST_None; + proto_info.TypeQuals = type_quals; + proto_info.RefQualifier = RQ_None; + + return CompilerType(ast, + ast->getFunctionType(ClangUtil::GetQualType(result_type), + qual_type_args, proto_info)); +} + +ParmVarDecl *ClangASTContext::CreateParameterDeclaration( + const char *name, const CompilerType ¶m_type, int storage) { + ASTContext *ast = getASTContext(); + assert(ast != nullptr); + return ParmVarDecl::Create(*ast, ast->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + name && name[0] ? &ast->Idents.get(name) : nullptr, + ClangUtil::GetQualType(param_type), nullptr, + (clang::StorageClass)storage, nullptr); +} + +void ClangASTContext::SetFunctionParameters(FunctionDecl *function_decl, + ParmVarDecl **params, + unsigned num_params) { + if (function_decl) + function_decl->setParams(ArrayRef<ParmVarDecl *>(params, num_params)); } CompilerType -ClangASTContext::CreateFunctionType (ASTContext *ast, - const CompilerType& result_type, - const CompilerType *args, - unsigned num_args, - bool is_variadic, - unsigned type_quals) -{ - if (ast == nullptr) - return CompilerType(); // invalid AST - - if (!result_type || !ClangUtil::IsClangType(result_type)) - return CompilerType(); // invalid return type - - std::vector<QualType> qual_type_args; - if (num_args > 0 && args == nullptr) - return CompilerType(); // invalid argument array passed in - - // Verify that all arguments are valid and the right type - for (unsigned i=0; i<num_args; ++i) - { - if (args[i]) - { - // Make sure we have a clang type in args[i] and not a type from another - // language whose name might match - const bool is_clang_type = ClangUtil::IsClangType(args[i]); - lldbassert(is_clang_type); - if (is_clang_type) - qual_type_args.push_back(ClangUtil::GetQualType(args[i])); - else - return CompilerType(); // invalid argument type (must be a clang type) - } - else - return CompilerType(); // invalid argument type (empty) - } +ClangASTContext::CreateBlockPointerType(const CompilerType &function_type) { + QualType block_type = m_ast_ap->getBlockPointerType( + clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType())); - // TODO: Detect calling convention in DWARF? - FunctionProtoType::ExtProtoInfo proto_info; - proto_info.Variadic = is_variadic; - proto_info.ExceptionSpec = EST_None; - proto_info.TypeQuals = type_quals; - proto_info.RefQualifier = RQ_None; - - return CompilerType(ast, ast->getFunctionType(ClangUtil::GetQualType(result_type), qual_type_args, proto_info)); + return CompilerType(this, block_type.getAsOpaquePtr()); } -ParmVarDecl * -ClangASTContext::CreateParameterDeclaration (const char *name, const CompilerType ¶m_type, int storage) -{ - ASTContext *ast = getASTContext(); - assert (ast != nullptr); - return ParmVarDecl::Create(*ast, ast->getTranslationUnitDecl(), SourceLocation(), SourceLocation(), - name && name[0] ? &ast->Idents.get(name) : nullptr, ClangUtil::GetQualType(param_type), - nullptr, (clang::StorageClass)storage, nullptr); -} +#pragma mark Array Types -void -ClangASTContext::SetFunctionParameters (FunctionDecl *function_decl, ParmVarDecl **params, unsigned num_params) -{ - if (function_decl) - function_decl->setParams (ArrayRef<ParmVarDecl*>(params, num_params)); -} +CompilerType ClangASTContext::CreateArrayType(const CompilerType &element_type, + size_t element_count, + bool is_vector) { + if (element_type.IsValid()) { + ASTContext *ast = getASTContext(); + assert(ast != nullptr); + + if (is_vector) { + return CompilerType( + ast, ast->getExtVectorType(ClangUtil::GetQualType(element_type), + element_count)); + } else { + + llvm::APInt ap_element_count(64, element_count); + if (element_count == 0) { + return CompilerType(ast, ast->getIncompleteArrayType( + ClangUtil::GetQualType(element_type), + clang::ArrayType::Normal, 0)); + } else { + return CompilerType( + ast, ast->getConstantArrayType(ClangUtil::GetQualType(element_type), + ap_element_count, + clang::ArrayType::Normal, 0)); + } + } + } + return CompilerType(); +} + +CompilerType ClangASTContext::CreateStructForIdentifier( + const ConstString &type_name, + const std::initializer_list<std::pair<const char *, CompilerType>> + &type_fields, + bool packed) { + CompilerType type; + if (!type_name.IsEmpty() && + (type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)) + .IsValid()) { + lldbassert("Trying to create a type for an existing name"); + return type; + } + + type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), + clang::TTK_Struct, lldb::eLanguageTypeC); + StartTagDeclarationDefinition(type); + for (const auto &field : type_fields) + AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic, + 0); + if (packed) + SetIsPacked(type); + CompleteTagDeclarationDefinition(type); + return type; +} + +CompilerType ClangASTContext::GetOrCreateStructForIdentifier( + const ConstString &type_name, + const std::initializer_list<std::pair<const char *, CompilerType>> + &type_fields, + bool packed) { + CompilerType type; + if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) + return type; -CompilerType -ClangASTContext::CreateBlockPointerType (const CompilerType &function_type) -{ - QualType block_type = m_ast_ap->getBlockPointerType(clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType())); - - return CompilerType (this, block_type.getAsOpaquePtr()); + return CreateStructForIdentifier(type_name, type_fields, packed); } -#pragma mark Array Types - -CompilerType -ClangASTContext::CreateArrayType (const CompilerType &element_type, - size_t element_count, - bool is_vector) -{ - if (element_type.IsValid()) - { - ASTContext *ast = getASTContext(); - assert (ast != nullptr); - - if (is_vector) - { - return CompilerType(ast, ast->getExtVectorType(ClangUtil::GetQualType(element_type), element_count)); - } - else - { - - llvm::APInt ap_element_count (64, element_count); - if (element_count == 0) - { - return CompilerType(ast, ast->getIncompleteArrayType(ClangUtil::GetQualType(element_type), - clang::ArrayType::Normal, 0)); - } - else - { - return CompilerType(ast, ast->getConstantArrayType(ClangUtil::GetQualType(element_type), - ap_element_count, clang::ArrayType::Normal, 0)); - } - } - } - return CompilerType(); -} +#pragma mark Enumeration Types CompilerType -ClangASTContext::CreateStructForIdentifier (const ConstString &type_name, - const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, - bool packed) -{ - CompilerType type; - if (!type_name.IsEmpty() && (type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) - { - lldbassert("Trying to create a type for an existing name"); - return type; - } - - type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); - StartTagDeclarationDefinition(type); - for (const auto& field : type_fields) - AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic, 0); - if (packed) - SetIsPacked(type); - CompleteTagDeclarationDefinition(type); - return type; -} +ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx, + const Declaration &decl, + const CompilerType &integer_clang_type) { + // TODO: Do something intelligent with the Declaration object passed in + // like maybe filling in the SourceLocation with it... + ASTContext *ast = getASTContext(); -CompilerType -ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, - const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, - bool packed) -{ - CompilerType type; - if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) - return type; + // TODO: ask about these... + // const bool IsScoped = false; + // const bool IsFixed = false; - return CreateStructForIdentifier (type_name, - type_fields, - packed); -} + EnumDecl *enum_decl = EnumDecl::Create( + *ast, decl_ctx, SourceLocation(), SourceLocation(), + name && name[0] ? &ast->Idents.get(name) : nullptr, nullptr, + false, // IsScoped + false, // IsScopedUsingClassTag + false); // IsFixed -#pragma mark Enumeration Types + if (enum_decl) { + // TODO: check if we should be setting the promotion type too? + enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type)); -CompilerType -ClangASTContext::CreateEnumerationType -( - const char *name, - DeclContext *decl_ctx, - const Declaration &decl, - const CompilerType &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; - - EnumDecl *enum_decl = EnumDecl::Create (*ast, - decl_ctx, - SourceLocation(), - SourceLocation(), - name && name[0] ? &ast->Idents.get(name) : nullptr, - nullptr, - false, // IsScoped - false, // IsScopedUsingClassTag - false); // IsFixed - - - if (enum_decl) - { - // TODO: check if we should be setting the promotion type too? - enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type)); + enum_decl->setAccess(AS_public); // TODO respect what's in the debug info - enum_decl->setAccess(AS_public); // TODO respect what's in the debug info - - return CompilerType (ast, ast->getTagDeclType(enum_decl)); - } - return CompilerType(); + return CompilerType(ast, ast->getTagDeclType(enum_decl)); + } + return CompilerType(); } // Disable this for now since I can't seem to get a nicely formatted float @@ -2192,8 +2185,10 @@ ClangASTContext::CreateEnumerationType // would like to get perfect string values for any kind of float semantics // so we can support remote targets. The code below also requires a patch to // llvm::APInt. -//bool -//ClangASTContext::ConvertFloatValueToString (ASTContext *ast, lldb::opaque_compiler_type_t clang_type, const uint8_t* bytes, size_t byte_size, int apint_byte_order, std::string &float_str) +// bool +// ClangASTContext::ConvertFloatValueToString (ASTContext *ast, +// lldb::opaque_compiler_type_t clang_type, const uint8_t* bytes, size_t +// byte_size, int apint_byte_order, std::string &float_str) //{ // uint32_t count = 0; // bool is_complex = false; @@ -2206,14 +2201,16 @@ ClangASTContext::CreateEnumerationType // uint32_t i; // for (i=0; i<count; i++) // { -// APInt ap_int(num_bits_per_float, bytes + i * num_bytes_per_float, (APInt::ByteOrder)apint_byte_order); +// APInt ap_int(num_bits_per_float, bytes + i * num_bytes_per_float, +// (APInt::ByteOrder)apint_byte_order); // bool is_ieee = false; // APFloat ap_float(ap_int, is_ieee); // char s[1024]; // unsigned int hex_digits = 0; // bool upper_case = false; // -// if (ap_float.convertToHexString(s, hex_digits, upper_case, APFloat::rmNearestTiesToEven) > 0) +// if (ap_float.convertToHexString(s, hex_digits, upper_case, +// APFloat::rmNearestTiesToEven) > 0) // { // if (i > 0) // float_str.append(", "); @@ -2227,2051 +2224,2118 @@ ClangASTContext::CreateEnumerationType // return false; //} -CompilerType -ClangASTContext::GetIntTypeFromBitSize (clang::ASTContext *ast, - size_t bit_size, bool is_signed) -{ - if (ast) - { - if (is_signed) - { - if (bit_size == ast->getTypeSize(ast->SignedCharTy)) - return CompilerType(ast, ast->SignedCharTy); - - if (bit_size == ast->getTypeSize(ast->ShortTy)) - return CompilerType(ast, ast->ShortTy); - - if (bit_size == ast->getTypeSize(ast->IntTy)) - return CompilerType(ast, ast->IntTy); - - if (bit_size == ast->getTypeSize(ast->LongTy)) - return CompilerType(ast, ast->LongTy); - - if (bit_size == ast->getTypeSize(ast->LongLongTy)) - return CompilerType(ast, ast->LongLongTy); - - if (bit_size == ast->getTypeSize(ast->Int128Ty)) - return CompilerType(ast, ast->Int128Ty); +CompilerType ClangASTContext::GetIntTypeFromBitSize(clang::ASTContext *ast, + size_t bit_size, + bool is_signed) { + if (ast) { + if (is_signed) { + if (bit_size == ast->getTypeSize(ast->SignedCharTy)) + return CompilerType(ast, ast->SignedCharTy); + + if (bit_size == ast->getTypeSize(ast->ShortTy)) + return CompilerType(ast, ast->ShortTy); + + if (bit_size == ast->getTypeSize(ast->IntTy)) + return CompilerType(ast, ast->IntTy); + + if (bit_size == ast->getTypeSize(ast->LongTy)) + return CompilerType(ast, ast->LongTy); + + if (bit_size == ast->getTypeSize(ast->LongLongTy)) + return CompilerType(ast, ast->LongLongTy); + + if (bit_size == ast->getTypeSize(ast->Int128Ty)) + return CompilerType(ast, ast->Int128Ty); + } else { + if (bit_size == ast->getTypeSize(ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedLongTy)) + return CompilerType(ast, ast->UnsignedLongTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy)) + return CompilerType(ast, ast->UnsignedLongLongTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty)) + return CompilerType(ast, ast->UnsignedInt128Ty); + } + } + return CompilerType(); +} + +CompilerType ClangASTContext::GetPointerSizedIntType(clang::ASTContext *ast, + bool is_signed) { + if (ast) + return GetIntTypeFromBitSize(ast, ast->getTypeSize(ast->VoidPtrTy), + is_signed); + return CompilerType(); +} + +void ClangASTContext::DumpDeclContextHiearchy(clang::DeclContext *decl_ctx) { + if (decl_ctx) { + DumpDeclContextHiearchy(decl_ctx->getParent()); + + clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl_ctx); + if (named_decl) { + printf("%20s: %s\n", decl_ctx->getDeclKindName(), + named_decl->getDeclName().getAsString().c_str()); + } else { + printf("%20s\n", decl_ctx->getDeclKindName()); + } + } +} + +void ClangASTContext::DumpDeclHiearchy(clang::Decl *decl) { + if (decl == nullptr) + return; + DumpDeclContextHiearchy(decl->getDeclContext()); + + clang::RecordDecl *record_decl = llvm::dyn_cast<clang::RecordDecl>(decl); + if (record_decl) { + printf("%20s: %s%s\n", decl->getDeclKindName(), + record_decl->getDeclName().getAsString().c_str(), + record_decl->isInjectedClassName() ? " (injected class name)" : ""); + + } else { + clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl); + if (named_decl) { + printf("%20s: %s\n", decl->getDeclKindName(), + named_decl->getDeclName().getAsString().c_str()); + } else { + printf("%20s\n", decl->getDeclKindName()); + } + } +} + +bool ClangASTContext::DeclsAreEquivalent(clang::Decl *lhs_decl, + clang::Decl *rhs_decl) { + if (lhs_decl && rhs_decl) { + //---------------------------------------------------------------------- + // Make sure the decl kinds match first + //---------------------------------------------------------------------- + const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind(); + const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind(); + + if (lhs_decl_kind == rhs_decl_kind) { + //------------------------------------------------------------------ + // Now check that the decl contexts kinds are all equivalent + // before we have to check any names of the decl contexts... + //------------------------------------------------------------------ + clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext(); + clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext(); + if (lhs_decl_ctx && rhs_decl_ctx) { + while (1) { + if (lhs_decl_ctx && rhs_decl_ctx) { + const clang::Decl::Kind lhs_decl_ctx_kind = + lhs_decl_ctx->getDeclKind(); + const clang::Decl::Kind rhs_decl_ctx_kind = + rhs_decl_ctx->getDeclKind(); + if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) { + lhs_decl_ctx = lhs_decl_ctx->getParent(); + rhs_decl_ctx = rhs_decl_ctx->getParent(); + + if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr) + break; + } else + return false; + } else + return false; } - else - { - if (bit_size == ast->getTypeSize(ast->UnsignedCharTy)) - return CompilerType(ast, ast->UnsignedCharTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedShortTy)) - return CompilerType(ast, ast->UnsignedShortTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedIntTy)) - return CompilerType(ast, ast->UnsignedIntTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedLongTy)) - return CompilerType(ast, ast->UnsignedLongTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy)) - return CompilerType(ast, ast->UnsignedLongLongTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty)) - return CompilerType(ast, ast->UnsignedInt128Ty); + + //-------------------------------------------------------------- + // Now make sure the name of the decls match + //-------------------------------------------------------------- + clang::NamedDecl *lhs_named_decl = + llvm::dyn_cast<clang::NamedDecl>(lhs_decl); + clang::NamedDecl *rhs_named_decl = + llvm::dyn_cast<clang::NamedDecl>(rhs_decl); + if (lhs_named_decl && rhs_named_decl) { + clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName(); + clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName(); + if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) { + if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) + return false; + } else + return false; + } else + return false; + + //-------------------------------------------------------------- + // We know that the decl context kinds all match, so now we need + // to make sure the names match as well + //-------------------------------------------------------------- + lhs_decl_ctx = lhs_decl->getDeclContext(); + rhs_decl_ctx = rhs_decl->getDeclContext(); + while (1) { + switch (lhs_decl_ctx->getDeclKind()) { + case clang::Decl::TranslationUnit: + // We don't care about the translation unit names + return true; + default: { + clang::NamedDecl *lhs_named_decl = + llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx); + clang::NamedDecl *rhs_named_decl = + llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx); + if (lhs_named_decl && rhs_named_decl) { + clang::DeclarationName lhs_decl_name = + lhs_named_decl->getDeclName(); + clang::DeclarationName rhs_decl_name = + rhs_named_decl->getDeclName(); + if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) { + if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) + return false; + } else + return false; + } else + return false; + } break; + } + lhs_decl_ctx = lhs_decl_ctx->getParent(); + rhs_decl_ctx = rhs_decl_ctx->getParent(); } + } } - return CompilerType(); + } + return false; } +bool ClangASTContext::GetCompleteDecl(clang::ASTContext *ast, + clang::Decl *decl) { + if (!decl) + return false; -CompilerType -ClangASTContext::GetPointerSizedIntType (clang::ASTContext *ast, bool is_signed) -{ - if (ast) - return GetIntTypeFromBitSize(ast, ast->getTypeSize(ast->VoidPtrTy), is_signed); - return CompilerType(); -} + ExternalASTSource *ast_source = ast->getExternalSource(); -void -ClangASTContext::DumpDeclContextHiearchy (clang::DeclContext *decl_ctx) -{ - if (decl_ctx) - { - DumpDeclContextHiearchy (decl_ctx->getParent()); + if (!ast_source) + return false; - clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl_ctx); - if (named_decl) - { - printf ("%20s: %s\n", decl_ctx->getDeclKindName(), named_decl->getDeclName().getAsString().c_str()); - } - else - { - printf ("%20s\n", decl_ctx->getDeclKindName()); - } - } -} + if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) { + if (tag_decl->isCompleteDefinition()) + return true; -void -ClangASTContext::DumpDeclHiearchy (clang::Decl *decl) -{ - if (decl == nullptr) - return; - DumpDeclContextHiearchy(decl->getDeclContext()); + if (!tag_decl->hasExternalLexicalStorage()) + return false; - clang::RecordDecl *record_decl = llvm::dyn_cast<clang::RecordDecl>(decl); - if (record_decl) - { - printf ("%20s: %s%s\n", decl->getDeclKindName(), record_decl->getDeclName().getAsString().c_str(), record_decl->isInjectedClassName() ? " (injected class name)" : ""); + ast_source->CompleteType(tag_decl); - } - else - { - clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl); - if (named_decl) - { - printf ("%20s: %s\n", decl->getDeclKindName(), named_decl->getDeclName().getAsString().c_str()); - } - else - { - printf ("%20s\n", decl->getDeclKindName()); - } - } -} + return !tag_decl->getTypeForDecl()->isIncompleteType(); + } else if (clang::ObjCInterfaceDecl *objc_interface_decl = + llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) { + if (objc_interface_decl->getDefinition()) + return true; -bool -ClangASTContext::DeclsAreEquivalent (clang::Decl *lhs_decl, clang::Decl *rhs_decl) -{ - if (lhs_decl && rhs_decl) - { - //---------------------------------------------------------------------- - // Make sure the decl kinds match first - //---------------------------------------------------------------------- - const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind(); - const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind(); - - if (lhs_decl_kind == rhs_decl_kind) - { - //------------------------------------------------------------------ - // Now check that the decl contexts kinds are all equivalent - // before we have to check any names of the decl contexts... - //------------------------------------------------------------------ - clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext(); - clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext(); - if (lhs_decl_ctx && rhs_decl_ctx) - { - while (1) - { - if (lhs_decl_ctx && rhs_decl_ctx) - { - const clang::Decl::Kind lhs_decl_ctx_kind = lhs_decl_ctx->getDeclKind(); - const clang::Decl::Kind rhs_decl_ctx_kind = rhs_decl_ctx->getDeclKind(); - if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) - { - lhs_decl_ctx = lhs_decl_ctx->getParent(); - rhs_decl_ctx = rhs_decl_ctx->getParent(); - - if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr) - break; - } - else - return false; - } - else - return false; - } + if (!objc_interface_decl->hasExternalLexicalStorage()) + return false; - //-------------------------------------------------------------- - // Now make sure the name of the decls match - //-------------------------------------------------------------- - clang::NamedDecl *lhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(lhs_decl); - clang::NamedDecl *rhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(rhs_decl); - if (lhs_named_decl && rhs_named_decl) - { - clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName(); - clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName(); - if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) - { - if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) - return false; - } - else - return false; - } - else - return false; - - //-------------------------------------------------------------- - // We know that the decl context kinds all match, so now we need - // to make sure the names match as well - //-------------------------------------------------------------- - lhs_decl_ctx = lhs_decl->getDeclContext(); - rhs_decl_ctx = rhs_decl->getDeclContext(); - while (1) - { - switch (lhs_decl_ctx->getDeclKind()) - { - case clang::Decl::TranslationUnit: - // We don't care about the translation unit names - return true; - default: - { - clang::NamedDecl *lhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx); - clang::NamedDecl *rhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx); - if (lhs_named_decl && rhs_named_decl) - { - clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName(); - clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName(); - if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) - { - if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) - return false; - } - else - return false; - } - else - return false; - } - break; + ast_source->CompleteType(objc_interface_decl); - } - lhs_decl_ctx = lhs_decl_ctx->getParent(); - rhs_decl_ctx = rhs_decl_ctx->getParent(); - } - } - } - } + return !objc_interface_decl->getTypeForDecl()->isIncompleteType(); + } else { return false; -} -bool -ClangASTContext::GetCompleteDecl (clang::ASTContext *ast, - clang::Decl *decl) -{ - if (!decl) - return false; - - ExternalASTSource *ast_source = ast->getExternalSource(); - - if (!ast_source) - return false; - - if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) - { - if (tag_decl->isCompleteDefinition()) - return true; - - if (!tag_decl->hasExternalLexicalStorage()) - return false; - - ast_source->CompleteType(tag_decl); - - return !tag_decl->getTypeForDecl()->isIncompleteType(); - } - else if (clang::ObjCInterfaceDecl *objc_interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) - { - if (objc_interface_decl->getDefinition()) - return true; - - if (!objc_interface_decl->hasExternalLexicalStorage()) - return false; - - ast_source->CompleteType(objc_interface_decl); - - return !objc_interface_decl->getTypeForDecl()->isIncompleteType(); - } - else - { - return false; - } + } } -void -ClangASTContext::SetMetadataAsUserID (const void *object, - user_id_t user_id) -{ - ClangASTMetadata meta_data; - meta_data.SetUserID (user_id); - SetMetadata (object, meta_data); +void ClangASTContext::SetMetadataAsUserID(const void *object, + user_id_t user_id) { + ClangASTMetadata meta_data; + meta_data.SetUserID(user_id); + SetMetadata(object, meta_data); } -void -ClangASTContext::SetMetadata (clang::ASTContext *ast, - const void *object, - ClangASTMetadata &metadata) -{ - ClangExternalASTSourceCommon *external_source = - ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); - - if (external_source) - external_source->SetMetadata(object, metadata); -} +void ClangASTContext::SetMetadata(clang::ASTContext *ast, const void *object, + ClangASTMetadata &metadata) { + ClangExternalASTSourceCommon *external_source = + ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); -ClangASTMetadata * -ClangASTContext::GetMetadata (clang::ASTContext *ast, - const void *object) -{ - ClangExternalASTSourceCommon *external_source = - ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); - - if (external_source && external_source->HasMetadata(object)) - return external_source->GetMetadata(object); - else - return nullptr; + if (external_source) + external_source->SetMetadata(object, metadata); } -clang::DeclContext * -ClangASTContext::GetAsDeclContext (clang::CXXMethodDecl *cxx_method_decl) -{ - return llvm::dyn_cast<clang::DeclContext>(cxx_method_decl); +ClangASTMetadata *ClangASTContext::GetMetadata(clang::ASTContext *ast, + const void *object) { + ClangExternalASTSourceCommon *external_source = + ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); + + if (external_source && external_source->HasMetadata(object)) + return external_source->GetMetadata(object); + else + return nullptr; } clang::DeclContext * -ClangASTContext::GetAsDeclContext (clang::ObjCMethodDecl *objc_method_decl) -{ - return llvm::dyn_cast<clang::DeclContext>(objc_method_decl); +ClangASTContext::GetAsDeclContext(clang::CXXMethodDecl *cxx_method_decl) { + return llvm::dyn_cast<clang::DeclContext>(cxx_method_decl); } -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::TagType>(clang_type); - if (tag_type) - { - clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl()); - if (tag_decl) - { - tag_decl->setTagKind ((clang::TagDecl::TagKind)kind); - return true; - } - } +clang::DeclContext * +ClangASTContext::GetAsDeclContext(clang::ObjCMethodDecl *objc_method_decl) { + return llvm::dyn_cast<clang::DeclContext>(objc_method_decl); +} + +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::TagType>(clang_type); + if (tag_type) { + clang::TagDecl *tag_decl = + llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl()); + if (tag_decl) { + tag_decl->setTagKind((clang::TagDecl::TagKind)kind); + return true; + } } - return false; + } + 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; +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 false; + return true; + } + return false; } clang::DeclContext * -ClangASTContext::GetDeclContextForType (const CompilerType& type) -{ - return GetDeclContextForType(ClangUtil::GetQualType(type)); +ClangASTContext::GetDeclContextForType(const CompilerType &type) { + return GetDeclContextForType(ClangUtil::GetQualType(type)); } 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::ObjCInterface: return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr())->getInterface(); - case clang::Type::ObjCObjectPointer: return GetDeclContextForType (llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType()); - case clang::Type::Record: return llvm::cast<clang::RecordType>(qual_type)->getDecl(); - case clang::Type::Enum: return llvm::cast<clang::EnumType>(qual_type)->getDecl(); - case clang::Type::Typedef: return GetDeclContextForType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()); - case clang::Type::Auto: return GetDeclContextForType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType()); - case clang::Type::Elaborated: return GetDeclContextForType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()); - case clang::Type::Paren: return GetDeclContextForType (llvm::cast<clang::ParenType>(qual_type)->desugar()); - default: - break; - } - // No DeclContext in this type... +ClangASTContext::GetDeclContextForType(clang::QualType type) { + if (type.isNull()) 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<clang::ArrayType>(qual_type.getTypePtr()); - - if (array_type) - return GetCompleteQualType (ast, array_type->getElementType(), allow_completion); - } - break; - case clang::Type::Record: - { - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - if (cxx_record_decl->hasExternalLexicalStorage()) - { - const bool is_complete = cxx_record_decl->isCompleteDefinition(); - const bool fields_loaded = cxx_record_decl->hasLoadedFieldsFromExternalStorage(); - if (is_complete && fields_loaded) - return true; - - if (!allow_completion) - return false; - - // Call the field_begin() accessor to for it to use the external source - // to load the fields... - clang::ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) - { - external_ast_source->CompleteType(cxx_record_decl); - if (cxx_record_decl->isCompleteDefinition()) - { - cxx_record_decl->field_begin(); - cxx_record_decl->setHasLoadedFieldsFromExternalStorage (true); - } - } - } - } - const clang::TagType *tag_type = llvm::cast<clang::TagType>(qual_type.getTypePtr()); - return !tag_type->isIncompleteType(); + clang::QualType qual_type = type.getCanonicalType(); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::ObjCInterface: + return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr()) + ->getInterface(); + case clang::Type::ObjCObjectPointer: + return GetDeclContextForType( + llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()) + ->getPointeeType()); + case clang::Type::Record: + return llvm::cast<clang::RecordType>(qual_type)->getDecl(); + case clang::Type::Enum: + return llvm::cast<clang::EnumType>(qual_type)->getDecl(); + case clang::Type::Typedef: + return GetDeclContextForType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()); + case clang::Type::Auto: + return GetDeclContextForType( + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()); + case clang::Type::Elaborated: + return GetDeclContextForType( + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()); + case clang::Type::Paren: + return GetDeclContextForType( + llvm::cast<clang::ParenType>(qual_type)->desugar()); + default: + 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<clang::ArrayType>(qual_type.getTypePtr()); + + if (array_type) + return GetCompleteQualType(ast, array_type->getElementType(), + allow_completion); + } break; + case clang::Type::Record: { + clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + if (cxx_record_decl->hasExternalLexicalStorage()) { + const bool is_complete = cxx_record_decl->isCompleteDefinition(); + const bool fields_loaded = + cxx_record_decl->hasLoadedFieldsFromExternalStorage(); + if (is_complete && fields_loaded) + return true; + + if (!allow_completion) + return false; + + // Call the field_begin() accessor to for it to use the external source + // to load the fields... + clang::ExternalASTSource *external_ast_source = + ast->getExternalSource(); + if (external_ast_source) { + external_ast_source->CompleteType(cxx_record_decl); + if (cxx_record_decl->isCompleteDefinition()) { + cxx_record_decl->field_begin(); + cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); + } + } + } + } + const clang::TagType *tag_type = + llvm::cast<clang::TagType>(qual_type.getTypePtr()); + return !tag_type->isIncompleteType(); + } break; + + case clang::Type::Enum: { + const clang::TagType *tag_type = + llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()); + if (tag_type) { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) { + if (tag_decl->getDefinition()) + 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(); } - break; + } + } + return false; + } + } - case clang::Type::Enum: - { - const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - { - if (tag_decl->getDefinition()) - 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<clang::ObjCObjectType>(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::ObjCObject: + case clang::Type::ObjCInterface: { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(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(); } - break; - - case clang::Type::Typedef: - return GetCompleteQualType (ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType(), allow_completion); - - case clang::Type::Auto: - return GetCompleteQualType (ast, llvm::cast<clang::AutoType>(qual_type)->getDeducedType(), allow_completion); - - case clang::Type::Elaborated: - return GetCompleteQualType (ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(), allow_completion); - - case clang::Type::Paren: - return GetCompleteQualType (ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), allow_completion); - - case clang::Type::Attributed: - return GetCompleteQualType (ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(), allow_completion); - - default: - break; + } + } + return false; + } } - - return true; + } break; + + case clang::Type::Typedef: + return GetCompleteQualType(ast, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType(), + allow_completion); + + case clang::Type::Auto: + return GetCompleteQualType( + ast, llvm::cast<clang::AutoType>(qual_type)->getDeducedType(), + allow_completion); + + case clang::Type::Elaborated: + return GetCompleteQualType( + ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(), + allow_completion); + + case clang::Type::Paren: + return GetCompleteQualType( + ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), + allow_completion); + + case clang::Type::Attributed: + return GetCompleteQualType( + ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(), + 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; - } +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 (lldb::opaque_compiler_type_t 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::Auto: - return IsAggregateType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - case clang::Type::Elaborated: - return IsAggregateType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - case clang::Type::Typedef: - return IsAggregateType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Paren: - return IsAggregateType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - default: - break; - } - // The clang type does have a value - return false; -} - -bool -ClangASTContext::IsAnonymousType (lldb::opaque_compiler_type_t type) -{ - clang::QualType qual_type (GetCanonicalQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - if (const clang::RecordType *record_type = llvm::dyn_cast_or_null<clang::RecordType>(qual_type.getTypePtrOrNull())) - { - if (const clang::RecordDecl *record_decl = record_type->getDecl()) - { - return record_decl->isAnonymousStructOrUnion(); - } - } - break; - } - case clang::Type::Auto: - return IsAnonymousType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - case clang::Type::Elaborated: - return IsAnonymousType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - case clang::Type::Typedef: - return IsAnonymousType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Paren: - return IsAnonymousType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - default: - break; - } - // The clang type does have a value - return false; -} - -bool -ClangASTContext::IsArrayType (lldb::opaque_compiler_type_t type, - CompilerType *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->SetCompilerType (getASTContext(), llvm::cast<clang::ConstantArrayType>(qual_type)->getElementType()); - if (size) - *size = llvm::cast<clang::ConstantArrayType>(qual_type)->getSize().getLimitedValue(ULLONG_MAX); - if (is_incomplete) - *is_incomplete = false; - return true; - - case clang::Type::IncompleteArray: - if (element_type_ptr) - element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::IncompleteArrayType>(qual_type)->getElementType()); - if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = true; - return true; +bool ClangASTContext::IsAggregateType(lldb::opaque_compiler_type_t 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::Auto: + return IsAggregateType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + case clang::Type::Elaborated: + return IsAggregateType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + case clang::Type::Typedef: + return IsAggregateType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + case clang::Type::Paren: + return IsAggregateType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + default: + break; + } + // The clang type does have a value + return false; +} + +bool ClangASTContext::IsAnonymousType(lldb::opaque_compiler_type_t type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: { + if (const clang::RecordType *record_type = + llvm::dyn_cast_or_null<clang::RecordType>( + qual_type.getTypePtrOrNull())) { + if (const clang::RecordDecl *record_decl = record_type->getDecl()) { + return record_decl->isAnonymousStructOrUnion(); + } + } + break; + } + case clang::Type::Auto: + return IsAnonymousType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + case clang::Type::Elaborated: + return IsAnonymousType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + case clang::Type::Typedef: + return IsAnonymousType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + case clang::Type::Paren: + return IsAnonymousType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + default: + break; + } + // The clang type does have a value + return false; +} + +bool ClangASTContext::IsArrayType(lldb::opaque_compiler_type_t type, + CompilerType *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->SetCompilerType( + getASTContext(), + llvm::cast<clang::ConstantArrayType>(qual_type)->getElementType()); + if (size) + *size = llvm::cast<clang::ConstantArrayType>(qual_type) + ->getSize() + .getLimitedValue(ULLONG_MAX); + if (is_incomplete) + *is_incomplete = false; + return true; - case clang::Type::VariableArray: - if (element_type_ptr) - element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::VariableArrayType>(qual_type)->getElementType()); - if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = false; - return true; + case clang::Type::IncompleteArray: + if (element_type_ptr) + element_type_ptr->SetCompilerType( + getASTContext(), + llvm::cast<clang::IncompleteArrayType>(qual_type)->getElementType()); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = true; + return true; - case clang::Type::DependentSizedArray: - if (element_type_ptr) - element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::DependentSizedArrayType>(qual_type)->getElementType()); - if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = false; - return true; + case clang::Type::VariableArray: + if (element_type_ptr) + element_type_ptr->SetCompilerType( + getASTContext(), + llvm::cast<clang::VariableArrayType>(qual_type)->getElementType()); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = false; + return true; - case clang::Type::Typedef: - return IsArrayType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - element_type_ptr, - size, - is_incomplete); - case clang::Type::Auto: - return IsArrayType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), - element_type_ptr, - size, - is_incomplete); - case clang::Type::Elaborated: - return IsArrayType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - element_type_ptr, - size, - is_incomplete); - case clang::Type::Paren: - return IsArrayType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), - element_type_ptr, - size, - is_incomplete); - } + case clang::Type::DependentSizedArray: if (element_type_ptr) - element_type_ptr->Clear(); + element_type_ptr->SetCompilerType( + getASTContext(), llvm::cast<clang::DependentSizedArrayType>(qual_type) + ->getElementType()); if (size) - *size = 0; + *size = 0; if (is_incomplete) - *is_incomplete = false; - return false; -} + *is_incomplete = false; + return true; -bool -ClangASTContext::IsVectorType (lldb::opaque_compiler_type_t type, - CompilerType *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<clang::VectorType>(); - if (vector_type) - { - if (size) - *size = vector_type->getNumElements(); - if (element_type) - *element_type = CompilerType(getASTContext(), vector_type->getElementType()); - } - return true; - } - break; - case clang::Type::ExtVector: - { - const clang::ExtVectorType *ext_vector_type = qual_type->getAs<clang::ExtVectorType>(); - if (ext_vector_type) - { - if (size) - *size = ext_vector_type->getNumElements(); - if (element_type) - *element_type = CompilerType(getASTContext(), ext_vector_type->getElementType()); - } - return true; - } - default: - break; + case clang::Type::Typedef: + return IsArrayType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + element_type_ptr, size, is_incomplete); + case clang::Type::Auto: + return IsArrayType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + element_type_ptr, size, is_incomplete); + case clang::Type::Elaborated: + return IsArrayType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + element_type_ptr, size, is_incomplete); + case clang::Type::Paren: + return IsArrayType( + llvm::cast<clang::ParenType>(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 false; +} + +bool ClangASTContext::IsVectorType(lldb::opaque_compiler_type_t type, + CompilerType *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<clang::VectorType>(); + if (vector_type) { + if (size) + *size = vector_type->getNumElements(); + if (element_type) + *element_type = + CompilerType(getASTContext(), vector_type->getElementType()); } + return true; + } break; + case clang::Type::ExtVector: { + const clang::ExtVectorType *ext_vector_type = + qual_type->getAs<clang::ExtVectorType>(); + if (ext_vector_type) { + if (size) + *size = ext_vector_type->getNumElements(); + if (element_type) + *element_type = + CompilerType(getASTContext(), ext_vector_type->getElementType()); + } + return true; + } + default: + break; + } + return false; +} + +bool ClangASTContext::IsRuntimeGeneratedType( + lldb::opaque_compiler_type_t type) { + clang::DeclContext *decl_ctx = ClangASTContext::GetASTContext(getASTContext()) + ->GetDeclContextForType(GetQualType(type)); + if (!decl_ctx) return false; -} -bool -ClangASTContext::IsRuntimeGeneratedType (lldb::opaque_compiler_type_t type) -{ - clang::DeclContext* decl_ctx = ClangASTContext::GetASTContext(getASTContext())->GetDeclContextForType(GetQualType(type)); - if (!decl_ctx) - return false; - - if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx)) - return false; - - clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx); - - ClangASTMetadata* ast_metadata = ClangASTContext::GetMetadata(getASTContext(), result_iface_decl); - if (!ast_metadata) - return false; - return (ast_metadata->GetISAPtr() != 0); -} + if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx)) + return false; + + clang::ObjCInterfaceDecl *result_iface_decl = + llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx); -bool -ClangASTContext::IsCharType (lldb::opaque_compiler_type_t type) -{ - return GetQualType(type).getUnqualifiedType()->isCharType(); + ClangASTMetadata *ast_metadata = + ClangASTContext::GetMetadata(getASTContext(), result_iface_decl); + if (!ast_metadata) + return false; + return (ast_metadata->GetISAPtr() != 0); } +bool ClangASTContext::IsCharType(lldb::opaque_compiler_type_t type) { + return GetQualType(type).getUnqualifiedType()->isCharType(); +} -bool -ClangASTContext::IsCompleteType (lldb::opaque_compiler_type_t type) -{ - const bool allow_completion = false; - return GetCompleteQualType (getASTContext(), GetQualType(type), allow_completion); +bool ClangASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) { + const bool allow_completion = false; + return GetCompleteQualType(getASTContext(), GetQualType(type), + allow_completion); } -bool -ClangASTContext::IsConst(lldb::opaque_compiler_type_t type) -{ - return GetQualType(type).isConstQualified(); +bool ClangASTContext::IsConst(lldb::opaque_compiler_type_t type) { + return GetQualType(type).isConstQualified(); } -bool -ClangASTContext::IsCStringType (lldb::opaque_compiler_type_t type, uint32_t &length) -{ - CompilerType 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<clang::ConstantArrayType>(GetCanonicalQualType(type).getTypePtr())->getSize().getLimitedValue(); - } - return true; - - } - } +bool ClangASTContext::IsCStringType(lldb::opaque_compiler_type_t type, + uint32_t &length) { + CompilerType 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; -} -bool -ClangASTContext::IsFunctionType (lldb::opaque_compiler_type_t 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<clang::FunctionProtoType>(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<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), nullptr); - case clang::Type::Auto: - return IsFunctionType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), nullptr); - case clang::Type::Elaborated: - return IsFunctionType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), nullptr); - case clang::Type::Paren: - return IsFunctionType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), nullptr); - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - if (reference_type) - return IsFunctionType(reference_type->getPointeeType().getAsOpaquePtr(), nullptr); - } - break; - } + 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<clang::ConstantArrayType>( + GetCanonicalQualType(type).getTypePtr()) + ->getSize() + .getLimitedValue(); + } + return true; + } + } + return false; +} + +bool ClangASTContext::IsFunctionType(lldb::opaque_compiler_type_t 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<clang::FunctionProtoType>(qual_type.getTypePtr()); + if (function_proto_type) + *is_variadic_ptr = function_proto_type->isVariadic(); + else + *is_variadic_ptr = false; + } + return true; } - return false; + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + default: + break; + case clang::Type::Typedef: + return IsFunctionType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + nullptr); + case clang::Type::Auto: + return IsFunctionType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + nullptr); + case clang::Type::Elaborated: + return IsFunctionType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + nullptr); + case clang::Type::Paren: + return IsFunctionType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + nullptr); + case clang::Type::LValueReference: + case clang::Type::RValueReference: { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(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 (lldb::opaque_compiler_type_t type, CompilerType* 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<clang::RecordType>(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; - uint64_t base_bitwidth = 0; - for (field_pos = record_decl->field_begin(); field_pos != field_end; ++field_pos) - { - clang::QualType field_qual_type = field_pos->getType(); - uint64_t field_bitwidth = getASTContext()->getTypeSize (qual_type); - 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()) - { - if (num_fields == 0) - { - base_qual_type = field_qual_type; - base_bitwidth = field_bitwidth; - } - else - { - if (is_hfa) - return 0; - is_hva = true; - if (base_bitwidth != field_bitwidth) - return 0; - if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) - return 0; - } - } - else - return 0; - ++num_fields; - } - if (base_type_ptr) - *base_type_ptr = CompilerType (getASTContext(), base_qual_type); - return num_fields; - } - } - } - break; - - case clang::Type::Typedef: - return IsHomogeneousAggregate(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), base_type_ptr); - - case clang::Type::Auto: - return IsHomogeneousAggregate(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), base_type_ptr); - - case clang::Type::Elaborated: - return IsHomogeneousAggregate(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), base_type_ptr); - default: - break; - } +ClangASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, + CompilerType *base_type_ptr) { + if (!type) return 0; -} -size_t -ClangASTContext::GetNumberOfFunctionArguments (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); - if (func) - return func->getNumParams(); - } - 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<clang::RecordType>(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; + uint64_t base_bitwidth = 0; + for (field_pos = record_decl->field_begin(); field_pos != field_end; + ++field_pos) { + clang::QualType field_qual_type = field_pos->getType(); + uint64_t field_bitwidth = getASTContext()->getTypeSize(qual_type); + 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()) { + if (num_fields == 0) { + base_qual_type = field_qual_type; + base_bitwidth = field_bitwidth; + } else { + if (is_hfa) + return 0; + is_hva = true; + if (base_bitwidth != field_bitwidth) + return 0; + if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) + return 0; + } + } else + return 0; + ++num_fields; + } + if (base_type_ptr) + *base_type_ptr = CompilerType(getASTContext(), base_qual_type); + return num_fields; + } + } + } + break; + + case clang::Type::Typedef: + return IsHomogeneousAggregate(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + base_type_ptr); + + case clang::Type::Auto: + return IsHomogeneousAggregate(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + base_type_ptr); + + case clang::Type::Elaborated: + return IsHomogeneousAggregate(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + base_type_ptr); + default: + break; + } + return 0; +} + +size_t ClangASTContext::GetNumberOfFunctionArguments( + lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); + if (func) + return func->getNumParams(); + } + return 0; } CompilerType -ClangASTContext::GetFunctionArgumentAtIndex (lldb::opaque_compiler_type_t type, const size_t index) -{ - if (type) - { - clang::QualType qual_type (GetQualType(type)); - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); - if (func) - { - if (index < func->getNumParams()) - return CompilerType(getASTContext(), func->getParamType(index)); - } +ClangASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, + const size_t index) { + if (type) { + clang::QualType qual_type(GetQualType(type)); + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); + if (func) { + if (index < func->getNumParams()) + return CompilerType(getASTContext(), func->getParamType(index)); } - return CompilerType(); + } + return CompilerType(); } -bool -ClangASTContext::IsFunctionPointerType (lldb::opaque_compiler_type_t 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<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Auto: - return IsFunctionPointerType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - case clang::Type::Elaborated: - return IsFunctionPointerType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - case clang::Type::Paren: - return IsFunctionPointerType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - if (reference_type) - return IsFunctionPointerType(reference_type->getPointeeType().getAsOpaquePtr()); - } - break; - } - } - return false; - -} - -bool -ClangASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - - if (qual_type->isBlockPointerType()) - { - if (function_pointer_type_ptr) - { - const clang::BlockPointerType *block_pointer_type = qual_type->getAs<clang::BlockPointerType>(); - QualType pointee_type = block_pointer_type->getPointeeType(); - QualType function_pointer_type = m_ast_ap->getPointerType(pointee_type); - *function_pointer_type_ptr = CompilerType (getASTContext(), function_pointer_type); - } - return true; - } - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - case clang::Type::Typedef: - return IsBlockPointerType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), function_pointer_type_ptr); - case clang::Type::Auto: - return IsBlockPointerType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), function_pointer_type_ptr); - case clang::Type::Elaborated: - return IsBlockPointerType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), function_pointer_type_ptr); - case clang::Type::Paren: - return IsBlockPointerType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), function_pointer_type_ptr); - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - if (reference_type) - return IsBlockPointerType(reference_type->getPointeeType().getAsOpaquePtr(), function_pointer_type_ptr); - } - break; - } +bool ClangASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t 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<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + case clang::Type::Auto: + return IsFunctionPointerType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + case clang::Type::Elaborated: + return IsFunctionPointerType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + case clang::Type::Paren: + return IsFunctionPointerType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + + case clang::Type::LValueReference: + case clang::Type::RValueReference: { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); + if (reference_type) + return IsFunctionPointerType( + reference_type->getPointeeType().getAsOpaquePtr()); + } break; + } + } + return false; +} + +bool ClangASTContext::IsBlockPointerType( + lldb::opaque_compiler_type_t type, + CompilerType *function_pointer_type_ptr) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + if (qual_type->isBlockPointerType()) { + if (function_pointer_type_ptr) { + const clang::BlockPointerType *block_pointer_type = + qual_type->getAs<clang::BlockPointerType>(); + QualType pointee_type = block_pointer_type->getPointeeType(); + QualType function_pointer_type = m_ast_ap->getPointerType(pointee_type); + *function_pointer_type_ptr = + CompilerType(getASTContext(), function_pointer_type); + } + return true; } + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + default: + break; + case clang::Type::Typedef: + return IsBlockPointerType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + function_pointer_type_ptr); + case clang::Type::Auto: + return IsBlockPointerType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + function_pointer_type_ptr); + case clang::Type::Elaborated: + return IsBlockPointerType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + function_pointer_type_ptr); + case clang::Type::Paren: + return IsBlockPointerType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + function_pointer_type_ptr); + + case clang::Type::LValueReference: + case clang::Type::RValueReference: { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); + if (reference_type) + return IsBlockPointerType( + reference_type->getPointeeType().getAsOpaquePtr(), + function_pointer_type_ptr); + } break; + } + } + return false; +} + +bool ClangASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, + bool &is_signed) { + if (!type) return false; -} -bool -ClangASTContext::IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) -{ - if (!type) - return false; - - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal()); - - if (builtin_type) - { - if (builtin_type->isInteger()) - { - is_signed = builtin_type->isSignedInteger(); - return true; - } + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::BuiltinType *builtin_type = + llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal()); + + if (builtin_type) { + if (builtin_type->isInteger()) { + is_signed = builtin_type->isSignedInteger(); + return true; } - - return false; + } + + return false; } -bool -ClangASTContext::IsEnumerationType(lldb::opaque_compiler_type_t type, bool &is_signed) -{ - if (type) - { - const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)->getCanonicalTypeInternal()); +bool ClangASTContext::IsEnumerationType(lldb::opaque_compiler_type_t type, + bool &is_signed) { + if (type) { + const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>( + GetCanonicalQualType(type)->getCanonicalTypeInternal()); - if (enum_type) - { - IsIntegerType(enum_type->getDecl()->getIntegerType().getAsOpaquePtr(), is_signed); - return true; - } + if (enum_type) { + IsIntegerType(enum_type->getDecl()->getIntegerType().getAsOpaquePtr(), + is_signed); + return true; } + } - return false; + return false; } -bool -ClangASTContext::IsPointerType (lldb::opaque_compiler_type_t type, CompilerType *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<clang::BuiltinType>(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->SetCompilerType (getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::BlockPointer: - if (pointee_type) - pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::Pointer: - if (pointee_type) - pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::MemberPointer: - if (pointee_type) - pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::Typedef: - return IsPointerType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type); - case clang::Type::Auto: - return IsPointerType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), pointee_type); - case clang::Type::Elaborated: - return IsPointerType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type); - case clang::Type::Paren: - return IsPointerType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), pointee_type); - default: - break; - } +bool ClangASTContext::IsPointerType(lldb::opaque_compiler_type_t type, + CompilerType *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<clang::BuiltinType>(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->SetCompilerType( + getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType()); + return true; + case clang::Type::BlockPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::Pointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::MemberPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::Typedef: + return IsPointerType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Auto: + return IsPointerType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Elaborated: + return IsPointerType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Paren: + return IsPointerType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + pointee_type); + default: + break; } - if (pointee_type) - pointee_type->Clear(); - return false; + } + if (pointee_type) + pointee_type->Clear(); + return false; } - -bool -ClangASTContext::IsPointerOrReferenceType (lldb::opaque_compiler_type_t type, CompilerType *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<clang::BuiltinType>(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->SetCompilerType(getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::BlockPointer: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::Pointer: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::MemberPointer: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::LValueReference: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); - return true; - case clang::Type::RValueReference: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); - return true; - case clang::Type::Typedef: - return IsPointerOrReferenceType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type); - case clang::Type::Auto: - return IsPointerOrReferenceType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), pointee_type); - case clang::Type::Elaborated: - return IsPointerOrReferenceType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type); - case clang::Type::Paren: - return IsPointerOrReferenceType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), pointee_type); - default: - break; - } +bool ClangASTContext::IsPointerOrReferenceType( + lldb::opaque_compiler_type_t type, CompilerType *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<clang::BuiltinType>(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->SetCompilerType( + getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType()); + return true; + case clang::Type::BlockPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::Pointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::MemberPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::LValueReference: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); + return true; + case clang::Type::RValueReference: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); + return true; + case clang::Type::Typedef: + return IsPointerOrReferenceType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Auto: + return IsPointerOrReferenceType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Elaborated: + return IsPointerOrReferenceType( + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Paren: + return IsPointerOrReferenceType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + pointee_type); + default: + break; } - if (pointee_type) - pointee_type->Clear(); - return false; + } + if (pointee_type) + pointee_type->Clear(); + return false; } +bool ClangASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type, + bool *is_rvalue) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); -bool -ClangASTContext::IsReferenceType (lldb::opaque_compiler_type_t type, CompilerType *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->SetCompilerType(getASTContext(), llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); - if (is_rvalue) - *is_rvalue = false; - return true; - case clang::Type::RValueReference: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); - if (is_rvalue) - *is_rvalue = true; - return true; - case clang::Type::Typedef: - return IsReferenceType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type, is_rvalue); - case clang::Type::Auto: - return IsReferenceType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), pointee_type, is_rvalue); - case clang::Type::Elaborated: - return IsReferenceType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type, is_rvalue); - case clang::Type::Paren: - return IsReferenceType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), pointee_type, is_rvalue); - - default: - break; - } + switch (type_class) { + case clang::Type::LValueReference: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); + if (is_rvalue) + *is_rvalue = false; + return true; + case clang::Type::RValueReference: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); + if (is_rvalue) + *is_rvalue = true; + return true; + case clang::Type::Typedef: + return IsReferenceType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + pointee_type, is_rvalue); + case clang::Type::Auto: + return IsReferenceType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + pointee_type, is_rvalue); + case clang::Type::Elaborated: + return IsReferenceType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + pointee_type, is_rvalue); + case clang::Type::Paren: + return IsReferenceType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + pointee_type, is_rvalue); + + default: + break; } - if (pointee_type) - pointee_type->Clear(); - return false; + } + if (pointee_type) + pointee_type->Clear(); + return false; } -bool -ClangASTContext::IsFloatingPointType (lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - - if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(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<clang::ComplexType>(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<clang::VectorType>(qual_type->getCanonicalTypeInternal())) - { - if (IsFloatingPointType (VT->getElementType().getAsOpaquePtr(), count, is_complex)) - { - count = VT->getNumElements(); - is_complex = false; - return true; - } - } +bool ClangASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, + uint32_t &count, bool &is_complex) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>( + 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<clang::ComplexType>( + 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<clang::VectorType>( + 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; + } + count = 0; + is_complex = false; + return false; } +bool ClangASTContext::IsDefined(lldb::opaque_compiler_type_t type) { + if (!type) + return false; -bool -ClangASTContext::IsDefined(lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - - clang::QualType qual_type(GetQualType(type)); - const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(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<clang::ObjCObjectType>(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; - } + clang::QualType qual_type(GetQualType(type)); + const clang::TagType *tag_type = + llvm::dyn_cast<clang::TagType>(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<clang::ObjCObjectType>(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; + } + return true; } -bool -ClangASTContext::IsObjCClassType (const CompilerType& type) -{ - if (type) - { - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); +bool ClangASTContext::IsObjCClassType(const CompilerType &type) { + if (type) { + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type); - - if (obj_pointer_type) - return obj_pointer_type->isObjCClassType(); - } - return false; + const clang::ObjCObjectPointerType *obj_pointer_type = + llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type); + + if (obj_pointer_type) + return obj_pointer_type->isObjCClassType(); + } + return false; } -bool -ClangASTContext::IsObjCObjectOrInterfaceType (const CompilerType& type) -{ - if (ClangUtil::IsClangType(type)) - return ClangUtil::GetCanonicalQualType(type)->isObjCObjectOrInterfaceType(); +bool ClangASTContext::IsObjCObjectOrInterfaceType(const CompilerType &type) { + if (ClangUtil::IsClangType(type)) + return ClangUtil::GetCanonicalQualType(type)->isObjCObjectOrInterfaceType(); + return false; +} + +bool ClangASTContext::IsClassType(lldb::opaque_compiler_type_t type) { + if (!type) return false; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + return (type_class == clang::Type::Record); } -bool -ClangASTContext::IsClassType(lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - return (type_class == clang::Type::Record); +bool ClangASTContext::IsEnumType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + return (type_class == clang::Type::Enum); } -bool -ClangASTContext::IsEnumType(lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; +bool ClangASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) { + if (type) { clang::QualType qual_type(GetCanonicalQualType(type)); const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - return (type_class == clang::Type::Enum); -} - -bool -ClangASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t 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<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - if (record_decl) - { - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - if (cxx_record_decl) - return cxx_record_decl->isPolymorphic(); - } - } - break; - - default: - break; + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl) { + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) + return cxx_record_decl->isPolymorphic(); } + } + break; + + default: + break; } - return false; + } + return false; } -bool -ClangASTContext::IsPossibleDynamicType (lldb::opaque_compiler_type_t type, CompilerType *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<clang::BuiltinType>(qual_type)->getKind() == clang::BuiltinType::ObjCId) - { - if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(this, type); - return true; - } - break; - - case clang::Type::ObjCObjectPointer: - if (check_objc) - { - if (auto objc_pointee_type = qual_type->getPointeeType().getTypePtrOrNull()) - { - if (auto objc_object_type = llvm::dyn_cast_or_null<clang::ObjCObjectType>(objc_pointee_type)) - { - if (objc_object_type->isObjCClass()) - return false; - } - } - if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType()); - return true; - } - break; - - case clang::Type::Pointer: - pointee_qual_type = llvm::cast<clang::PointerType>(qual_type)->getPointeeType(); - success = true; - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - pointee_qual_type = llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType(); - success = true; - break; - - case clang::Type::Typedef: - return IsPossibleDynamicType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - dynamic_pointee_type, - check_cplusplus, - check_objc); - - case clang::Type::Auto: - return IsPossibleDynamicType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), - dynamic_pointee_type, - check_cplusplus, - check_objc); - - case clang::Type::Elaborated: - return IsPossibleDynamicType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - dynamic_pointee_type, - check_cplusplus, - check_objc); - - case clang::Type::Paren: - return IsPossibleDynamicType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), - dynamic_pointee_type, - check_cplusplus, - check_objc); - default: - break; +bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, + CompilerType *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<clang::BuiltinType>(qual_type)->getKind() == + clang::BuiltinType::ObjCId) { + if (dynamic_pointee_type) + dynamic_pointee_type->SetCompilerType(this, type); + return true; + } + break; + + case clang::Type::ObjCObjectPointer: + if (check_objc) { + if (auto objc_pointee_type = + qual_type->getPointeeType().getTypePtrOrNull()) { + if (auto objc_object_type = + llvm::dyn_cast_or_null<clang::ObjCObjectType>( + objc_pointee_type)) { + if (objc_object_type->isObjCClass()) + return false; + } } - - 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<clang::BuiltinType>(pointee_qual_type)->getKind()) - { - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(getASTContext(), pointee_qual_type); - return true; - default: - 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 = CompilerType(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->SetCompilerType(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->SetCompilerType(getASTContext(), pointee_qual_type); - return true; - } - break; - - default: - break; + if (dynamic_pointee_type) + dynamic_pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType()); + return true; + } + break; + + case clang::Type::Pointer: + pointee_qual_type = + llvm::cast<clang::PointerType>(qual_type)->getPointeeType(); + success = true; + break; + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + pointee_qual_type = + llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType(); + success = true; + break; + + case clang::Type::Typedef: + return IsPossibleDynamicType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + dynamic_pointee_type, check_cplusplus, + check_objc); + + case clang::Type::Auto: + return IsPossibleDynamicType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + dynamic_pointee_type, check_cplusplus, + check_objc); + + case clang::Type::Elaborated: + return IsPossibleDynamicType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + dynamic_pointee_type, check_cplusplus, + check_objc); + + case clang::Type::Paren: + return IsPossibleDynamicType( + llvm::cast<clang::ParenType>(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<clang::BuiltinType>(pointee_qual_type)->getKind()) { + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::Void: + if (dynamic_pointee_type) + dynamic_pointee_type->SetCompilerType(getASTContext(), + pointee_qual_type); + return true; + default: + 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 = CompilerType(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->SetCompilerType(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->SetCompilerType(getASTContext(), + pointee_qual_type); + return true; + } + break; + + default: + break; + } } - if (dynamic_pointee_type) - dynamic_pointee_type->Clear(); - return false; + } + if (dynamic_pointee_type) + dynamic_pointee_type->Clear(); + return false; } +bool ClangASTContext::IsScalarType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; -bool -ClangASTContext::IsScalarType (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - - return (GetTypeInfo (type, nullptr) & eTypeIsScalar) != 0; + return (GetTypeInfo(type, nullptr) & eTypeIsScalar) != 0; } -bool -ClangASTContext::IsTypedefType (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - return GetQualType(type)->getTypeClass() == clang::Type::Typedef; +bool ClangASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + return GetQualType(type)->getTypeClass() == clang::Type::Typedef; } -bool -ClangASTContext::IsVoidType (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - return GetCanonicalQualType(type)->isVoidType(); -} - -bool -ClangASTContext::SupportsLanguage (lldb::LanguageType language) -{ - return ClangASTContextSupportsLanguage(language); -} - -bool -ClangASTContext::GetCXXClassName (const CompilerType& type, std::string &class_name) -{ - if (type) - { - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - if (!qual_type.isNull()) - { - 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(); +bool ClangASTContext::IsVoidType(lldb::opaque_compiler_type_t type) { + if (!type) return false; + return GetCanonicalQualType(type)->isVoidType(); } +bool ClangASTContext::SupportsLanguage(lldb::LanguageType language) { + return ClangASTContextSupportsLanguage(language); +} -bool -ClangASTContext::IsCXXClassType (const CompilerType& type) -{ - if (!type) - return false; - +bool ClangASTContext::GetCXXClassName(const CompilerType &type, + std::string &class_name) { + if (type) { clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr) + if (!qual_type.isNull()) { + 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 CompilerType &type) { + if (!type) return false; + + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr) + return true; + return false; } -bool -ClangASTContext::IsBeingDefined (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type); - if (tag_type) - return tag_type->isBeingDefined(); +bool ClangASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) { + if (!type) return false; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type); + if (tag_type) + return tag_type->isBeingDefined(); + return false; } -bool -ClangASTContext::IsObjCObjectPointerType (const CompilerType& type, CompilerType *class_type_ptr) -{ - if (!type) - return false; +bool ClangASTContext::IsObjCObjectPointerType(const CompilerType &type, + CompilerType *class_type_ptr) { + if (!type) + return false; - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - if (!qual_type.isNull() && qual_type->isObjCObjectPointerType()) - { - if (class_type_ptr) - { - if (!qual_type->isObjCClassType() && - !qual_type->isObjCIdType()) - { - const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type); - if (obj_pointer_type == nullptr) - class_type_ptr->Clear(); - else - class_type_ptr->SetCompilerType (type.GetTypeSystem(), clang::QualType(obj_pointer_type->getInterfaceType(), 0).getAsOpaquePtr()); - } - } - return true; + if (!qual_type.isNull() && qual_type->isObjCObjectPointerType()) { + if (class_type_ptr) { + if (!qual_type->isObjCClassType() && !qual_type->isObjCIdType()) { + const clang::ObjCObjectPointerType *obj_pointer_type = + llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type); + if (obj_pointer_type == nullptr) + class_type_ptr->Clear(); + else + class_type_ptr->SetCompilerType( + type.GetTypeSystem(), + clang::QualType(obj_pointer_type->getInterfaceType(), 0) + .getAsOpaquePtr()); + } } - if (class_type_ptr) - class_type_ptr->Clear(); - return false; + return true; + } + if (class_type_ptr) + class_type_ptr->Clear(); + return false; } -bool -ClangASTContext::GetObjCClassName (const CompilerType& type, std::string &class_name) -{ - if (!type) - return false; +bool ClangASTContext::GetObjCClassName(const CompilerType &type, + std::string &class_name) { + if (!type) + return false; - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (object_type) - { - const clang::ObjCInterfaceDecl *interface = object_type->getInterface(); - if (interface) - { - class_name = interface->getNameAsString(); - return true; - } + const clang::ObjCObjectType *object_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type); + if (object_type) { + const clang::ObjCInterfaceDecl *interface = object_type->getInterface(); + if (interface) { + class_name = interface->getNameAsString(); + return true; } - return false; + } + return false; } - //---------------------------------------------------------------------- // Type Completion //---------------------------------------------------------------------- -bool -ClangASTContext::GetCompleteType (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - const bool allow_completion = true; - return GetCompleteQualType (getASTContext(), GetQualType(type), allow_completion); +bool ClangASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + const bool allow_completion = true; + return GetCompleteQualType(getASTContext(), GetQualType(type), + allow_completion); } -ConstString -ClangASTContext::GetTypeName (lldb::opaque_compiler_type_t type) -{ - std::string type_name; - if (type) - { - clang::PrintingPolicy printing_policy (getASTContext()->getPrintingPolicy()); - clang::QualType qual_type(GetQualType(type)); - printing_policy.SuppressTagKeyword = true; - const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>(); - if (typedef_type) - { - const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); - type_name = typedef_decl->getQualifiedNameAsString(); - } - else - { - type_name = qual_type.getAsString(printing_policy); - } +ConstString ClangASTContext::GetTypeName(lldb::opaque_compiler_type_t type) { + std::string type_name; + if (type) { + clang::PrintingPolicy printing_policy(getASTContext()->getPrintingPolicy()); + clang::QualType qual_type(GetQualType(type)); + printing_policy.SuppressTagKeyword = true; + const clang::TypedefType *typedef_type = + qual_type->getAs<clang::TypedefType>(); + if (typedef_type) { + const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); + type_name = typedef_decl->getQualifiedNameAsString(); + } else { + type_name = qual_type.getAsString(printing_policy); } - return ConstString(type_name); + } + return ConstString(type_name); } uint32_t -ClangASTContext::GetTypeInfo (lldb::opaque_compiler_type_t type, CompilerType *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<clang::BuiltinType>(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->SetCompilerType(getASTContext(), getASTContext()->ObjCBuiltinClassTy); - builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; - break; - - case clang::BuiltinType::ObjCSel: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(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->SetCompilerType(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<clang::ComplexType>(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->SetCompilerType(getASTContext(), llvm::cast<clang::ArrayType>(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->SetCompilerType(getASTContext(), llvm::cast<clang::EnumType>(qual_type)->getDecl()->getIntegerType()); - return eTypeIsEnumeration | eTypeHasValue; - - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetTypeInfo (pointee_or_element_clang_type); - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTypeInfo (pointee_or_element_clang_type); - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(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->SetCompilerType(getASTContext(), llvm::cast<clang::ReferenceType>(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->SetCompilerType(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->SetCompilerType(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 | CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(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<clang::VectorType>(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; +ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, + CompilerType *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<clang::BuiltinType>( + 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->SetCompilerType( + getASTContext(), getASTContext()->ObjCBuiltinClassTy); + builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; + break; + + case clang::BuiltinType::ObjCSel: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType(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->SetCompilerType( + 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<clang::ComplexType>( + 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->SetCompilerType( + getASTContext(), llvm::cast<clang::ArrayType>(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->SetCompilerType( + getASTContext(), + llvm::cast<clang::EnumType>(qual_type)->getDecl()->getIntegerType()); + return eTypeIsEnumeration | eTypeHasValue; + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetTypeInfo(pointee_or_element_clang_type); + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetTypeInfo(pointee_or_element_clang_type); + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(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->SetCompilerType( + getASTContext(), + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()) + ->getPointeeType()); + return eTypeHasChildren | eTypeIsReference | eTypeHasValue; -lldb::LanguageType -ClangASTContext::GetMinimumLanguage (lldb::opaque_compiler_type_t 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; - } + case clang::Type::MemberPointer: + return eTypeIsPointer | eTypeIsMember | eTypeHasValue; + + case clang::Type::ObjCObjectPointer: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType( + 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->SetCompilerType( + getASTContext(), qual_type->getPointeeType()); + return eTypeHasChildren | eTypeIsPointer | eTypeHasValue; + + case clang::Type::Record: + if (qual_type->getAsCXXRecordDecl()) + return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus; 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<clang::BuiltinType>(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 CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetMinimumLanguage(); - } - } + 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 | + CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(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<clang::VectorType>( + 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(lldb::opaque_compiler_type_t 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<clang::BuiltinType>(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 CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetMinimumLanguage(); + } + } + return lldb::eLanguageTypeC; } lldb::TypeClass -ClangASTContext::GetTypeClass (lldb::opaque_compiler_type_t 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<clang::RecordType>(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 CompilerType(getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTypeClass(); - case clang::Type::Auto: - return CompilerType(getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetTypeClass(); - case clang::Type::Elaborated: - return CompilerType(getASTContext(), llvm::cast<clang::ElaboratedType>(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::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; - case clang::Type::Pipe: 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(lldb::opaque_compiler_type_t type) -{ - if (type) - return GetQualType(type).getQualifiers().getCVRQualifiers(); - return 0; +ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t 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<clang::RecordType>(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 CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetTypeClass(); + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetTypeClass(); + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(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::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; + case clang::Type::Pipe: + break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: + break; + case clang::Type::Adjusted: + break; + case clang::Type::ObjCTypeParam: + break; + } + // We don't know hot to display this type... + return lldb::eTypeClassOther; +} + +unsigned ClangASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) { + if (type) + return GetQualType(type).getQualifiers().getCVRQualifiers(); + return 0; } //---------------------------------------------------------------------- @@ -4279,1689 +4343,1837 @@ ClangASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) //---------------------------------------------------------------------- CompilerType -ClangASTContext::GetArrayElementType (lldb::opaque_compiler_type_t 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 CompilerType(); - - CompilerType 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 CompilerType(); -} +ClangASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, + uint64_t *stride) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); -CompilerType -ClangASTContext::GetCanonicalType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType (getASTContext(), GetCanonicalQualType(type)); - return CompilerType(); + const clang::Type *array_eletype = + qual_type.getTypePtr()->getArrayElementTypeNoTypeQual(); + + if (!array_eletype) + return CompilerType(); + + CompilerType 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 CompilerType(); } -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; +CompilerType ClangASTContext::GetArrayType(lldb::opaque_compiler_type_t type, + uint64_t size) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + if (clang::ASTContext *ast_ctx = getASTContext()) { + if (size != 0) + return CompilerType( + ast_ctx, ast_ctx->getConstantArrayType( + qual_type, llvm::APInt(64, size), + clang::ArrayType::ArraySizeModifier::Normal, 0)); + else + return CompilerType( + ast_ctx, + ast_ctx->getIncompleteArrayType( + qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0)); + } + } + + return CompilerType(); } CompilerType -ClangASTContext::GetFullyUnqualifiedType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType(getASTContext(), GetFullyUnqualifiedType_Impl(getASTContext(), GetQualType(type))); - return CompilerType(); +ClangASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType(getASTContext(), GetCanonicalQualType(type)); + return CompilerType(); } - -int -ClangASTContext::GetFunctionArgumentCount (lldb::opaque_compiler_type_t type) -{ - if (type) - { - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType(type)); - if (func) - return func->getNumParams(); - } - return -1; +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; } CompilerType -ClangASTContext::GetFunctionArgumentTypeAtIndex (lldb::opaque_compiler_type_t type, size_t idx) -{ - if (type) - { - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetQualType(type)); - if (func) - { - const uint32_t num_args = func->getNumParams(); - if (idx < num_args) - return CompilerType(getASTContext(), func->getParamType(idx)); - } - } - return CompilerType(); +ClangASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType( + getASTContext(), + GetFullyUnqualifiedType_Impl(getASTContext(), GetQualType(type))); + return CompilerType(); +} + +int ClangASTContext::GetFunctionArgumentCount( + lldb::opaque_compiler_type_t type) { + if (type) { + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType(type)); + if (func) + return func->getNumParams(); + } + return -1; +} + +CompilerType ClangASTContext::GetFunctionArgumentTypeAtIndex( + lldb::opaque_compiler_type_t type, size_t idx) { + if (type) { + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(GetQualType(type)); + if (func) { + const uint32_t num_args = func->getNumParams(); + if (idx < num_args) + return CompilerType(getASTContext(), func->getParamType(idx)); + } + } + return CompilerType(); } CompilerType -ClangASTContext::GetFunctionReturnType (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type(GetQualType(type)); - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); - if (func) - return CompilerType(getASTContext(), func->getReturnType()); - } - return CompilerType(); +ClangASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType qual_type(GetQualType(type)); + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); + if (func) + return CompilerType(getASTContext(), func->getReturnType()); + } + return CompilerType(); } size_t -ClangASTContext::GetNumMemberFunctions (lldb::opaque_compiler_type_t 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<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(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<clang::ObjCObjectType>(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 CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumMemberFunctions(); - - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetNumMemberFunctions(); - - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumMemberFunctions(); - - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumMemberFunctions(); - - default: - break; +ClangASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t 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<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(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: { + const clang::ObjCObjectPointerType *objc_class_type = + qual_type->getAsObjCInterfacePointerType(); + const clang::ObjCInterfaceType *objc_interface_type = + objc_class_type->getInterfaceType(); + if (objc_interface_type && + GetCompleteType((lldb::opaque_compiler_type_t)objc_interface_type)) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_interface_type->getDecl(); + 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<clang::ObjCObjectType>(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 CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetNumMemberFunctions(); + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetNumMemberFunctions(); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetNumMemberFunctions(); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetNumMemberFunctions(); + + default: + break; } - return num_functions; + } + return num_functions; } TypeMemberFunctionImpl -ClangASTContext::GetMemberFunctionAtIndex (lldb::opaque_compiler_type_t type, size_t idx) -{ - std::string name; - MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown); - CompilerType clang_type; - CompilerDecl clang_decl; - 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<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(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<size_t>(std::distance(method_iter, method_end))) - { - std::advance(method_iter, idx); - clang::CXXMethodDecl *cxx_method_decl = method_iter->getCanonicalDecl(); - if (cxx_method_decl) - { - name = cxx_method_decl->getDeclName().getAsString(); - if (cxx_method_decl->isStatic()) - kind = lldb::eMemberFunctionKindStaticMethod; - else if (llvm::isa<clang::CXXConstructorDecl>(cxx_method_decl)) - kind = lldb::eMemberFunctionKindConstructor; - else if (llvm::isa<clang::CXXDestructorDecl>(cxx_method_decl)) - kind = lldb::eMemberFunctionKindDestructor; - else - kind = lldb::eMemberFunctionKindInstanceMethod; - clang_type = CompilerType(this, cxx_method_decl->getType().getAsOpaquePtr()); - clang_decl = CompilerDecl(this, cxx_method_decl); - } - } - } - } - 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<size_t>(std::distance(method_iter, method_end))) - { - std::advance(method_iter, idx); - clang::ObjCMethodDecl *objc_method_decl = method_iter->getCanonicalDecl(); - if (objc_method_decl) - { - clang_decl = CompilerDecl(this, objc_method_decl); - name = objc_method_decl->getSelector().getAsString(); - if (objc_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<clang::ObjCObjectType>(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<size_t>(std::distance(method_iter, method_end))) - { - std::advance(method_iter, idx); - clang::ObjCMethodDecl *objc_method_decl = method_iter->getCanonicalDecl(); - if (objc_method_decl) - { - clang_decl = CompilerDecl(this, objc_method_decl); - name = objc_method_decl->getSelector().getAsString(); - if (objc_method_decl->isClassMethod()) - kind = lldb::eMemberFunctionKindStaticMethod; - else - kind = lldb::eMemberFunctionKindInstanceMethod; - } - } - } - } - } - break; - - case clang::Type::Typedef: - return GetMemberFunctionAtIndex(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx); - - case clang::Type::Auto: - return GetMemberFunctionAtIndex(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), idx); - - case clang::Type::Elaborated: - return GetMemberFunctionAtIndex(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx); - - case clang::Type::Paren: - return GetMemberFunctionAtIndex(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx); - - default: - break; +ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, + size_t idx) { + std::string name; + MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown); + CompilerType clang_type; + CompilerDecl clang_decl; + 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<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(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<size_t>(std::distance(method_iter, method_end))) { + std::advance(method_iter, idx); + clang::CXXMethodDecl *cxx_method_decl = + method_iter->getCanonicalDecl(); + if (cxx_method_decl) { + name = cxx_method_decl->getDeclName().getAsString(); + if (cxx_method_decl->isStatic()) + kind = lldb::eMemberFunctionKindStaticMethod; + else if (llvm::isa<clang::CXXConstructorDecl>(cxx_method_decl)) + kind = lldb::eMemberFunctionKindConstructor; + else if (llvm::isa<clang::CXXDestructorDecl>(cxx_method_decl)) + kind = lldb::eMemberFunctionKindDestructor; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + clang_type = CompilerType( + this, cxx_method_decl->getType().getAsOpaquePtr()); + clang_decl = CompilerDecl(this, cxx_method_decl); + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: { + const clang::ObjCObjectPointerType *objc_class_type = + qual_type->getAsObjCInterfacePointerType(); + const clang::ObjCInterfaceType *objc_interface_type = + objc_class_type->getInterfaceType(); + if (objc_interface_type && + GetCompleteType((lldb::opaque_compiler_type_t)objc_interface_type)) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_interface_type->getDecl(); + if (class_interface_decl) { + auto method_iter = class_interface_decl->meth_begin(); + auto method_end = class_interface_decl->meth_end(); + if (idx < + static_cast<size_t>(std::distance(method_iter, method_end))) { + std::advance(method_iter, idx); + clang::ObjCMethodDecl *objc_method_decl = + method_iter->getCanonicalDecl(); + if (objc_method_decl) { + clang_decl = CompilerDecl(this, objc_method_decl); + name = objc_method_decl->getSelector().getAsString(); + if (objc_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<clang::ObjCObjectType>(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<size_t>(std::distance(method_iter, method_end))) { + std::advance(method_iter, idx); + clang::ObjCMethodDecl *objc_method_decl = + method_iter->getCanonicalDecl(); + if (objc_method_decl) { + clang_decl = CompilerDecl(this, objc_method_decl); + name = objc_method_decl->getSelector().getAsString(); + if (objc_method_decl->isClassMethod()) + kind = lldb::eMemberFunctionKindStaticMethod; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + } + } + } + } + } + break; + + case clang::Type::Typedef: + return GetMemberFunctionAtIndex(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + idx); + + case clang::Type::Auto: + return GetMemberFunctionAtIndex(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + idx); + + case clang::Type::Elaborated: + return GetMemberFunctionAtIndex( + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + idx); + + case clang::Type::Paren: + return GetMemberFunctionAtIndex( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + idx); + + default: + break; } - - if (kind == eMemberFunctionKindUnknown) - return TypeMemberFunctionImpl(); - else - return TypeMemberFunctionImpl(clang_type, clang_decl, name, kind); + } + + if (kind == eMemberFunctionKindUnknown) + return TypeMemberFunctionImpl(); + else + return TypeMemberFunctionImpl(clang_type, clang_decl, name, kind); } CompilerType -ClangASTContext::GetNonReferenceType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType(getASTContext(), GetQualType(type).getNonReferenceType()); - return CompilerType(); +ClangASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType(getASTContext(), + GetQualType(type).getNonReferenceType()); + return CompilerType(); +} + +CompilerType ClangASTContext::CreateTypedefType( + const CompilerType &type, const char *typedef_name, + const CompilerDeclContext &compiler_decl_ctx) { + if (type && typedef_name && typedef_name[0]) { + ClangASTContext *ast = + llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (!ast) + return CompilerType(); + clang::ASTContext *clang_ast = ast->getASTContext(); + clang::QualType qual_type(ClangUtil::GetQualType(type)); + + clang::DeclContext *decl_ctx = + ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx); + 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 CompilerType(clang_ast, clang_ast->getTypedefType(decl)); + } + return CompilerType(); } CompilerType -ClangASTContext::CreateTypedefType (const CompilerType& type, - const char *typedef_name, - const CompilerDeclContext &compiler_decl_ctx) -{ - if (type && typedef_name && typedef_name[0]) - { - ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (!ast) - return CompilerType(); - clang::ASTContext* clang_ast = ast->getASTContext(); - clang::QualType qual_type(ClangUtil::GetQualType(type)); - - clang::DeclContext *decl_ctx = ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx); - 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 CompilerType (clang_ast, clang_ast->getTypedefType (decl)); - } - return CompilerType(); - +ClangASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType qual_type(GetQualType(type)); + return CompilerType(getASTContext(), + qual_type.getTypePtr()->getPointeeType()); + } + return CompilerType(); } CompilerType -ClangASTContext::GetPointeeType (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type(GetQualType(type)); - return CompilerType (getASTContext(), qual_type.getTypePtr()->getPointeeType()); +ClangASTContext::GetPointerType(lldb::opaque_compiler_type_t 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 CompilerType(getASTContext(), + getASTContext()->getObjCObjectPointerType(qual_type)); + + default: + return CompilerType(getASTContext(), + getASTContext()->getPointerType(qual_type)); } - return CompilerType(); + } + return CompilerType(); } CompilerType -ClangASTContext::GetPointerType (lldb::opaque_compiler_type_t 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 CompilerType(getASTContext(), getASTContext()->getObjCObjectPointerType(qual_type)); - - default: - return CompilerType(getASTContext(), getASTContext()->getPointerType(qual_type)); - } - } +ClangASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType(this, getASTContext() + ->getLValueReferenceType(GetQualType(type)) + .getAsOpaquePtr()); + else return CompilerType(); } - CompilerType -ClangASTContext::GetLValueReferenceType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType(this, getASTContext()->getLValueReferenceType(GetQualType(type)).getAsOpaquePtr()); - else - return CompilerType(); +ClangASTContext::GetRValueReferenceType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType(this, getASTContext() + ->getRValueReferenceType(GetQualType(type)) + .getAsOpaquePtr()); + else + return CompilerType(); } CompilerType -ClangASTContext::GetRValueReferenceType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType(this, getASTContext()->getRValueReferenceType(GetQualType(type)).getAsOpaquePtr()); - else - return CompilerType(); +ClangASTContext::AddConstModifier(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType result(GetQualType(type)); + result.addConst(); + return CompilerType(this, result.getAsOpaquePtr()); + } + return CompilerType(); } CompilerType -ClangASTContext::AddConstModifier (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType result(GetQualType(type)); - result.addConst(); - return CompilerType (this, result.getAsOpaquePtr()); - } - return CompilerType(); +ClangASTContext::AddVolatileModifier(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType result(GetQualType(type)); + result.addVolatile(); + return CompilerType(this, result.getAsOpaquePtr()); + } + return CompilerType(); } CompilerType -ClangASTContext::AddVolatileModifier (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType result(GetQualType(type)); - result.addVolatile(); - return CompilerType (this, result.getAsOpaquePtr()); - } - return CompilerType(); - +ClangASTContext::AddRestrictModifier(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType result(GetQualType(type)); + result.addRestrict(); + return CompilerType(this, result.getAsOpaquePtr()); + } + return CompilerType(); } CompilerType -ClangASTContext::AddRestrictModifier (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType result(GetQualType(type)); - result.addRestrict(); - return CompilerType (this, result.getAsOpaquePtr()); - } - return CompilerType(); - -} +ClangASTContext::CreateTypedef(lldb::opaque_compiler_type_t type, + const char *typedef_name, + const CompilerDeclContext &compiler_decl_ctx) { + if (type) { + clang::ASTContext *clang_ast = getASTContext(); + clang::QualType qual_type(GetQualType(type)); -CompilerType -ClangASTContext::CreateTypedef (lldb::opaque_compiler_type_t type, const char *typedef_name, const CompilerDeclContext &compiler_decl_ctx) -{ - if (type) - { - clang::ASTContext* clang_ast = getASTContext(); - clang::QualType qual_type (GetQualType(type)); - - clang::DeclContext *decl_ctx = ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx); - if (decl_ctx == nullptr) - decl_ctx = 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)); - - clang::TagDecl *tdecl = nullptr; - if (!qual_type.isNull()) - { - if (const clang::RecordType *rt = qual_type->getAs<clang::RecordType>()) - tdecl = rt->getDecl(); - if (const clang::EnumType *et = qual_type->getAs<clang::EnumType>()) - tdecl = et->getDecl(); - } + clang::DeclContext *decl_ctx = + ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx); + if (decl_ctx == nullptr) + decl_ctx = getASTContext()->getTranslationUnitDecl(); - // Check whether this declaration is an anonymous struct, union, or enum, hidden behind a typedef. If so, we - // try to check whether we have a typedef tag to attach to the original record declaration - if (tdecl && !tdecl->getIdentifier() && !tdecl->getTypedefNameForAnonDecl()) - tdecl->setTypedefNameForAnonDecl(decl); + 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 + clang::TagDecl *tdecl = nullptr; + if (!qual_type.isNull()) { + if (const clang::RecordType *rt = qual_type->getAs<clang::RecordType>()) + tdecl = rt->getDecl(); + if (const clang::EnumType *et = qual_type->getAs<clang::EnumType>()) + tdecl = et->getDecl(); + } - // Get a uniqued clang::QualType for the typedef decl type - return CompilerType (this, clang_ast->getTypedefType (decl).getAsOpaquePtr()); + // Check whether this declaration is an anonymous struct, union, or enum, + // hidden behind a typedef. If so, we + // try to check whether we have a typedef tag to attach to the original + // record declaration + if (tdecl && !tdecl->getIdentifier() && !tdecl->getTypedefNameForAnonDecl()) + tdecl->setTypedefNameForAnonDecl(decl); - } - return CompilerType(); + decl->setAccess(clang::AS_public); // TODO respect proper access specifier + // Get a uniqued clang::QualType for the typedef decl type + return CompilerType(this, clang_ast->getTypedefType(decl).getAsOpaquePtr()); + } + return CompilerType(); } CompilerType -ClangASTContext::GetTypedefedType (lldb::opaque_compiler_type_t type) -{ - if (type) - { - const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(GetQualType(type)); - if (typedef_type) - return CompilerType (getASTContext(), typedef_type->getDecl()->getUnderlyingType()); - } - return CompilerType(); +ClangASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) { + if (type) { + const clang::TypedefType *typedef_type = + llvm::dyn_cast<clang::TypedefType>(GetQualType(type)); + if (typedef_type) + return CompilerType(getASTContext(), + typedef_type->getDecl()->getUnderlyingType()); + } + return CompilerType(); } - //---------------------------------------------------------------------- // Create related types using the current type's AST //---------------------------------------------------------------------- -CompilerType -ClangASTContext::GetBasicTypeFromAST (lldb::BasicType basic_type) -{ - return ClangASTContext::GetBasicType(getASTContext(), basic_type); +CompilerType ClangASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) { + return ClangASTContext::GetBasicType(getASTContext(), basic_type); } //---------------------------------------------------------------------- // Exploring the type //---------------------------------------------------------------------- -uint64_t -ClangASTContext::GetBitSize (lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) -{ - if (GetCompleteType (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)) - return getASTContext()->getTypeSize(qual_type); - else - return 0; - break; - - 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(CompilerType(getASTContext(), qual_type), bit_size)) - return bit_size; - } - } - else - { - static bool g_printed = false; - if (!g_printed) - { - StreamString s; - DumpTypeDescription(type, &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; - } - } - } - LLVM_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 (lldb::opaque_compiler_type_t type) -{ - if (GetCompleteType(type)) - return getASTContext()->getTypeAlign(GetQualType(type)); - return 0; -} - - -lldb::Encoding -ClangASTContext::GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count) -{ - if (!type) - return lldb::eEncodingInvalid; - - count = 1; +uint64_t ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) { + if (GetCompleteType(type)) { 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<clang::BuiltinType>(qual_type)->getKind()) - { - 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::Half: - case clang::BuiltinType::Float: - case clang::BuiltinType::Float128: - 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::OCLClkEvent: - case clang::BuiltinType::Kind::OCLEvent: - case clang::BuiltinType::Kind::OCLImage1dRO: - case clang::BuiltinType::Kind::OCLImage1dWO: - case clang::BuiltinType::Kind::OCLImage1dRW: - case clang::BuiltinType::Kind::OCLImage1dArrayRO: - case clang::BuiltinType::Kind::OCLImage1dArrayWO: - case clang::BuiltinType::Kind::OCLImage1dArrayRW: - case clang::BuiltinType::Kind::OCLImage1dBufferRO: - case clang::BuiltinType::Kind::OCLImage1dBufferWO: - case clang::BuiltinType::Kind::OCLImage1dBufferRW: - case clang::BuiltinType::Kind::OCLImage2dRO: - case clang::BuiltinType::Kind::OCLImage2dWO: - case clang::BuiltinType::Kind::OCLImage2dRW: - case clang::BuiltinType::Kind::OCLImage2dArrayRO: - case clang::BuiltinType::Kind::OCLImage2dArrayWO: - case clang::BuiltinType::Kind::OCLImage2dArrayRW: - case clang::BuiltinType::Kind::OCLImage2dArrayDepthRO: - case clang::BuiltinType::Kind::OCLImage2dArrayDepthWO: - case clang::BuiltinType::Kind::OCLImage2dArrayDepthRW: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAARO: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAAWO: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAARW: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRO: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthWO: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRW: - case clang::BuiltinType::Kind::OCLImage2dDepthRO: - case clang::BuiltinType::Kind::OCLImage2dDepthWO: - case clang::BuiltinType::Kind::OCLImage2dDepthRW: - case clang::BuiltinType::Kind::OCLImage2dMSAARO: - case clang::BuiltinType::Kind::OCLImage2dMSAAWO: - case clang::BuiltinType::Kind::OCLImage2dMSAARW: - case clang::BuiltinType::Kind::OCLImage2dMSAADepthRO: - case clang::BuiltinType::Kind::OCLImage2dMSAADepthWO: - case clang::BuiltinType::Kind::OCLImage2dMSAADepthRW: - case clang::BuiltinType::Kind::OCLImage3dRO: - case clang::BuiltinType::Kind::OCLImage3dWO: - case clang::BuiltinType::Kind::OCLImage3dRW: - case clang::BuiltinType::Kind::OCLQueue: - case clang::BuiltinType::Kind::OCLNDRange: - case clang::BuiltinType::Kind::OCLReserveID: - case clang::BuiltinType::Kind::OCLSampler: - case clang::BuiltinType::Kind::OMPArraySection: - 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 = CompilerType(getASTContext(), complex_type->getElementType()).GetEncoding(count); - else - encoding = lldb::eEncodingSint; - } - count = 2; - return encoding; + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) + return getASTContext()->getTypeSize(qual_type); + else + return 0; + break; + + 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( + CompilerType(getASTContext(), qual_type), bit_size)) + return bit_size; } - - case clang::Type::ObjCInterface: break; - case clang::Type::Record: break; - case clang::Type::Enum: return lldb::eEncodingSint; - case clang::Type::Typedef: - return CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetEncoding(count); - - case clang::Type::Auto: - return CompilerType(getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetEncoding(count); - - case clang::Type::Elaborated: - return CompilerType(getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetEncoding(count); - - case clang::Type::Paren: - return CompilerType(getASTContext(), llvm::cast<clang::ParenType>(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::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: - case clang::Type::Pipe: - break; - - // pointer type decayed from an array or function type. - case clang::Type::Decayed: - break; + } else { + static bool g_printed = false; + if (!g_printed) { + StreamString s; + DumpTypeDescription(type, &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; + } + } } - count = 0; + LLVM_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(lldb::opaque_compiler_type_t type) { + if (GetCompleteType(type)) + return getASTContext()->getTypeAlign(GetQualType(type)); + return 0; +} + +lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type, + uint64_t &count) { + if (!type) return lldb::eEncodingInvalid; -} -lldb::Format -ClangASTContext::GetFormat (lldb::opaque_compiler_type_t 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<clang::BuiltinType>(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::Half: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: return lldb::eFormatFloat; - default: - 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 CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetFormat(); - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->desugar()).GetFormat(); - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetFormat(); - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(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: - case clang::Type::Pipe: - 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; + 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<clang::BuiltinType>(qual_type)->getKind()) { + 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::Half: + case clang::BuiltinType::Float: + case clang::BuiltinType::Float128: + 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::OCLClkEvent: + case clang::BuiltinType::Kind::OCLEvent: + case clang::BuiltinType::Kind::OCLImage1dRO: + case clang::BuiltinType::Kind::OCLImage1dWO: + case clang::BuiltinType::Kind::OCLImage1dRW: + case clang::BuiltinType::Kind::OCLImage1dArrayRO: + case clang::BuiltinType::Kind::OCLImage1dArrayWO: + case clang::BuiltinType::Kind::OCLImage1dArrayRW: + case clang::BuiltinType::Kind::OCLImage1dBufferRO: + case clang::BuiltinType::Kind::OCLImage1dBufferWO: + case clang::BuiltinType::Kind::OCLImage1dBufferRW: + case clang::BuiltinType::Kind::OCLImage2dRO: + case clang::BuiltinType::Kind::OCLImage2dWO: + case clang::BuiltinType::Kind::OCLImage2dRW: + case clang::BuiltinType::Kind::OCLImage2dArrayRO: + case clang::BuiltinType::Kind::OCLImage2dArrayWO: + case clang::BuiltinType::Kind::OCLImage2dArrayRW: + case clang::BuiltinType::Kind::OCLImage2dArrayDepthRO: + case clang::BuiltinType::Kind::OCLImage2dArrayDepthWO: + case clang::BuiltinType::Kind::OCLImage2dArrayDepthRW: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAARO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAAWO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAARW: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthWO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRW: + case clang::BuiltinType::Kind::OCLImage2dDepthRO: + case clang::BuiltinType::Kind::OCLImage2dDepthWO: + case clang::BuiltinType::Kind::OCLImage2dDepthRW: + case clang::BuiltinType::Kind::OCLImage2dMSAARO: + case clang::BuiltinType::Kind::OCLImage2dMSAAWO: + case clang::BuiltinType::Kind::OCLImage2dMSAARW: + case clang::BuiltinType::Kind::OCLImage2dMSAADepthRO: + case clang::BuiltinType::Kind::OCLImage2dMSAADepthWO: + case clang::BuiltinType::Kind::OCLImage2dMSAADepthRW: + case clang::BuiltinType::Kind::OCLImage3dRO: + case clang::BuiltinType::Kind::OCLImage3dWO: + case clang::BuiltinType::Kind::OCLImage3dRW: + case clang::BuiltinType::Kind::OCLQueue: + case clang::BuiltinType::Kind::OCLNDRange: + case clang::BuiltinType::Kind::OCLReserveID: + case clang::BuiltinType::Kind::OCLSampler: + case clang::BuiltinType::Kind::OMPArraySection: + 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 = CompilerType(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 CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetEncoding(count); + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetEncoding(count); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetEncoding(count); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(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::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: + case clang::Type::Pipe: + break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: + break; + case clang::Type::ObjCTypeParam: + break; + } + count = 0; + return lldb::eEncodingInvalid; +} + +lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t 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<clang::BuiltinType>(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::Half: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + return lldb::eFormatFloat; + default: + 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 CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetFormat(); + case clang::Type::Auto: + return CompilerType(getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->desugar()) + .GetFormat(); + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetFormat(); + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(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: + case clang::Type::Pipe: + break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: + break; + case clang::Type::ObjCTypeParam: + 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; } -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(lldb::opaque_compiler_type_t type, + bool omit_empty_base_classes) { + if (!type) + return 0; -uint32_t -ClangASTContext::GetNumChildren (lldb::opaque_compiler_type_t 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<clang::BuiltinType>(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<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(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<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->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<clang::ObjCObjectType>(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<clang::ObjCObjectPointerType>(qual_type.getTypePtr()); - clang::QualType pointee_type = pointer_type->getPointeeType(); - uint32_t num_pointee_children = CompilerType (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<clang::VectorType>(qual_type.getTypePtr())->getNumElements(); - break; - - case clang::Type::ConstantArray: - num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue(); - break; - - case clang::Type::Pointer: - { - const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr()); - clang::QualType pointee_type (pointer_type->getPointeeType()); - uint32_t num_pointee_children = CompilerType (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<clang::ReferenceType>(qual_type.getTypePtr()); - clang::QualType pointee_type = reference_type->getPointeeType(); - uint32_t num_pointee_children = CompilerType (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 = CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumChildren (omit_empty_base_classes); - break; + 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<clang::BuiltinType>(qual_type)->getKind()) { + case clang::BuiltinType::ObjCId: // child is Class + case clang::BuiltinType::ObjCClass: // child is Class + num_children = 1; + break; - case clang::Type::Auto: - num_children = CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetNumChildren (omit_empty_base_classes); - break; - - case clang::Type::Elaborated: - num_children = CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumChildren (omit_empty_base_classes); - break; - - case clang::Type::Paren: - num_children = CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumChildren (omit_empty_base_classes); - break; - default: - break; + default: + break; } - return num_children; -} + break; -CompilerType -ClangASTContext::GetBuiltinTypeByName (const ConstString &name) -{ - return GetBasicType(GetBasicTypeEnumeration(name)); -} + case clang::Type::Complex: + return 0; -lldb::BasicType -ClangASTContext::GetBasicTypeEnumeration (lldb::opaque_compiler_type_t 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<clang::BuiltinType>(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; - default: - return eBasicTypeOther; - } + case clang::Type::Record: + if (GetCompleteQualType(getASTContext(), qual_type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(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<clang::CXXRecordDecl>( + base_class->getType() + ->getAs<clang::RecordType>() + ->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(); } - } - return eBasicTypeInvalid; -} - -void -ClangASTContext::ForEachEnumerator (lldb::opaque_compiler_type_t type, std::function <bool (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value)> const &callback) -{ - const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)); - if (enum_type) - { - const clang::EnumDecl *enum_decl = enum_type->getDecl(); - if (enum_decl) - { - CompilerType integer_type(this, enum_decl->getIntegerType().getAsOpaquePtr()); - - 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) - { - ConstString name(enum_pos->getNameAsString().c_str()); - if (!callback (integer_type, name, enum_pos->getInitVal())) - break; - } + } + 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<clang::ObjCObjectType>(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<clang::ObjCObjectPointerType>(qual_type.getTypePtr()); + clang::QualType pointee_type = pointer_type->getPointeeType(); + uint32_t num_pointee_children = + CompilerType(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<clang::VectorType>(qual_type.getTypePtr())->getNumElements(); + break; + + case clang::Type::ConstantArray: + num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr()) + ->getSize() + .getLimitedValue(); + break; + + case clang::Type::Pointer: { + const clang::PointerType *pointer_type = + llvm::cast<clang::PointerType>(qual_type.getTypePtr()); + clang::QualType pointee_type(pointer_type->getPointeeType()); + uint32_t num_pointee_children = + CompilerType(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<clang::ReferenceType>(qual_type.getTypePtr()); + clang::QualType pointee_type = reference_type->getPointeeType(); + uint32_t num_pointee_children = + CompilerType(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 = + CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetNumChildren(omit_empty_base_classes); + break; + + case clang::Type::Auto: + num_children = + CompilerType(getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetNumChildren(omit_empty_base_classes); + break; + + case clang::Type::Elaborated: + num_children = + CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetNumChildren(omit_empty_base_classes); + break; + + case clang::Type::Paren: + num_children = + CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetNumChildren(omit_empty_base_classes); + break; + default: + break; + } + return num_children; +} + +CompilerType ClangASTContext::GetBuiltinTypeByName(const ConstString &name) { + return GetBasicType(GetBasicTypeEnumeration(name)); } +lldb::BasicType +ClangASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t 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<clang::BuiltinType>(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; + default: + return eBasicTypeOther; + } + } + } + return eBasicTypeInvalid; +} + +void ClangASTContext::ForEachEnumerator( + lldb::opaque_compiler_type_t type, + std::function<bool(const CompilerType &integer_type, + const ConstString &name, + const llvm::APSInt &value)> const &callback) { + const clang::EnumType *enum_type = + llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)); + if (enum_type) { + const clang::EnumDecl *enum_decl = enum_type->getDecl(); + if (enum_decl) { + CompilerType integer_type(this, + enum_decl->getIntegerType().getAsOpaquePtr()); + + 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) { + ConstString name(enum_pos->getNameAsString().c_str()); + if (!callback(integer_type, name, enum_pos->getInitVal())) + break; + } + } + } +} #pragma mark Aggregate Types -uint32_t -ClangASTContext::GetNumFields (lldb::opaque_compiler_type_t 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<clang::RecordType>(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 = CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumFields(); - break; +uint32_t ClangASTContext::GetNumFields(lldb::opaque_compiler_type_t type) { + if (!type) + return 0; - case clang::Type::Auto: - count = CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetNumFields(); - break; - - case clang::Type::Elaborated: - count = CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumFields(); - break; - - case clang::Type::Paren: - count = CompilerType (getASTContext(), llvm::cast<clang::ParenType>(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<clang::ObjCObjectType>(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; + 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<clang::RecordType>(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 = + CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetNumFields(); + break; + + case clang::Type::Auto: + count = + CompilerType(getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetNumFields(); + break; + + case clang::Type::Elaborated: + count = CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetNumFields(); + break; + + case clang::Type::Paren: + count = CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetNumFields(); + break; + + case clang::Type::ObjCObjectPointer: { + const clang::ObjCObjectPointerType *objc_class_type = + qual_type->getAsObjCInterfacePointerType(); + const clang::ObjCInterfaceType *objc_interface_type = + objc_class_type->getInterfaceType(); + if (objc_interface_type && + GetCompleteType((lldb::opaque_compiler_type_t)objc_interface_type)) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_interface_type->getDecl(); + 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<clang::ObjCObjectType>(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(); + } } - return count; + break; + + default: + break; + } + return count; } static lldb::opaque_compiler_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(); - } +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; + } + return nullptr; } -CompilerType -ClangASTContext::GetFieldAtIndex (lldb::opaque_compiler_type_t 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 CompilerType(); - - 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<clang::RecordType>(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 CompilerType (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 CompilerType (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<clang::ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - return CompilerType (this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); - } - } - break; - - - case clang::Type::Typedef: - return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - default: - break; - } +CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t 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 CompilerType(); -} -uint32_t -ClangASTContext::GetNumDirectBaseClasses (lldb::opaque_compiler_type_t type) -{ - 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::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - count = cxx_record_decl->getNumBases(); + 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<clang::RecordType>(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(); + } } - break; - - case clang::Type::ObjCObjectPointer: - count = GetPointeeType(type).GetNumDirectBaseClasses(); - break; - - case clang::Type::ObjCObject: - if (GetCompleteType(type)) - { - 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(type)) - { - const clang::ObjCInterfaceType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>(); - 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(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - break; - - case clang::Type::Auto: - count = GetNumDirectBaseClasses(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - break; - - case clang::Type::Elaborated: - count = GetNumDirectBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - break; - - case clang::Type::Paren: - return GetNumDirectBaseClasses(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - - default: - break; - } - return count; + } + if (is_bitfield_ptr) + *is_bitfield_ptr = is_bitfield; + return CompilerType(getASTContext(), field->getType()); + } + } + } + break; + + case clang::Type::ObjCObjectPointer: { + const clang::ObjCObjectPointerType *objc_class_type = + qual_type->getAsObjCInterfacePointerType(); + const clang::ObjCInterfaceType *objc_interface_type = + objc_class_type->getInterfaceType(); + if (objc_interface_type && + GetCompleteType((lldb::opaque_compiler_type_t)objc_interface_type)) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_interface_type->getDecl(); + if (class_interface_decl) { + return CompilerType( + 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<clang::ObjCObjectType>(qual_type.getTypePtr()); + assert(objc_class_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + return CompilerType( + this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, + idx, name, bit_offset_ptr, + bitfield_bit_size_ptr, is_bitfield_ptr)); + } + } + break; + + case clang::Type::Typedef: + return CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr); + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr); + + default: + break; + } + return CompilerType(); } uint32_t -ClangASTContext::GetNumVirtualBaseClasses (lldb::opaque_compiler_type_t type) -{ - 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::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - count = cxx_record_decl->getNumVBases(); - } - break; - - case clang::Type::Typedef: - count = GetNumVirtualBaseClasses(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - break; - - case clang::Type::Auto: - count = GetNumVirtualBaseClasses(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - break; - - case clang::Type::Elaborated: - count = GetNumVirtualBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - break; - - case clang::Type::Paren: - count = GetNumVirtualBaseClasses(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - break; - - default: - break; - } - return count; - +ClangASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) { + 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::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + count = cxx_record_decl->getNumBases(); + } + break; + + case clang::Type::ObjCObjectPointer: + count = GetPointeeType(type).GetNumDirectBaseClasses(); + break; + + case clang::Type::ObjCObject: + if (GetCompleteType(type)) { + 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(type)) { + const clang::ObjCInterfaceType *objc_interface_type = + qual_type->getAs<clang::ObjCInterfaceType>(); + 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(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + break; + + case clang::Type::Auto: + count = GetNumDirectBaseClasses(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + break; + + case clang::Type::Elaborated: + count = GetNumDirectBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + break; + + case clang::Type::Paren: + return GetNumDirectBaseClasses( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + + default: + break; + } + return count; } -CompilerType -ClangASTContext::GetDirectBaseClassAtIndex (lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) -{ - 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) - { - 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 = getASTContext()->getASTRecordLayout(cxx_record_decl); - const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->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 CompilerType (this, base_class->getType().getAsOpaquePtr()); - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - return GetPointeeType(type).GetDirectBaseClassAtIndex(idx, bit_offset_ptr); - - case clang::Type::ObjCObject: - if (idx == 0 && GetCompleteType(type)) - { - 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 CompilerType (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl)); - } - } - } +uint32_t +ClangASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) { + 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::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + count = cxx_record_decl->getNumVBases(); + } + break; + + case clang::Type::Typedef: + count = GetNumVirtualBaseClasses(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + break; + + case clang::Type::Auto: + count = GetNumVirtualBaseClasses(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + break; + + case clang::Type::Elaborated: + count = + GetNumVirtualBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + break; + + case clang::Type::Paren: + count = GetNumVirtualBaseClasses( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + break; + + default: + break; + } + return count; +} + +CompilerType ClangASTContext::GetDirectBaseClassAtIndex( + lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) { + 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) { + 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 = + getASTContext()->getASTRecordLayout(cxx_record_decl); + const clang::CXXRecordDecl *base_class_decl = + llvm::cast<clang::CXXRecordDecl>( + base_class->getType() + ->getAs<clang::RecordType>() + ->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; } - break; - case clang::Type::ObjCInterface: - if (idx == 0 && GetCompleteType(type)) - { - const clang::ObjCObjectType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>(); - 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 CompilerType (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl)); - } - } - } + return CompilerType(this, base_class->getType().getAsOpaquePtr()); + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + return GetPointeeType(type).GetDirectBaseClassAtIndex(idx, bit_offset_ptr); + + case clang::Type::ObjCObject: + if (idx == 0 && GetCompleteType(type)) { + 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 CompilerType(getASTContext(), + getASTContext()->getObjCInterfaceType( + superclass_interface_decl)); + } + } + } + } + break; + case clang::Type::ObjCInterface: + if (idx == 0 && GetCompleteType(type)) { + const clang::ObjCObjectType *objc_interface_type = + qual_type->getAs<clang::ObjCInterfaceType>(); + 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 CompilerType(getASTContext(), + getASTContext()->getObjCInterfaceType( + superclass_interface_decl)); + } + } + } + } + break; + + case clang::Type::Typedef: + return GetDirectBaseClassAtIndex(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); + + case clang::Type::Auto: + return GetDirectBaseClassAtIndex(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); + + case clang::Type::Elaborated: + return GetDirectBaseClassAtIndex( + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); + + case clang::Type::Paren: + return GetDirectBaseClassAtIndex( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + idx, bit_offset_ptr); + + default: + break; + } + return CompilerType(); +} + +CompilerType ClangASTContext::GetVirtualBaseClassAtIndex( + lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) { + 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) { + 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 = + getASTContext()->getASTRecordLayout(cxx_record_decl); + const clang::CXXRecordDecl *base_class_decl = + llvm::cast<clang::CXXRecordDecl>( + base_class->getType() + ->getAs<clang::RecordType>() + ->getDecl()); + *bit_offset_ptr = + record_layout.getVBaseClassOffset(base_class_decl) + .getQuantity() * + 8; } - break; - - - case clang::Type::Typedef: - return GetDirectBaseClassAtIndex (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Auto: - return GetDirectBaseClassAtIndex (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Elaborated: - return GetDirectBaseClassAtIndex (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Paren: - return GetDirectBaseClassAtIndex (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx, bit_offset_ptr); - - default: - break; + return CompilerType(this, base_class->getType().getAsOpaquePtr()); + } + } + } } - return CompilerType(); -} + break; -CompilerType -ClangASTContext::GetVirtualBaseClassAtIndex (lldb::opaque_compiler_type_t type, - size_t idx, - uint32_t *bit_offset_ptr) -{ - 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) - { - 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 = getASTContext()->getASTRecordLayout(cxx_record_decl); - const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; + case clang::Type::Typedef: + return GetVirtualBaseClassAtIndex(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); - } - return CompilerType (this, base_class->getType().getAsOpaquePtr()); - } - } - } - } - break; + case clang::Type::Auto: + return GetVirtualBaseClassAtIndex(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); - case clang::Type::Typedef: - return GetVirtualBaseClassAtIndex (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Auto: - return GetVirtualBaseClassAtIndex (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Elaborated: - return GetVirtualBaseClassAtIndex (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx, bit_offset_ptr); + case clang::Type::Elaborated: + return GetVirtualBaseClassAtIndex( + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); - case clang::Type::Paren: - return GetVirtualBaseClassAtIndex(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx, - bit_offset_ptr); - - default: - break; - } - return CompilerType(); + case clang::Type::Paren: + return GetVirtualBaseClassAtIndex( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + idx, bit_offset_ptr); + default: + break; + } + return CompilerType(); } // If a pointer to a pointee type (the clang_type arg) says that it has no @@ -5969,776 +6181,754 @@ ClangASTContext::GetVirtualBaseClassAtIndex (lldb::opaque_compiler_type_t type, // 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<clang::BuiltinType>(qual_type)->getKind()) - { - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - case clang::BuiltinType::NullPtr: - case clang::BuiltinType::OCLEvent: - case clang::BuiltinType::OCLImage1dRO: - case clang::BuiltinType::OCLImage1dWO: - case clang::BuiltinType::OCLImage1dRW: - case clang::BuiltinType::OCLImage1dArrayRO: - case clang::BuiltinType::OCLImage1dArrayWO: - case clang::BuiltinType::OCLImage1dArrayRW: - case clang::BuiltinType::OCLImage1dBufferRO: - case clang::BuiltinType::OCLImage1dBufferWO: - case clang::BuiltinType::OCLImage1dBufferRW: - case clang::BuiltinType::OCLImage2dRO: - case clang::BuiltinType::OCLImage2dWO: - case clang::BuiltinType::OCLImage2dRW: - case clang::BuiltinType::OCLImage2dArrayRO: - case clang::BuiltinType::OCLImage2dArrayWO: - case clang::BuiltinType::OCLImage2dArrayRW: - case clang::BuiltinType::OCLImage3dRO: - case clang::BuiltinType::OCLImage3dWO: - case clang::BuiltinType::OCLImage3dRW: - 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: - case clang::BuiltinType::OMPArraySection: - return 1; - default: - return 0; - } - 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<clang::ParenType>(qual_type)->desugar()); - case clang::Type::Typedef: return GetNumPointeeChildren (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()); - case clang::Type::Auto: return GetNumPointeeChildren (llvm::cast<clang::AutoType>(qual_type)->getDeducedType()); - case clang::Type::Elaborated: return GetNumPointeeChildren (llvm::cast<clang::ElaboratedType>(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; - } +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<clang::BuiltinType>(qual_type)->getKind()) { + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::Void: + case clang::BuiltinType::NullPtr: + case clang::BuiltinType::OCLEvent: + case clang::BuiltinType::OCLImage1dRO: + case clang::BuiltinType::OCLImage1dWO: + case clang::BuiltinType::OCLImage1dRW: + case clang::BuiltinType::OCLImage1dArrayRO: + case clang::BuiltinType::OCLImage1dArrayWO: + case clang::BuiltinType::OCLImage1dArrayRW: + case clang::BuiltinType::OCLImage1dBufferRO: + case clang::BuiltinType::OCLImage1dBufferWO: + case clang::BuiltinType::OCLImage1dBufferRW: + case clang::BuiltinType::OCLImage2dRO: + case clang::BuiltinType::OCLImage2dWO: + case clang::BuiltinType::OCLImage2dRW: + case clang::BuiltinType::OCLImage2dArrayRO: + case clang::BuiltinType::OCLImage2dArrayWO: + case clang::BuiltinType::OCLImage2dArrayRW: + case clang::BuiltinType::OCLImage3dRO: + case clang::BuiltinType::OCLImage3dWO: + case clang::BuiltinType::OCLImage3dRW: + 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: + case clang::BuiltinType::OMPArraySection: + return 1; + default: + return 0; + } + break; -CompilerType -ClangASTContext::GetChildCompilerTypeAtIndex (lldb::opaque_compiler_type_t 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, - uint64_t &language_flags) -{ - if (!type) - return CompilerType(); - - 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; - language_flags = 0; - - 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<clang::BuiltinType>(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 CompilerType (getASTContext(), getASTContext()->ObjCBuiltinClassTy); - - default: - break; - } - } - break; - - case clang::Type::Record: - if (idx_is_valid && GetCompleteType(type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(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<clang::CXXRecordDecl>(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<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - if (ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - } - - if (idx == child_idx) - { - if (base_class_decl == nullptr) - base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->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<clang::MicrosoftVTableContext *>(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<clang::ItaniumVTableContext *>(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_size = process->GetAddressByteSize(); - const uint64_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, base_offset_size, 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; - CompilerType 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. - CompilerType 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); - const uint32_t child_bit_size = child_byte_size * 8; - - // Figure out the field offset within the current struct/union/class type - bit_offset = record_layout.getFieldOffset (field_idx); - if (ClangASTContext::FieldIsBitfield (getASTContext(), *field, child_bitfield_bit_size)) - { - child_bitfield_bit_offset = bit_offset % child_bit_size; - const uint32_t child_bit_offset = bit_offset - child_bitfield_bit_offset; - child_byte_offset = child_bit_offset / 8; - } - else - { - child_byte_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<clang::ObjCObjectType>(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) - { - CompilerType 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 CompilerType (getASTContext(), ivar_qual_type); - } - - ++child_idx; - } + 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<clang::ParenType>(qual_type)->desugar()); + case clang::Type::Typedef: + return GetNumPointeeChildren(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()); + case clang::Type::Auto: + return GetNumPointeeChildren( + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()); + case clang::Type::Elaborated: + return GetNumPointeeChildren( + llvm::cast<clang::ElaboratedType>(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; +} + +CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( + lldb::opaque_compiler_type_t 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, uint64_t &language_flags) { + if (!type) + return CompilerType(); + + 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; + language_flags = 0; + + 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<clang::BuiltinType>(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 CompilerType(getASTContext(), + getASTContext()->ObjCBuiltinClassTy); + + default: + break; + } + } + break; + + case clang::Type::Record: + if (idx_is_valid && GetCompleteType(type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(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<clang::CXXRecordDecl>(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<clang::CXXRecordDecl>( + base_class->getType()->getAs<clang::RecordType>()->getDecl()); + if (ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + } + + if (idx == child_idx) { + if (base_class_decl == nullptr) + base_class_decl = llvm::cast<clang::CXXRecordDecl>( + base_class->getType()->getAs<clang::RecordType>()->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<clang::MicrosoftVTableContext *>( + 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 - ++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) - { - CompilerType 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<int32_t>(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 CompilerType (getASTContext(), ivar_qual_type); - } - ++child_idx; + } else { + clang::ItaniumVTableContext *itanium_vtable_ctx = + static_cast<clang::ItaniumVTableContext *>( + 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_size = + process->GetAddressByteSize(); + const uint64_t base_offset = + process->ReadUnsignedIntegerFromMemory( + base_offset_addr, base_offset_size, + UINT32_MAX, err); + if (base_offset < UINT32_MAX) { + handled = true; + bit_offset = base_offset * 8; } + } } + } } + } } - } - break; - - case clang::Type::ObjCObjectPointer: - if (idx_is_valid) - { - CompilerType 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.GetChildCompilerTypeAtIndex (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, - language_flags); - } - 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<clang::VectorType>(parent_qual_type.getTypePtr()); - if (array) - { - CompilerType element_type (getASTContext(), array->getElementType()); - if (element_type.GetCompleteType()) - { - char element_name[64]; - ::snprintf (element_name, sizeof (element_name), "[%" PRIu64 "]", static_cast<uint64_t>(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) - { - CompilerType element_type (getASTContext(), array->getElementType()); - if (element_type.GetCompleteType()) - { - char element_name[64]; - ::snprintf (element_name, sizeof (element_name), "[%" PRIu64 "]", static_cast<uint64_t>(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) - { - CompilerType pointee_clang_type (GetPointeeType(type)); - - // Don't dereference "void *" pointers - if (pointee_clang_type.IsVoidType()) - return CompilerType(); - - 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.GetChildCompilerTypeAtIndex (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, - language_flags); + } + 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; + CompilerType 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()); + + // Figure out the type byte size (field_type_info.first) and + // alignment (field_type_info.second) from the AST context. + CompilerType 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); + const uint32_t child_bit_size = child_byte_size * 8; + + // Figure out the field offset within the current struct/union/class + // type + bit_offset = record_layout.getFieldOffset(field_idx); + if (ClangASTContext::FieldIsBitfield(getASTContext(), *field, + child_bitfield_bit_size)) { + child_bitfield_bit_offset = bit_offset % child_bit_size; + const uint32_t child_bit_offset = + bit_offset - child_bitfield_bit_offset; + child_byte_offset = child_bit_offset / 8; + } else { + child_byte_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<clang::ObjCObjectType>(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) { + CompilerType 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()); + + 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 CompilerType(getASTContext(), ivar_qual_type); } - 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; - } + + ++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()); + + 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) { + CompilerType parent_ast_type(getASTContext(), + parent_qual_type); + child_byte_offset = objc_runtime->GetByteOffsetForIvar( + parent_ast_type, ivar_decl->getNameAsString().c_str()); + } } - } - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - if (idx_is_valid) - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr()); - CompilerType 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.GetChildCompilerTypeAtIndex (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, - language_flags); + + // Setting this to UINT32_MAX to make sure we don't compute it + // twice... + bit_offset = UINT32_MAX; + + if (child_byte_offset == + static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET)) { + bit_offset = interface_layout.getFieldOffset(child_idx - + superclass_idx); + child_byte_offset = bit_offset / 8; } - 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; - } + + // 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 CompilerType(getASTContext(), ivar_qual_type); + } + ++child_idx; } - break; - - case clang::Type::Typedef: - { - CompilerType typedefed_clang_type (getASTContext(), llvm::cast<clang::TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType()); - return typedefed_clang_type.GetChildCompilerTypeAtIndex (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, - language_flags); + } } - break; - - case clang::Type::Auto: - { - CompilerType elaborated_clang_type (getASTContext(), llvm::cast<clang::AutoType>(parent_qual_type)->getDeducedType()); - return elaborated_clang_type.GetChildCompilerTypeAtIndex (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, - language_flags); + } + } + break; + + case clang::Type::ObjCObjectPointer: + if (idx_is_valid) { + CompilerType 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.GetChildCompilerTypeAtIndex( + 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, + language_flags); + } 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; } - - case clang::Type::Elaborated: - { - CompilerType elaborated_clang_type (getASTContext(), llvm::cast<clang::ElaboratedType>(parent_qual_type)->getNamedType()); - return elaborated_clang_type.GetChildCompilerTypeAtIndex (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, - language_flags); + } + } + break; + + case clang::Type::Vector: + case clang::Type::ExtVector: + if (idx_is_valid) { + const clang::VectorType *array = + llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr()); + if (array) { + CompilerType element_type(getASTContext(), array->getElementType()); + if (element_type.GetCompleteType()) { + char element_name[64]; + ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", + static_cast<uint64_t>(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; } - - case clang::Type::Paren: - { - CompilerType paren_clang_type (getASTContext(), llvm::cast<clang::ParenType>(parent_qual_type)->desugar()); - return paren_clang_type.GetChildCompilerTypeAtIndex (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, - language_flags); + } + } + 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) { + CompilerType element_type(getASTContext(), array->getElementType()); + if (element_type.GetCompleteType()) { + child_name = llvm::formatv("[{0}]", idx); + 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; } - - - default: - break; + } } - return CompilerType(); -} + break; -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<clang::CXXRecordDecl>(record_decl); - - // const char *super_name = record_decl->getNameAsCString(); - // const char *base_name = base_spec->getType()->getAs<clang::RecordType>()->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<clang::RecordType>()->getDecl()->getNameAsCString()); - // - // - if (base_class == base_spec) - return child_idx; - ++child_idx; + case clang::Type::Pointer: + if (idx_is_valid) { + CompilerType pointee_clang_type(GetPointeeType(type)); + + // Don't dereference "void *" pointers + if (pointee_clang_type.IsVoidType()) + return CompilerType(); + + 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.GetChildCompilerTypeAtIndex( + 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, + language_flags); + } 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; } - } - - return UINT32_MAX; -} + // 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<clang::ReferenceType>(parent_qual_type.getTypePtr()); + CompilerType 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.GetChildCompilerTypeAtIndex( + 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, + language_flags); + } else { + const char *parent_name = + valobj ? valobj->GetName().GetCString() : NULL; + if (parent_name) { + child_name.assign(1, '&'); + child_name += parent_name; + } -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<clang::CXXRecordDecl>(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; + // 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: { + CompilerType typedefed_clang_type( + getASTContext(), llvm::cast<clang::TypedefType>(parent_qual_type) + ->getDecl() + ->getUnderlyingType()); + return typedefed_clang_type.GetChildCompilerTypeAtIndex( + 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, language_flags); + } break; + + case clang::Type::Auto: { + CompilerType elaborated_clang_type( + getASTContext(), + llvm::cast<clang::AutoType>(parent_qual_type)->getDeducedType()); + return elaborated_clang_type.GetChildCompilerTypeAtIndex( + 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, language_flags); + } + + case clang::Type::Elaborated: { + CompilerType elaborated_clang_type( + getASTContext(), + llvm::cast<clang::ElaboratedType>(parent_qual_type)->getNamedType()); + return elaborated_clang_type.GetChildCompilerTypeAtIndex( + 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, language_flags); + } + + case clang::Type::Paren: { + CompilerType paren_clang_type( + getASTContext(), + llvm::cast<clang::ParenType>(parent_qual_type)->desugar()); + return paren_clang_type.GetChildCompilerTypeAtIndex( + 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, language_flags); + } + + default: + break; + } + return CompilerType(); +} + +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<clang::CXXRecordDecl>(record_decl); + + // const char *super_name = record_decl->getNameAsCString(); + // const char *base_name = + // base_spec->getType()->getAs<clang::RecordType>()->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<clang::RecordType>()->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<clang::CXXRecordDecl>(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 @@ -6765,3074 +6955,2849 @@ GetIndexForRecordChild (const clang::RecordDecl *record_decl, // 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: +// 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 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 (lldb::opaque_compiler_type_t type, const char *name, - bool omit_empty_base_classes, - std::vector<uint32_t>& 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<clang::RecordType>(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<clang::CXXRecordDecl>(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()) - { - CompilerType 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([decl_name](const clang::CXXBaseSpecifier *specifier, clang::CXXBasePath &path) { - return clang::CXXRecordDecl::FindOrdinaryMember(specifier, path, decl_name); - }, - 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<num_path_elements; ++e) - { - clang::CXXBasePathElement elem = (*path)[e]; - - child_idx = GetIndexForRecordBase (parent_record_decl, elem.Base, omit_empty_base_classes); - if (child_idx == UINT32_MAX) - { - child_indexes.clear(); - return 0; - } - else - { - child_indexes.push_back (child_idx); - parent_record_decl = llvm::cast<clang::RecordDecl>(elem.Base->getType()->getAs<clang::RecordType>()->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(); - } - } - +size_t ClangASTContext::GetIndexOfChildMemberWithName( + lldb::opaque_compiler_type_t type, const char *name, + bool omit_empty_base_classes, std::vector<uint32_t> &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<clang::RecordType>(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<clang::CXXRecordDecl>(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()) { + CompilerType 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( + [decl_name](const clang::CXXBaseSpecifier *specifier, + clang::CXXBasePath &path) { + return clang::CXXRecordDecl::FindOrdinaryMember( + specifier, path, decl_name); + }, + 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 < num_path_elements; ++e) { + clang::CXXBasePathElement elem = (*path)[e]; + + child_idx = GetIndexForRecordBase(parent_record_decl, elem.Base, + omit_empty_base_classes); + if (child_idx == UINT32_MAX) { + child_indexes.clear(); + return 0; + } else { + child_indexes.push_back(child_idx); + parent_record_decl = llvm::cast<clang::RecordDecl>( + elem.Base->getType() + ->getAs<clang::RecordType>() + ->getDecl()); } - 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<clang::ObjCObjectType>(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); - - CompilerType 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(); - } - } - } + } + 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); } - break; - - case clang::Type::ObjCObjectPointer: - { - CompilerType objc_object_clang_type (getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(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<clang::ConstantArrayType>(parent_qual_type.getTypePtr()); - // const uint64_t element_count = array->getSize().getLimitedValue(); - // - // if (idx < element_count) - // { - // std::pair<uint64_t, unsigned> 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<MemberPointerType>(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<clang::ReferenceType>(qual_type.getTypePtr()); - clang::QualType pointee_type(reference_type->getPointeeType()); - CompilerType pointee_clang_type (getASTContext(), pointee_type); - - if (pointee_clang_type.IsAggregateType ()) - { - return pointee_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - } + 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<clang::ObjCObjectType>(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(); + } } - break; - - case clang::Type::Pointer: - { - CompilerType pointee_clang_type (GetPointeeType(type)); - - if (pointee_clang_type.IsAggregateType ()) - { - return pointee_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - } + + 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); + + CompilerType 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::Typedef: - return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - default: - break; + } } + } + break; + + case clang::Type::ObjCObjectPointer: { + CompilerType objc_object_clang_type( + getASTContext(), + llvm::cast<clang::ObjCObjectPointerType>(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<clang::ConstantArrayType>(parent_qual_type.getTypePtr()); + // const uint64_t element_count = + // array->getSize().getLimitedValue(); + // + // if (idx < element_count) + // { + // std::pair<uint64_t, unsigned> 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<MemberPointerType>(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<clang::ReferenceType>(qual_type.getTypePtr()); + clang::QualType pointee_type(reference_type->getPointeeType()); + CompilerType 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: { + CompilerType 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 CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, + child_indexes); + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, + child_indexes); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, + child_indexes); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, + child_indexes); + + default: + break; } - return 0; + } + 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 (lldb::opaque_compiler_type_t 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<clang::RecordType>(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<clang::CXXRecordDecl>(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<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - if (omit_empty_base_classes && ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - - CompilerType 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<clang::ObjCObjectType>(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: - { - CompilerType pointee_clang_type (getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(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<clang::ConstantArrayType>(parent_qual_type.getTypePtr()); - // const uint64_t element_count = array->getSize().getLimitedValue(); - // - // if (idx < element_count) - // { - // std::pair<uint64_t, unsigned> 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<MemberPointerType>(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<clang::ReferenceType>(qual_type.getTypePtr()); - CompilerType 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<clang::PointerType>(qual_type.getTypePtr()); - CompilerType 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<uint64_t, unsigned> 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; +ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, + const char *name, + bool omit_empty_base_classes) { + if (type && name && name[0]) { + clang::QualType qual_type(GetCanonicalQualType(type)); - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - case clang::Type::Typedef: - return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - default: - break; + 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<clang::RecordType>(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<clang::CXXRecordDecl>(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<clang::CXXRecordDecl>( + base_class->getType() + ->getAs<clang::RecordType>() + ->getDecl()); + if (omit_empty_base_classes && + ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + + CompilerType 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; + } } - } - return UINT32_MAX; -} + // 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<clang::ObjCObjectType>(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; -size_t -ClangASTContext::GetNumTemplateArguments (lldb::opaque_compiler_type_t type) -{ - if (!type) - return 0; + return child_idx; + } + } - 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) - { - const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl); - if (template_decl) - return template_decl->getTemplateArgs().size(); - } + if (superclass_interface_decl) { + if (superclass_interface_decl->getName().equals(name_sref)) + return 0; } - break; - - case clang::Type::Typedef: - return (CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType())).GetNumTemplateArguments(); - - case clang::Type::Auto: - return (CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType())).GetNumTemplateArguments(); - - case clang::Type::Elaborated: - return (CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())).GetNumTemplateArguments(); - - case clang::Type::Paren: - return (CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar())).GetNumTemplateArguments(); - - default: - break; - } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: { + CompilerType pointee_clang_type( + getASTContext(), + llvm::cast<clang::ObjCObjectPointerType>(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<clang::ConstantArrayType>(parent_qual_type.getTypePtr()); + // const uint64_t element_count = + // array->getSize().getLimitedValue(); + // + // if (idx < element_count) + // { + // std::pair<uint64_t, unsigned> 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<MemberPointerType>(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<clang::ReferenceType>(qual_type.getTypePtr()); + CompilerType 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<clang::PointerType>(qual_type.getTypePtr()); + CompilerType 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<uint64_t, unsigned> 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::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetIndexOfChildWithName(name, omit_empty_base_classes); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetIndexOfChildWithName(name, omit_empty_base_classes); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetIndexOfChildWithName(name, omit_empty_base_classes); + + case clang::Type::Typedef: + return CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetIndexOfChildWithName(name, omit_empty_base_classes); - return 0; + default: + break; + } + } + return UINT32_MAX; } -CompilerType -ClangASTContext::GetTemplateArgument (lldb::opaque_compiler_type_t type, size_t arg_idx, lldb::TemplateArgumentKind &kind) -{ - if (!type) - return CompilerType(); +size_t +ClangASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { + 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::CXXRecord |