diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 52e3efff2359d..47cd32c2ab867 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3211,15 +3211,20 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { return false; if (!this->emitAddf(getRoundingMode(E), E)) return false; - return this->emitStoreFloat(E); + if (!this->emitStoreFloat(E)) + return false; + } else { + assert(isIntegralType(*T)); + if (!this->emitLoad(*T, E)) + return false; + if (!this->emitConst(1, E)) + return false; + if (!this->emitAdd(*T, E)) + return false; + if (!this->emitStore(*T, E)) + return false; } - if (!this->emitLoad(*T, E)) - return false; - if (!this->emitConst(1, E)) - return false; - if (!this->emitAdd(*T, E)) - return false; - return this->emitStore(*T, E); + return E->isGLValue() || this->emitLoadPop(*T, E); } case UO_PreDec: { // --x if (!this->visit(SubExpr)) @@ -3250,15 +3255,20 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { return false; if (!this->emitSubf(getRoundingMode(E), E)) return false; - return this->emitStoreFloat(E); + if (!this->emitStoreFloat(E)) + return false; + } else { + assert(isIntegralType(*T)); + if (!this->emitLoad(*T, E)) + return false; + if (!this->emitConst(1, E)) + return false; + if (!this->emitSub(*T, E)) + return false; + if (!this->emitStore(*T, E)) + return false; } - if (!this->emitLoad(*T, E)) - return false; - if (!this->emitConst(1, E)) - return false; - if (!this->emitSub(*T, E)) - return false; - return this->emitStore(*T, E); + return E->isGLValue() || this->emitLoadPop(*T, E); } case UO_LNot: // !x if (DiscardResult) diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index e0b18120fd211..38df38d1ccfae 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -233,3 +233,15 @@ _Static_assert(funcp == (void*)0, ""); // all-error {{failed due to requirement // pedantic-warning {{expression is not an integer constant expression}} _Static_assert(funcp == (void*)123, ""); // pedantic-warning {{equality comparison between function pointer and void pointer}} \ // pedantic-warning {{expression is not an integer constant expression}} + +void unaryops(void) { + (void)(++(struct x {unsigned x;}){3}.x); + (void)(--(struct y {unsigned x;}){3}.x); + (void)(++(struct z {float x;}){3}.x); + (void)(--(struct w {float x;}){3}.x); + + (void)((struct xx {unsigned x;}){3}.x++); + (void)((struct yy {unsigned x;}){3}.x--); + (void)((struct zz {float x;}){3}.x++); + (void)((struct ww {float x;}){3}.x--); +}