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 cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits