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; } 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 -bool ByteCodeExprGen::discard(const Expr *E) { +bool ByteCodeExprGen::VisitUnaryExprOrTypeTraitExpr( + const UnaryExprOrTypeTraitExpr *E) { + + if (E->getKind() == UETT_SizeOf) { + QualType ArgType = E->getTypeOfArgument(); + + if (Optional ArgSize = Ctx.sizeofType(ArgType)) + return this->emitConst(E, *ArgSize); + } + + return false; +} + +template bool ByteCodeExprGen::discard(const Expr *E) { OptionScope Scope(this, /*NewDiscardResult=*/true); return this->Visit(E); } 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 classify(QualType T) const; + /// Calculate size of \T. + llvm::Optional 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 Context::sizeofType(QualType T) const { + if (llvm::Optional ArgT = classify(T)) + return primSize(*ArgT); + + if (const auto *AT = T->getAsArrayTypeUnsafe()) { + if (const auto *CAT = dyn_cast(T)) { + size_t NumElems = CAT->getSize().getZExtValue(); + QualType ElemType = CAT->getElementType(); + + if (llvm::Optional ElemSize = sizeofType(ElemType)) + return NumElems * (*ElemSize); + } + } + + // TODO: Handle record types + + return {}; +} + unsigned Context::getCharBit() const { return Ctx.getTargetInfo().getCharWidth(); } 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/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), ""); +};