tbaeder updated this revision to Diff 540927.
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,36 @@
+// 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.
+}
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
@@ -965,6 +965,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();
@@ -1006,8 +1007,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();
@@ -1205,11 +1207,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;
}
@@ -1221,11 +1222,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
@@ -113,8 +113,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
@@ -282,8 +282,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:
@@ -1474,8 +1476,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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits