diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -241,6 +241,8 @@ return Discard(this->emitShl(*LT, *RT, BO)); case BO_Shr: return Discard(this->emitShr(*LT, *RT, BO)); + case BO_Xor: + return Discard(this->emitBitXor(*T, BO)); case BO_LAnd: case BO_LOr: default: diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/Interp/Integral.h @@ -227,6 +227,11 @@ return false; } + static bool bitXor(Integral A, Integral B, unsigned OpBits, Integral *R) { + *R = Integral(A.V ^ B.V); + return false; + } + static bool neg(Integral A, Integral *R) { *R = -A; return false; diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -211,6 +211,23 @@ return false; } +/// 1) Pops the RHS from the stack. +/// 2) Pops the LHS from the stack. +/// 3) Pushes 'LHS ^ RHS' on the stack +template ::T> +bool BitXor(InterpState &S, CodePtr OpPC) { + const T &RHS = S.Stk.pop(); + const T &LHS = S.Stk.pop(); + + unsigned Bits = RHS.bitWidth(); + T Result; + if (!T::bitXor(LHS, RHS, Bits, &Result)) { + S.Stk.push(Result); + return true; + } + return false; +} + /// 1) Pops the RHS from the stack. /// 2) Pops the LHS from the stack. /// 3) Pushes 'LHS % RHS' on the stack (the remainder of dividing LHS by RHS). diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -419,6 +419,7 @@ let Types = [NumberTypeClass]; let HasGroup = 1; } +def BitXor : IntegerOpcode; //===----------------------------------------------------------------------===// // Unary operators. diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -279,6 +279,23 @@ static_assert((12 | true) == 13, ""); }; +namespace bitXor { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wxor-used-as-pow" + static_assert((10 ^ 1) == 11, ""); + static_assert((10 ^ 10) == 0, ""); + + enum { + ONE = 1, + }; + + static_assert((1337 ^ -1) == -1338, ""); + static_assert((0 | gimme(12)) == 12, ""); + static_assert((12 ^ true) == 13, ""); + static_assert((12 ^ ONE) == 13, ""); +#pragma clang diagnostic pop +}; + #if __cplusplus >= 201402L constexpr bool IgnoredUnary() { bool bo = true;