Depends on https://github.com/llvm/llvm-project/pull/100674 Currently, we treat VLAs declared as `int[]` and `int[0]` identically. I.e., we create them as `IncompleteArrayType`s. However, the `DW_AT_count` for `int[0]` *does* exist, and is retrievable without an execution context. This patch decouples the notion of "has 0 elements" from "has no known `DW_AT_count`". This aligns with how Clang represents `int[0]` in the AST (it treats it as a `ConstantArrayType` of 0 size). This issue was surfaced when adapting LLDB to https://github.com/llvm/llvm-project/issues/93069. There, the `__compressed_pair_padding` type has a `char[0]` member. If we previously got the `__compressed_pair_padding` out of a module (where clang represents `char[0]` as a `ConstantArrayType`), and try to merge the AST with one we got from DWARF (where LLDB used to represent `char[0]` as an `IncompleteArrayType`), the AST structural equivalence check fails, resulting in silent ASTImporter failures. This manifested in a failure in `TestNonModuleTypeSeparation.py`. **Implementation** 1. Adjust `ParseChildArrayInfo` to store the element counts of each VLA dimension as an `optional<uint64_t>`, instead of a regular `uint64_t`. So when we pass this down to `CreateArrayType`, we have a better heuristic for what is an `IncompleteArrayType`. 2. In `TypeSystemClang::GetBitSize`, if we encounter a `ConstantArrayType` simply return the size that it was created with. If we couldn't determine the authoritative bound from DWARF during parsing, we would've created an `IncompleteArrayType`. This ensures that `GetBitSize` on arrays with `DW_AT_count 0x0` returns `0` (whereas previously it would've returned a `std::nullopt`, causing that `FieldDecl` to just get dropped during printing)
81 lines
1.8 KiB
C++
81 lines
1.8 KiB
C++
// RUN: %clangxx_host -gdwarf -std=c++11 -o %t %s
|
|
// RUN: %lldb %t \
|
|
// RUN: -o run \
|
|
// RUN: -o "frame var --show-types f" \
|
|
// RUN: -o "frame var vla0" \
|
|
// RUN: -o "frame var fla0" \
|
|
// RUN: -o "frame var fla1" \
|
|
// RUN: -o "frame var vla01" \
|
|
// RUN: -o "frame var vla10" \
|
|
// RUN: -o "frame var vlaN" \
|
|
// RUN: -o "frame var vlaNM" \
|
|
// RUN: -o exit | FileCheck %s
|
|
|
|
struct Foo {
|
|
static constexpr int n = 1;
|
|
int m_vlaN[n];
|
|
|
|
int m_vla0[0];
|
|
};
|
|
|
|
int main() {
|
|
Foo f;
|
|
f.m_vlaN[0] = 60;
|
|
|
|
// CHECK: (lldb) frame var --show-types f
|
|
// CHECK-NEXT: (Foo) f = {
|
|
// CHECK-NEXT: (int[1]) m_vlaN = {
|
|
// CHECK-NEXT: (int) [0] = 60
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: (int[0]) m_vla0 = {}
|
|
// CHECK-NEXT: }
|
|
|
|
int vla0[0] = {};
|
|
|
|
// CHECK: (lldb) frame var vla0
|
|
// CHECK-NEXT: (int[0]) vla0 = {}
|
|
|
|
int fla0[] = {};
|
|
|
|
// CHECK: (lldb) frame var fla0
|
|
// CHECK-NEXT: (int[0]) fla0 = {}
|
|
|
|
int fla1[] = {42};
|
|
|
|
// CHECK: (lldb) frame var fla1
|
|
// CHECK-NEXT: (int[1]) fla1 = ([0] = 42)
|
|
|
|
int vla01[0][1];
|
|
|
|
// CHECK: (lldb) frame var vla01
|
|
// CHECK-NEXT: (int[0][1]) vla01 = {}
|
|
|
|
int vla10[1][0];
|
|
|
|
// CHECK: (lldb) frame var vla10
|
|
// CHECK-NEXT: (int[1][0]) vla10 = ([0] = int[0]
|
|
|
|
int n = 3;
|
|
int vlaN[n];
|
|
for (int i = 0; i < n; ++i)
|
|
vlaN[i] = -i;
|
|
|
|
// CHECK: (lldb) frame var vlaN
|
|
// CHECK-NEXT: (int[]) vlaN = ([0] = 0, [1] = -1, [2] = -2)
|
|
|
|
int m = 2;
|
|
int vlaNM[n][m];
|
|
for (int i = 0; i < n; ++i)
|
|
for (int j = 0; j < m; ++j)
|
|
vlaNM[i][j] = i + j;
|
|
|
|
// FIXME: multi-dimensional VLAs aren't well supported
|
|
// CHECK: (lldb) frame var vlaNM
|
|
// CHECK-NEXT: (int[][]) vlaNM = {
|
|
// CHECK-NEXT: [0] = ([0] = 0, [1] = 1, [2] = 1)
|
|
// CHECK-NEXT: [1] = ([0] = 1, [1] = 1, [2] = 2)
|
|
// CHECK-NEXT: }
|
|
|
|
__builtin_debugtrap();
|
|
}
|