| struct S { |
| int field; |
| int other; |
| void method(); |
| }; |
| |
| struct Inner { |
| int leaf; |
| int otherLeaf; |
| void method(); |
| }; |
| |
| struct Outer { |
| Inner inner; |
| Inner array[2]; |
| }; |
| |
| struct Base { |
| int inherited; |
| }; |
| |
| struct Derived : Base { |
| int direct; |
| }; |
| |
| struct RefOuter { |
| Inner &ref; |
| }; |
| |
| struct WithAnon { |
| int outer; |
| union { |
| int anonInt; |
| Inner anonInner; |
| }; |
| }; |
| |
| struct ShadowBase { |
| Inner shadowed; |
| }; |
| |
| struct ShadowDerived : ShadowBase { |
| using ShadowBase::shadowed; |
| }; |
| |
| struct WithBitField { |
| int regular; |
| int bit : 4; |
| int : 4; |
| int otherRegular; |
| }; |
| |
| struct WithAnonBitField { |
| int outer; |
| struct { |
| int anonRegular; |
| int anonBit : 4; |
| }; |
| }; |
| |
| #define offsetof(type, member) __builtin_offsetof(type, member) |
| |
| // Cursor immediately after the comma: empty designator path. |
| int empty = __builtin_offsetof(S, field); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):35 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-S --implicit-check-not=method %s |
| |
| // Cursor after a dot: completion in the nested record's type. |
| int after_dot = __builtin_offsetof(Outer, inner.leaf); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):49 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-INNER --implicit-check-not=method %s |
| |
| // Cursor after a dot following an array subscript. |
| int array = __builtin_offsetof(Outer, array[0].leaf); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):48 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-INNER --implicit-check-not=method %s |
| |
| // Inherited fields participate in offsetof completion. |
| int inherited = __builtin_offsetof(Derived, inherited); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):45 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-DERIVED %s |
| |
| // Reference field: dereferenced before continuing the path. |
| int ref = __builtin_offsetof(RefOuter, ref.leaf); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):44 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-INNER --implicit-check-not=method %s |
| |
| // Empty path on a record with anonymous-member indirect fields. |
| int anon_empty = __builtin_offsetof(WithAnon, anonInt); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):47 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-ANON %s |
| |
| // Designator that starts with an indirect field from an anonymous member. |
| int anon_nested = __builtin_offsetof(WithAnon, anonInner.leaf); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):58 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-INNER --implicit-check-not=method %s |
| |
| // Field exposed via `using Base::...` resolves through its UsingShadowDecl. |
| int shadowed = __builtin_offsetof(ShadowDerived, shadowed.leaf); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):59 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-INNER --implicit-check-not=method %s |
| |
| // Macro form expands to __builtin_offsetof with the same completion behavior. |
| int macro = offsetof(S, field); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):25 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-S --implicit-check-not=method %s |
| |
| // Bit-fields are not valid as the offsetof member designator |
| // (err_offsetof_bitfield), so they should not be offered as completions. |
| // Unnamed bit-fields have no identifier and are filtered out of lookup |
| // independently. |
| int bf = __builtin_offsetof(WithBitField, regular); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):43 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-BF --implicit-check-not=bit %s |
| |
| // Bit-fields exposed via an anonymous struct's IndirectFieldDecl are also |
| // filtered: the leaf field is what offsetof would name. |
| int abf = __builtin_offsetof(WithAnonBitField, outer); |
| // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:%(line-1):48 %s -o - -std=c++17 | FileCheck -check-prefix=CHECK-ABF --implicit-check-not=anonBit %s |
| |
| // CHECK-S-DAG: COMPLETION: field : [#int#]field |
| // CHECK-S-DAG: COMPLETION: other : [#int#]other |
| |
| // CHECK-INNER-DAG: COMPLETION: leaf : [#int#]leaf |
| // CHECK-INNER-DAG: COMPLETION: otherLeaf : [#int#]otherLeaf |
| |
| // CHECK-DERIVED-DAG: COMPLETION: direct : [#int#]direct |
| // CHECK-DERIVED-DAG: COMPLETION: inherited (InBase) : [#int#]inherited |
| |
| // CHECK-ANON-DAG: COMPLETION: anonInner : [#Inner#]anonInner |
| // CHECK-ANON-DAG: COMPLETION: anonInt : [#int#]anonInt |
| // CHECK-ANON-DAG: COMPLETION: outer : [#int#]outer |
| |
| // CHECK-BF-DAG: COMPLETION: regular : [#int#]regular |
| // CHECK-BF-DAG: COMPLETION: otherRegular : [#int#]otherRegular |
| |
| // CHECK-ABF-DAG: COMPLETION: outer : [#int#]outer |
| // CHECK-ABF-DAG: COMPLETION: anonRegular : [#int#]anonRegular |