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: {