tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, shafik, cor3ntin.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Put all the index expressions on the stack and cast them to `SInt64`. Then add
a new `OffsetOf` opcode so we can evaluate the index expressions.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D156400
Files:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/InterpBuiltin.cpp
clang/lib/AST/Interp/Opcodes.td
clang/test/AST/Interp/class-layout.cpp
clang/test/AST/Interp/literals.cpp
clang/test/Sema/offsetof-64.c
clang/test/SemaCXX/class-layout.cpp
clang/test/SemaCXX/offsetof-0x.cpp
clang/test/SemaCXX/offsetof.cpp
Index: clang/test/SemaCXX/offsetof.cpp
===================================================================
--- clang/test/SemaCXX/offsetof.cpp
+++ clang/test/SemaCXX/offsetof.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -verify %s -Winvalid-offsetof -std=c++98
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -verify %s -Winvalid-offsetof -std=c++98 -fexperimental-new-constant-interpreter
struct NonPOD {
virtual void f();
Index: clang/test/SemaCXX/offsetof-0x.cpp
===================================================================
--- clang/test/SemaCXX/offsetof-0x.cpp
+++ clang/test/SemaCXX/offsetof-0x.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -std=c++11 -verify %s -Winvalid-offsetof
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -std=c++11 -verify %s -Winvalid-offsetof -fexperimental-new-constant-interpreter
struct NonPOD {
virtual void f();
Index: clang/test/SemaCXX/class-layout.cpp
===================================================================
--- clang/test/SemaCXX/class-layout.cpp
+++ clang/test/SemaCXX/class-layout.cpp
@@ -14,6 +14,25 @@
// RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
// RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base -Wno-c++11-extensions
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-apple-darwin %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-scei-ps4 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-sie-ps5 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=16 -DCLANG_ABI_COMPAT=16
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+
+
+
+
// expected-no-diagnostics
#if !defined(__MVS__) && !defined(_AIX)
Index: clang/test/Sema/offsetof-64.c
===================================================================
--- clang/test/Sema/offsetof-64.c
+++ clang/test/Sema/offsetof-64.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-linux-gnu
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-linux-gnu -fexperimental-new-constant-interpreter
// PR15216
// Don't crash when taking computing the offset of structs with large arrays.
Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -933,6 +933,7 @@
(short)5;
(bool)1;
__null;
+ __builtin_offsetof(A, a);
return 0;
}
Index: clang/test/AST/Interp/class-layout.cpp
===================================================================
--- clang/test/AST/Interp/class-layout.cpp
+++ /dev/null
@@ -1,698 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -fexperimental-new-constant-interpreter -std=c++98 -Wno-inaccessible-base -Wno-c++11-extensions
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -fexperimental-new-constant-interpreter -std=c++11 -Wno-inaccessible-base
-// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -fsyntax-only -verify -fexperimental-new-constant-interpreter -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
-// RUN: %clang_cc1 -triple x86_64-scei-ps4 %s -fsyntax-only -verify -fexperimental-new-constant-interpreter -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
-// RUN: %clang_cc1 -triple x86_64-sie-ps5 %s -fsyntax-only -verify -fexperimental-new-constant-interpreter -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -fexperimental-new-constant-interpreter -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -fexperimental-new-constant-interpreter -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -fexperimental-new-constant-interpreter -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -fexperimental-new-constant-interpreter -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=16 -DCLANG_ABI_COMPAT=16
-// expected-no-diagnostics
-
-// FIXME: This is a copy of clang/test/SemaCXX/class-layout.cpp, but with the
-// __builtin_offsetof calls commented out. Once that is supported in the
-// new interpreter, we might as well remove this duplicated file and
-// just use the one in SemaCXX/.
-
-#define SA(n, p) int a##n[(p) ? 1 : -1]
-
-struct A {
- int a;
- char b;
-};
-
-SA(0, sizeof(A) == 8);
-
-struct B : A {
- char c;
-};
-
-SA(1, sizeof(B) == 12);
-
-struct C {
-// Make fields private so C won't be a POD type.
-private:
- int a;
- char b;
-};
-
-SA(2, sizeof(C) == 8);
-
-struct D : C {
- char c;
-};
-
-SA(3, sizeof(D) == 8);
-
-struct __attribute__((packed)) E {
- char b;
- int a;
-};
-
-SA(4, sizeof(E) == 5);
-
-struct __attribute__((packed)) F : E {
- char d;
-};
-
-SA(5, sizeof(F) == 6);
-
-struct G { G(); };
-struct H : G { };
-
-SA(6, sizeof(H) == 1);
-
-struct I {
- char b;
- int a;
-} __attribute__((packed));
-
-SA(6_1, sizeof(I) == 5);
-
-// PR5580
-namespace PR5580 {
-
-class A { bool iv0 : 1; };
-SA(7, sizeof(A) == 1);
-
-class B : A { bool iv0 : 1; };
-SA(8, sizeof(B) == 2);
-
-struct C { bool iv0 : 1; };
-SA(9, sizeof(C) == 1);
-
-struct D : C { bool iv0 : 1; };
-SA(10, sizeof(D) == 2);
-
-}
-
-namespace Test1 {
-
-// Test that we don't assert on this hierarchy.
-struct A { };
-struct B : A { virtual void b(); };
-class C : virtual A { int c; };
-struct D : virtual B { };
-struct E : C, virtual D { };
-class F : virtual E { };
-struct G : virtual E, F { };
-
-SA(0, sizeof(G) == 24);
-
-}
-
-namespace Test2 {
-
-// Test that this somewhat complex class structure is laid out correctly.
-struct A { };
-struct B : A { virtual void b(); };
-struct C : virtual B { };
-struct D : virtual A { };
-struct E : virtual B, D { };
-struct F : E, virtual C { };
-struct G : virtual F, A { };
-struct H { G g; };
-
-SA(0, sizeof(H) == 24);
-
-}
-
-namespace PR16537 {
-namespace test1 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct tail_padded_pod_in_11_only {
- pod_in_11_only pod11;
- char tail_padding;
- };
-
- struct might_use_tail_padding : public tail_padded_pod_in_11_only {
- char may_go_into_tail_padding;
- };
-
- SA(0, sizeof(might_use_tail_padding) == 16);
-}
-
-namespace test2 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct tail_padded_pod_in_11_only {
- pod_in_11_only pod11 __attribute__((aligned(16)));
- };
-
- struct might_use_tail_padding : public tail_padded_pod_in_11_only {
- char may_go_into_tail_padding;
- };
-
- SA(0, sizeof(might_use_tail_padding) == 16);
-}
-
-namespace test3 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct tail_padded_pod_in_11_only {
- pod_in_11_only pod11;
- char tail_padding;
- };
-
- struct second_base {
- char foo;
- };
-
- struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base {
-
- };
- SA(0, sizeof(might_use_tail_padding) == 16);
-}
-
-namespace test4 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct tail_padded_pod_in_11_only {
- pod_in_11_only pod11;
- char tail_padding;
- };
-
- struct second_base {
- char foo;
- };
-
- struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base {
- char may_go_into_tail_padding;
- };
- SA(0, sizeof(might_use_tail_padding) == 16);
-}
-
-namespace test5 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct pod_in_11_only2 {
- private:
- long long x;
- };
-
- struct tail_padded_pod_in_11_only {
- pod_in_11_only pod11;
- char tail_padding;
- };
-
- struct second_base {
- pod_in_11_only2 two;
- char foo;
- };
-
- struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base {
- char may_go_into_tail_padding;
- };
- SA(0, sizeof(might_use_tail_padding) == 32);
-}
-
-namespace test6 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct pod_in_11_only2 {
- private:
- long long x;
- };
-
- struct tail_padded_pod_in_11_only {
- pod_in_11_only pod11;
- char tail_padding;
- };
-
- struct second_base {
- pod_in_11_only2 two;
- char foo;
- };
-
- struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base {
- char may_go_into_tail_padding;
- };
- SA(0, sizeof(might_use_tail_padding) == 32);
-}
-
-namespace test7 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct tail_padded_pod_in_11_only {
- pod_in_11_only pod11;
- pod_in_11_only pod12;
- char tail_padding;
- };
-
- struct might_use_tail_padding : public tail_padded_pod_in_11_only {
- char may_go_into_tail_padding;
- };
-
- SA(0, sizeof(might_use_tail_padding) == 24);
-}
-
-namespace test8 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct tail_padded_pod_in_11_only {
- pod_in_11_only pod11;
- char tail_padding;
- };
-
- struct another_layer {
- tail_padded_pod_in_11_only pod;
- char padding;
- };
-
- struct might_use_tail_padding : public another_layer {
- char may_go_into_tail_padding;
- };
-
- SA(0, sizeof(might_use_tail_padding) == 24);
-}
-
-namespace test9 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct tail_padded_pod_in_11_only {
- pod_in_11_only pod11;
- char tail_padding;
- };
-
- struct another_layer : tail_padded_pod_in_11_only {
- };
-
- struct might_use_tail_padding : public another_layer {
- char may_go_into_tail_padding;
- };
-
- SA(0, sizeof(might_use_tail_padding) == 16);
-}
-
-namespace test10 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct A {
- pod_in_11_only a;
- char apad;
- };
-
- struct B {
- char b;
- };
-
- struct C {
- pod_in_11_only c;
- char cpad;
- };
-
- struct D {
- char d;
- };
-
- struct might_use_tail_padding : public A, public B, public C, public D {
- };
-
- SA(0, sizeof(might_use_tail_padding) == 32);
-}
-
-namespace test11 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct A {
- pod_in_11_only a;
- char apad;
- };
-
- struct B {
- char b_pre;
- pod_in_11_only b;
- char bpad;
- };
-
- struct C {
- char c_pre;
- pod_in_11_only c;
- char cpad;
- };
-
- struct D {
- char d_pre;
- pod_in_11_only d;
- char dpad;
- };
-
- struct might_use_tail_padding : public A, public B, public C, public D {
- char m;
- };
-
- SA(0, sizeof(might_use_tail_padding) == 88);
-}
-
-namespace test12 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct A {
- pod_in_11_only a __attribute__((aligned(128)));
- };
-
- struct B {
- char bpad;
- };
-
- struct C {
- char cpad;
- };
-
- struct D {
- char dpad;
- };
-
- struct might_use_tail_padding : public A, public B, public C, public D {
- char m;
- };
- SA(0, sizeof(might_use_tail_padding) == 128);
-}
-
-namespace test13 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct A {
- pod_in_11_only a;
- char apad;
- };
-
- struct B {
- };
-
- struct C {
- char c_pre;
- pod_in_11_only c;
- char cpad;
- };
-
- struct D {
- };
-
- struct might_use_tail_padding : public A, public B, public C, public D {
- char m;
- };
- SA(0, sizeof(might_use_tail_padding) == 40);
-}
-
-namespace test14 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct A {
- pod_in_11_only a;
- char apad;
- };
-
- struct might_use_tail_padding : public A {
- struct {
- int : 0;
- } x;
- };
- SA(0, sizeof(might_use_tail_padding) == 16);
-}
-
-namespace test15 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct A {
- pod_in_11_only a;
- char apad;
- };
-
- struct might_use_tail_padding : public A {
- struct {
- char a:1;
- char b:2;
- char c:2;
- char d:2;
- char e:1;
- } x;
- };
- SA(0, sizeof(might_use_tail_padding) == 16);
-}
-
-namespace test16 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct A {
- pod_in_11_only a;
- char apad;
- };
-
- struct B {
- char bpod;
- pod_in_11_only b;
- char bpad;
- };
-
- struct C : public A, public B {
- };
-
- struct D : public C {
- };
-
- struct might_use_tail_padding : public D {
- char m;
- };
- SA(0, sizeof(might_use_tail_padding) == 40);
-}
-
-namespace test17 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct A {
- pod_in_11_only a __attribute__((aligned(512)));
- };
-
- struct B {
- char bpad;
- pod_in_11_only foo;
- char btail;
- };
-
- struct C {
- char cpad;
- };
-
- struct D {
- char dpad;
- };
-
- struct might_use_tail_padding : public A, public B, public C, public D {
- char a;
- };
- SA(0, sizeof(might_use_tail_padding) == 512);
-}
-
-namespace test18 {
- struct pod_in_11_only {
- private:
- long long x;
- };
-
- struct A {
- pod_in_11_only a;
- char apad;
- };
-
- struct B {
- char bpod;
- pod_in_11_only b;
- char bpad;
- };
-
- struct A1 {
- pod_in_11_only a;
- char apad;
- };
-
- struct B1 {
- char bpod;
- pod_in_11_only b;
- char bpad;
- };
-
- struct C : public A, public B {
- };
-
- struct D : public A1, public B1 {
- };
-
- struct E : public D, public C {
- };
-
- struct F : public E {
- };
-
- struct might_use_tail_padding : public F {
- char m;
- };
- SA(0, sizeof(might_use_tail_padding) == 80);
-}
-} // namespace PR16537
-
-namespace PR37275 {
- struct X { char c; };
-
- struct A { int n; };
- _Static_assert(_Alignof(A) == _Alignof(int), "");
- _Static_assert(_Alignof(A[]) == _Alignof(A), "");
-
- _Static_assert(_Alignof(int[]) == _Alignof(int), "");
- _Static_assert(_Alignof(char[]) == _Alignof(char), "");
-
- // __attribute__((packed)) does not apply to base classes.
- struct __attribute__((packed)) B : X, A {};
-#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 6
- _Static_assert(_Alignof(B) == 1, "");
- _Static_assert(_Alignof(B[]) == 1, "");
- //_Static_assert(__builtin_offsetof(B, n) == 1, ""); FIXME
-#else
- _Static_assert(_Alignof(B) == _Alignof(int), "");
- _Static_assert(_Alignof(B[]) == _Alignof(int), "");
- //_Static_assert(__builtin_offsetof(B, n) == 4, ""); FIXME
-#endif
-
- // #pragma pack does, though.
-#pragma pack(push, 2)
- struct C : X, A {};
- _Static_assert(_Alignof(C) == 2, "");
- _Static_assert(_Alignof(C[]) == 2, "");
- //_Static_assert(__builtin_offsetof(C, n) == 2, ""); FIXME
-
- struct __attribute__((packed)) D : X, A {};
-#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 6
- _Static_assert(_Alignof(D) == 1, "");
- //_Static_assert(__builtin_offsetof(D, n) == 1, ""); FIXME
-#else
- _Static_assert(_Alignof(D) == 2, "");
- //_Static_assert(__builtin_offsetof(D, n) == 2, ""); FIXME
-#endif
-#pragma pack(pop)
-}
-
-namespace non_pod {
-struct t1 {
-protected:
- int a;
-};
-// GCC prints warning: ignoring packed attribute because of unpacked non-POD field 't1 t2::v1'`
-struct t2 {
- char c1;
- short s1;
- char c2;
- t1 v1;
-} __attribute__((packed));
-#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 15
-_Static_assert(_Alignof(t1) == 4, "");
-_Static_assert(_Alignof(t1[]) == 4, "");
-_Static_assert(_Alignof(t2) == 1, "");
-_Static_assert(_Alignof(t2[]) == 1, "");
-#else
-_Static_assert(_Alignof(t1) == 4, "");
-_Static_assert(_Alignof(t1[]) == 4, "");
-_Static_assert(_Alignof(t2) == 4, "");
-_Static_assert(_Alignof(t2[]) == 4, "");
-#endif
-_Static_assert(sizeof(t2) == 8, ""); // it's still packing the rest of the struct
-} // namespace non_pod
-
-namespace non_pod_packed {
-struct t1 {
-protected:
- int a;
-} __attribute__((packed));
-struct t2 {
- t1 v1;
-} __attribute__((packed));
-_Static_assert(_Alignof(t1) == 1, "");
-_Static_assert(_Alignof(t2) == 1, "");
-} // namespace non_pod_packed
-
-namespace non_pod_packed_packed {
-struct B {
- int b;
-};
-struct FromB : B {
-} __attribute__((packed));
-struct C {
- char a[3];
- FromB b;
-} __attribute__((packed));
-//_Static_assert(__builtin_offsetof(C, b) == 3, ""); FIXME
-}
-
-namespace cxx11_pod {
-struct t1 {
- t1() = default;
- t1(const t1&) = delete;
- ~t1() = delete;
- t1(t1&&) = default;
- int a;
- char c;
-};
-struct t2 {
- t1 v1;
-} __attribute__((packed));
-_Static_assert(_Alignof(t2) == 1, "");
-struct t3 : t1 {
- char c;
-};
-#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 15
-_Static_assert(sizeof(t3) == 8, "");
-#else
-_Static_assert(sizeof(t3) == 12, "");
-#endif
-}
Index: clang/lib/AST/Interp/Opcodes.td
===================================================================
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -53,6 +53,7 @@
def ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; }
def ArgCastKind : ArgType { let Name = "CastKind"; }
def ArgCallExpr : ArgType { let Name = "const CallExpr *"; }
+def ArgOffsetOfExpr : ArgType { let Name = "const OffsetOfExpr *"; }
//===----------------------------------------------------------------------===//
// Classes of types instructions operate on.
@@ -198,6 +199,12 @@
let Types = [];
}
+def OffsetOf : Opcode {
+ let Types = [IntegerTypeClass];
+ let Args = [ArgOffsetOfExpr];
+ let HasGroup = 1;
+}
+
//===----------------------------------------------------------------------===//
// Frame management
//===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/InterpBuiltin.cpp
===================================================================
--- clang/lib/AST/Interp/InterpBuiltin.cpp
+++ clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -8,6 +8,7 @@
#include "Boolean.h"
#include "Interp.h"
#include "PrimType.h"
+#include "clang/AST/RecordLayout.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
@@ -586,5 +587,79 @@
return false;
}
+bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
+ const std::vector<int64_t> &ArrayIndices,
+ int64_t &IntResult) {
+ CharUnits Result;
+ unsigned N = E->getNumComponents();
+ assert(N > 0);
+
+ unsigned ArrayIndex = 0;
+ QualType CurrentType = E->getTypeSourceInfo()->getType();
+ for (unsigned I = 0; I != N; ++I) {
+ const OffsetOfNode &Node = E->getComponent(I);
+ switch (Node.getKind()) {
+ case OffsetOfNode::Field: {
+ const FieldDecl *MemberDecl = Node.getField();
+ const RecordType *RT = CurrentType->getAs<RecordType>();
+ if (!RT)
+ return false;
+ RecordDecl *RD = RT->getDecl();
+ if (RD->isInvalidDecl())
+ return false;
+ const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
+ unsigned FieldIndex = MemberDecl->getFieldIndex();
+ assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
+ Result += S.getCtx().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));
+ CurrentType = MemberDecl->getType().getNonReferenceType();
+ break;
+ }
+ case OffsetOfNode::Array: {
+ // When generating bytecode, we put all the index expressions as Sint64 on
+ // the stack.
+ int64_t Index = ArrayIndices[ArrayIndex];
+ const ArrayType *AT = S.getCtx().getAsArrayType(CurrentType);
+ if (!AT)
+ return false;
+ CurrentType = AT->getElementType();
+ CharUnits ElementSize = S.getCtx().getTypeSizeInChars(CurrentType);
+ Result += Index * ElementSize;
+ ++ArrayIndex;
+ break;
+ }
+ case OffsetOfNode::Base: {
+ const CXXBaseSpecifier *BaseSpec = Node.getBase();
+ if (BaseSpec->isVirtual())
+ return false;
+
+ // Find the layout of the class whose base we are looking into.
+ const RecordType *RT = CurrentType->getAs<RecordType>();
+ if (!RT)
+ return false;
+ const RecordDecl *RD = RT->getDecl();
+ if (RD->isInvalidDecl())
+ return false;
+ const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
+
+ // Find the base class itself.
+ CurrentType = BaseSpec->getType();
+ const RecordType *BaseRT = CurrentType->getAs<RecordType>();
+ if (!BaseRT)
+ return false;
+
+ // Add the offset to the base.
+ Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
+ break;
+ }
+ case OffsetOfNode::Identifier:
+ llvm_unreachable("Dependent OffsetOfExpr?");
+ }
+ }
+
+ IntResult = Result.getQuantity();
+
+ return true;
+}
+
} // namespace interp
} // namespace clang
Index: clang/lib/AST/Interp/Interp.h
===================================================================
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -183,6 +183,10 @@
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call);
+bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
+ const std::vector<int64_t> &ArrayIndices,
+ int64_t &Result);
+
/// Perform a bitcast of all fields of P into Buff. This performs the
/// actions of a __builtin_bit_cast expression when the target type
/// is primitive.
@@ -1892,6 +1896,21 @@
return false;
}
+template <PrimType Name, class T = typename PrimConv<Name>::T>
+inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) {
+ std::vector<int64_t> ArrayIndices;
+ for (unsigned I = 0; I != E->getNumExpressions(); ++I)
+ ArrayIndices.emplace_back(S.Stk.pop<int64_t>());
+
+ int64_t Result;
+ if (!InterpretOffsetOf(S, OpPC, E, ArrayIndices, Result))
+ return false;
+
+ S.Stk.push<T>(T::from(Result));
+
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// Read opcode arguments
//===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -105,6 +105,7 @@
bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
bool VisitSourceLocExpr(const SourceLocExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E);
+ bool VisitOffsetOfExpr(const OffsetOfExpr *E);
protected:
bool visitExpr(const Expr *E) override;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -16,6 +16,7 @@
#include "PrimType.h"
#include "Program.h"
#include "State.h"
+#include "clang/AST/RecordLayout.h"
using namespace clang;
using namespace clang::interp;
@@ -1513,6 +1514,41 @@
return false;
}
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) {
+ unsigned N = E->getNumComponents();
+ if (N == 0)
+ return false;
+
+ for (unsigned I = 0; I != N; ++I) {
+ const OffsetOfNode &Node = E->getComponent(I);
+ if (Node.getKind() == OffsetOfNode::Array) {
+ const Expr *ArrayIndexExpr = E->getIndexExpr(Node.getArrayExprIndex());
+ PrimType IndexT = classifyPrim(ArrayIndexExpr->getType());
+
+ if (DiscardResult) {
+ if (!this->discard(ArrayIndexExpr))
+ return false;
+ continue;
+ }
+
+ if (!this->visit(ArrayIndexExpr))
+ return false;
+ // Cast to Sint64.
+ if (IndexT != PT_Sint64) {
+ if (!this->emitCast(IndexT, PT_Sint64, E))
+ return false;
+ }
+ }
+ }
+
+ if (DiscardResult)
+ return true;
+
+ PrimType T = classifyPrim(E->getType());
+ return this->emitOffsetOf(T, E, E);
+}
+
template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
if (E->containsErrors())
return false;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits