This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG8065b1cc133c: [clang][Interp] Basic support for bit fields (authored by tbaeder).
Changed prior to commit: https://reviews.llvm.org/D155270?vs=540927&id=548887#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D155270/new/ https://reviews.llvm.org/D155270 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeStmtGen.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Record.h clang/test/AST/Interp/bitfields.cpp
Index: clang/test/AST/Interp/bitfields.cpp =================================================================== --- /dev/null +++ clang/test/AST/Interp/bitfields.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -Wno-bitfield-constant-conversion -verify %s +// RUN: %clang_cc1 -verify=ref -Wno-bitfield-constant-conversion %s + +// expected-no-diagnostics +// ref-no-diagnostics + +namespace Basic { + struct A { + unsigned int a : 2; + constexpr A() : a(0) {} + constexpr A(int a) : a(a) {} + }; + + constexpr A a{1}; + static_assert(a.a == 1, ""); + + constexpr A a2{10}; + static_assert(a2.a == 2, ""); + + + constexpr int storeA() { + A a; + a.a = 10; + + return a.a; + } + static_assert(storeA() == 2, ""); + + constexpr int storeA2() { + A a; + return a.a = 10; + } + static_assert(storeA2() == 2, ""); + + // TODO: +=, -=, etc. operators. +} + +namespace Overflow { + struct A {int c:3;}; + + constexpr int f() { + A a1{3}; + return a1.c++; + } + + static_assert(f() == 3, ""); +} Index: clang/lib/AST/Interp/Record.h =================================================================== --- clang/lib/AST/Interp/Record.h +++ clang/lib/AST/Interp/Record.h @@ -29,6 +29,7 @@ const FieldDecl *Decl; unsigned Offset; Descriptor *Desc; + bool isBitField() const { return Decl->isBitField(); } }; /// Describes a base class. Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1007,6 +1007,7 @@ template <PrimType Name, class T = typename PrimConv<Name>::T> bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) { + assert(F->isBitField()); if (S.checkingPotentialConstantExpression()) return false; const Pointer &This = S.Current->getThis(); @@ -1048,8 +1049,9 @@ template <PrimType Name, class T = typename PrimConv<Name>::T> bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) { + assert(F->isBitField()); const T &Value = S.Stk.pop<T>(); - const Pointer &Field = S.Stk.pop<Pointer>().atField(F->Offset); + const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset); Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx())); Field.activate(); Field.initialize(); @@ -1247,11 +1249,10 @@ return false; if (!Ptr.isRoot()) Ptr.initialize(); - if (auto *FD = Ptr.getField()) { + if (const auto *FD = Ptr.getField()) Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx())); - } else { + else Ptr.deref<T>() = Value; - } return true; } @@ -1263,11 +1264,10 @@ return false; if (!Ptr.isRoot()) Ptr.initialize(); - if (auto *FD = Ptr.getField()) { + if (const auto *FD = Ptr.getField()) Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx())); - } else { + else Ptr.deref<T>() = Value; - } return true; } Index: clang/lib/AST/Interp/ByteCodeStmtGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -169,8 +169,13 @@ if (!this->visit(InitExpr)) return false; - if (!this->emitInitThisField(*T, F->Offset, InitExpr)) - return false; + if (F->isBitField()) { + if (!this->emitInitThisBitField(*T, F, InitExpr)) + return false; + } else { + if (!this->emitInitThisField(*T, F->Offset, InitExpr)) + return false; + } } else { // Non-primitive case. Get a pointer to the field-to-initialize // on the stack and call visitInitialzer() for it. Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -305,8 +305,10 @@ return Discard(this->emitDiv(*T, BO)); case BO_Assign: if (DiscardResult) - return this->emitStorePop(*T, BO); - return this->emitStore(*T, BO); + return LHS->refersToBitField() ? this->emitStoreBitFieldPop(*T, BO) + : this->emitStorePop(*T, BO); + return LHS->refersToBitField() ? this->emitStoreBitField(*T, BO) + : this->emitStore(*T, BO); case BO_And: return Discard(this->emitBitAnd(*T, BO)); case BO_Or: @@ -1590,8 +1592,13 @@ if (!this->visit(Init)) return false; - if (!this->emitInitField(*T, FieldToInit->Offset, Initializer)) - return false; + if (FieldToInit->isBitField()) { + if (!this->emitInitBitField(*T, FieldToInit, Initializer)) + return false; + } else { + if (!this->emitInitField(*T, FieldToInit->Offset, Initializer)) + return false; + } if (!this->emitPopPtr(Initializer)) return false;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits