[clang] ee2e414 - [clang][Interp] Handle sizeof()
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 29 03:51:26 PDT 2022
Author: Timm Bäder
Date: 2022-09-29T12:50:55+02:00
New Revision: ee2e414d66a4b3b4e1a3bade11168a108f349d8a
URL: https://github.com/llvm/llvm-project/commit/ee2e414d66a4b3b4e1a3bade11168a108f349d8a
DIFF: https://github.com/llvm/llvm-project/commit/ee2e414d66a4b3b4e1a3bade11168a108f349d8a.diff
LOG: [clang][Interp] Handle sizeof()
Implement visiting UnaryExprOrTypeTraitExprs to handle sizeof()
expressions.
Differential Revision: https://reviews.llvm.org/D133934
Added:
Modified:
clang/lib/AST/Interp/Boolean.h
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/lib/AST/Interp/Opcodes.td
clang/test/AST/Interp/literals.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index e739ce28e92c5..f1a0b9007df80 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -47,6 +47,10 @@ class Boolean {
Boolean operator~() const { return Boolean(true); }
explicit operator unsigned() const { return V; }
+ explicit operator int8_t() const { return V; }
+ explicit operator uint8_t() const { return V; }
+ explicit operator int16_t() const { return V; }
+ explicit operator uint16_t() const { return V; }
explicit operator int64_t() const { return V; }
explicit operator uint64_t() const { return V; }
explicit operator int() const { return V; }
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index f86a7b1aa1898..5974678f0cfc9 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -281,7 +281,29 @@ bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
+bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr(
+ const UnaryExprOrTypeTraitExpr *E) {
+
+ if (E->getKind() == UETT_SizeOf) {
+ QualType ArgType = E->getTypeOfArgument();
+
+ CharUnits Size;
+ if (ArgType->isVoidType() || ArgType->isFunctionType())
+ Size = CharUnits::One();
+ else {
+ if (ArgType->isDependentType() || !ArgType->isConstantSizeType())
+ return false;
+
+ Size = Ctx.getASTContext().getTypeSizeInChars(ArgType);
+ }
+
+ return this->emitConst(E, Size.getQuantity());
+ }
+
+ return false;
+}
+
+template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
return this->Visit(E);
}
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 6a74bc371855e..d73a8dfb18c28 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -80,6 +80,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
bool VisitInitListExpr(const InitListExpr *E);
bool VisitConstantExpr(const ConstantExpr *E);
+ bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
protected:
bool visitExpr(const Expr *E) override;
diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index 49cc0e0253de6..c743807714b1f 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -427,11 +427,11 @@ def Neg: Opcode {
// TODO: Expand this to handle casts between more types.
def FromCastTypeClass : TypeClass {
- let Types = [Uint32, Sint32, Bool];
+ let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool];
}
def ToCastTypeClass : TypeClass {
- let Types = [Uint32, Sint32, Bool];
+ let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool];
}
def Cast: Opcode {
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 5c1df00a25e77..5de727f005c86 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++11 -verify %s
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify %s
// RUN: %clang_cc1 -std=c++11 -verify=ref %s
+// RUN: %clang_cc1 -std=c++20 -verify=ref %s
static_assert(true, "");
static_assert(false, ""); // expected-error{{failed}} ref-error{{failed}}
@@ -72,10 +74,74 @@ static_assert(*p == 10, "");
constexpr const int* getIntPointer() {
return &m;
}
-//static_assert(getIntPointer() == &m, ""); TODO
-//static_assert(*getIntPointer() == 10, ""); TODO
+static_assert(getIntPointer() == &m, "");
+static_assert(*getIntPointer() == 10, "");
constexpr int gimme(int k) {
return k;
}
-// static_assert(gimme(5) == 5, ""); TODO
+static_assert(gimme(5) == 5, "");
+
+namespace SizeOf {
+ constexpr int soint = sizeof(int);
+ constexpr int souint = sizeof(unsigned int);
+ static_assert(soint == souint, "");
+
+ static_assert(sizeof(&soint) == sizeof(void*), "");
+ static_assert(sizeof(&soint) == sizeof(nullptr), "");
+
+ static_assert(sizeof(long) == sizeof(unsigned long), "");
+ static_assert(sizeof(char) == sizeof(unsigned char), "");
+
+ constexpr int N = 4;
+ constexpr int arr[N] = {1,2,3,4};
+ static_assert(sizeof(arr) == N * sizeof(int), "");
+ static_assert(sizeof(arr) == N * sizeof(arr[0]), "");
+
+ constexpr bool arrB[N] = {true, true, true, true};
+ static_assert(sizeof(arrB) == N * sizeof(bool), "");
+
+ static_assert(sizeof(bool) == 1, "");
+ static_assert(sizeof(char) == 1, "");
+
+ constexpr int F = sizeof(void); // expected-error{{incomplete type 'void'}} \
+ // ref-error{{incomplete type 'void'}}
+
+ constexpr int F2 = sizeof(gimme); // expected-error{{to a function type}} \
+ // ref-error{{to a function type}}
+
+
+
+ /// FIXME: The following code should be accepted.
+ struct S {
+ void func();
+ };
+ constexpr void (S::*Func)() = &S::func; // expected-error {{must be initialized by a constant expression}} \
+ // expected-error {{interpreter failed to evaluate an expression}}
+ static_assert(sizeof(Func) == sizeof(&S::func), "");
+
+
+ void func() {
+ int n = 12;
+ constexpr int oofda = sizeof(int[n++]); // expected-error {{must be initialized by a constant expression}} \
+ // ref-error {{must be initialized by a constant expression}}
+ }
+
+
+#if __cplusplus >= 202002L
+ /// FIXME: The following code should be accepted.
+ consteval int foo(int n) { // ref-error {{consteval function never produces a constant expression}}
+ return sizeof(int[n]); // ref-note 3{{not valid in a constant expression}} \
+ // expected-note {{not valid in a constant expression}}
+ }
+ constinit int var = foo(5); // ref-error {{not a constant expression}} \
+ // ref-note 2{{in call to}} \
+ // ref-error {{does not have a constant initializer}} \
+ // ref-note {{required by 'constinit' specifier}} \
+ // expected-error {{is not a constant expression}} \
+ // expected-note {{in call to}} \
+ // expected-error {{does not have a constant initializer}} \
+ // expected-note {{required by 'constinit' specifier}} \
+
+#endif
+};
More information about the cfe-commits
mailing list