Track in the AST whether the operand to a UnaryOperator can overflow and then use that logic when evaluating constant expressions and emitting codegen.
llvm-svn: 322074
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6cbb498..61bd1e5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3244,17 +3244,12 @@
}
CompleteObject Obj = findCompleteObject(Info, E, AK_Assign, LVal, LValType);
- return Obj && modifySubobject(Info, E, Obj, LVal.Designator, Val);
-}
-
-static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) {
- return T->isSignedIntegerType() &&
- Ctx.getIntWidth(T) >= Ctx.getIntWidth(Ctx.IntTy);
-}
-
-namespace {
-struct CompoundAssignSubobjectHandler {
- EvalInfo &Info;
+ return Obj && modifySubobject(Info, E, Obj, LVal.Designator, Val);
+}
+
+namespace {
+struct CompoundAssignSubobjectHandler {
+ EvalInfo &Info;
const Expr *E;
QualType PromotedLHSType;
BinaryOperatorKind Opcode;
@@ -3370,13 +3365,13 @@
return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler);
}
-namespace {
-struct IncDecSubobjectHandler {
- EvalInfo &Info;
- const Expr *E;
- AccessKinds AccessKind;
- APValue *Old;
-
+namespace {
+struct IncDecSubobjectHandler {
+ EvalInfo &Info;
+ const UnaryOperator *E;
+ AccessKinds AccessKind;
+ APValue *Old;
+
typedef bool result_type;
bool checkConst(QualType QT) {
@@ -3442,22 +3437,20 @@
}
bool WasNegative = Value.isNegative();
- if (AccessKind == AK_Increment) {
- ++Value;
-
- if (!WasNegative && Value.isNegative() &&
- isOverflowingIntegerType(Info.Ctx, SubobjType)) {
- APSInt ActualValue(Value, /*IsUnsigned*/true);
- return HandleOverflow(Info, E, ActualValue, SubobjType);
- }
- } else {
- --Value;
-
- if (WasNegative && !Value.isNegative() &&
- isOverflowingIntegerType(Info.Ctx, SubobjType)) {
- unsigned BitWidth = Value.getBitWidth();
- APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false);
- ActualValue.setBit(BitWidth);
+ if (AccessKind == AK_Increment) {
+ ++Value;
+
+ if (!WasNegative && Value.isNegative() && E->canOverflow()) {
+ APSInt ActualValue(Value, /*IsUnsigned*/true);
+ return HandleOverflow(Info, E, ActualValue, SubobjType);
+ }
+ } else {
+ --Value;
+
+ if (WasNegative && !Value.isNegative() && E->canOverflow()) {
+ unsigned BitWidth = Value.getBitWidth();
+ APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false);
+ ActualValue.setBit(BitWidth);
return HandleOverflow(Info, E, ActualValue, SubobjType);
}
}
@@ -3512,13 +3505,13 @@
Info.FFDiag(E);
return false;
}
-
- AccessKinds AK = IsIncrement ? AK_Increment : AK_Decrement;
- CompleteObject Obj = findCompleteObject(Info, E, AK, LVal, LValType);
- IncDecSubobjectHandler Handler = { Info, E, AK, Old };
- return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler);
-}
-
+
+ AccessKinds AK = IsIncrement ? AK_Increment : AK_Decrement;
+ CompleteObject Obj = findCompleteObject(Info, E, AK, LVal, LValType);
+ IncDecSubobjectHandler Handler = {Info, cast<UnaryOperator>(E), AK, Old};
+ return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler);
+}
+
/// Build an lvalue for the object argument of a member function call.
static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object,
LValue &This) {
@@ -8875,13 +8868,13 @@
return Visit(E->getSubExpr());
case UO_Minus: {
if (!Visit(E->getSubExpr()))
- return false;
- if (!Result.isInt()) return Error(E);
- const APSInt &Value = Result.getInt();
- if (Value.isSigned() && Value.isMinSignedValue() &&
- !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
- E->getType()))
- return false;
+ return false;
+ if (!Result.isInt()) return Error(E);
+ const APSInt &Value = Result.getInt();
+ if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow() &&
+ !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
+ E->getType()))
+ return false;
return Success(-Value, E);
}
case UO_Not: {