tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, shafik, tahonermann.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Handle sizeof expressions.
I was a bit unsure here about alignment, but the rest is pretty
self-explanatory I think.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D133934
Files:
clang/lib/AST/Interp/Boolean.h
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/lib/AST/Interp/Context.cpp
clang/lib/AST/Interp/Context.h
clang/lib/AST/Interp/Opcodes.td
clang/test/AST/Interp/literals.cpp
Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -72,10 +72,30 @@
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), "");
+};
Index: clang/lib/AST/Interp/Opcodes.td
===================================================================
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -427,11 +427,11 @@
// 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 {
Index: clang/lib/AST/Interp/Context.h
===================================================================
--- clang/lib/AST/Interp/Context.h
+++ clang/lib/AST/Interp/Context.h
@@ -62,6 +62,9 @@
/// Classifies an expression.
llvm::Optional<PrimType> classify(QualType T) const;
+ /// Calculate size of \T.
+ llvm::Optional<size_t> sizeofType(QualType T) const;
+
private:
/// Runs a function.
bool Run(State &Parent, Function *Func, APValue &Result);
Index: clang/lib/AST/Interp/Context.cpp
===================================================================
--- clang/lib/AST/Interp/Context.cpp
+++ clang/lib/AST/Interp/Context.cpp
@@ -130,6 +130,25 @@
return {};
}
+llvm::Optional<size_t> Context::sizeofType(QualType T) const {
+ if (llvm::Optional<PrimType> ArgT = classify(T))
+ return primSize(*ArgT);
+
+ if (const auto *AT = T->getAsArrayTypeUnsafe()) {
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(T)) {
+ size_t NumElems = CAT->getSize().getZExtValue();
+ QualType ElemType = CAT->getElementType();
+
+ if (llvm::Optional<size_t> ElemSize = sizeofType(ElemType))
+ return NumElems * (*ElemSize);
+ }
+ }
+
+ // TODO: Handle record types
+
+ return {};
+}
+
unsigned Context::getCharBit() const {
return Ctx.getTargetInfo().getCharWidth();
}
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -80,6 +80,7 @@
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;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -281,7 +281,20 @@
}
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();
+
+ if (Optional<size_t> ArgSize = Ctx.sizeofType(ArgType))
+ return this->emitConst(E, *ArgSize);
+ }
+
+ return false;
+}
+
+template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
return this->Visit(E);
}
Index: clang/lib/AST/Interp/Boolean.h
===================================================================
--- clang/lib/AST/Interp/Boolean.h
+++ clang/lib/AST/Interp/Boolean.h
@@ -48,6 +48,10 @@
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; }
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits