Explicitly permit undefined behavior in constant initializers for global
variables in C, in the cases where we can constant-fold it to a value
regardless (such as floating-point division by zero and signed integer
overflow). Strictly enforcing this rule breaks too much code.

llvm-svn: 254992
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 33ea76e..9996546 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2891,7 +2891,10 @@
     return cast<CXXDefaultInitExpr>(this)->getExpr()
       ->isConstantInitializer(Ctx, false, Culprit);
   }
-  if (isEvaluatable(Ctx))
+  // Allow certain forms of UB in constant initializers: signed integer
+  // overflow and floating-point division by zero. We'll give a warning on
+  // these, but they're common enough that we have to accept them.
+  if (isEvaluatable(Ctx, SE_AllowUndefinedBehavior))
     return true;
   if (Culprit)
     *Culprit = this;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index ffaf742..3c8868c 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -715,6 +715,32 @@
       return keepEvaluatingAfterSideEffect();
     }
 
+    /// Should we continue evaluation after encountering undefined behavior?
+    bool keepEvaluatingAfterUndefinedBehavior() {
+      switch (EvalMode) {
+      case EM_EvaluateForOverflow:
+      case EM_IgnoreSideEffects:
+      case EM_ConstantFold:
+      case EM_DesignatorFold:
+        return true;
+
+      case EM_PotentialConstantExpression:
+      case EM_PotentialConstantExpressionUnevaluated:
+      case EM_ConstantExpression:
+      case EM_ConstantExpressionUnevaluated:
+        return false;
+      }
+      llvm_unreachable("Missed EvalMode case");
+    }
+
+    /// Note that we hit something that was technically undefined behavior, but
+    /// that we can evaluate past it (such as signed overflow or floating-point
+    /// division by zero.)
+    bool noteUndefinedBehavior() {
+      EvalStatus.HasUndefinedBehavior = true;
+      return keepEvaluatingAfterUndefinedBehavior();
+    }
+
     /// Should we continue evaluation as much as possible after encountering a
     /// construct which can't be reduced to a value?
     bool keepEvaluatingAfterFailure() {
@@ -1549,7 +1575,7 @@
                            const T &SrcValue, QualType DestType) {
   Info.CCEDiag(E, diag::note_constexpr_overflow)
     << SrcValue << DestType;
-  return Info.noteSideEffect();
+  return Info.noteUndefinedBehavior();
 }
 
 static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E,
@@ -1818,8 +1844,7 @@
 
   if (LHS.isInfinity() || LHS.isNaN()) {
     Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN();
-    // Undefined behavior is a side-effect.
-    return Info.noteSideEffect();
+    return Info.noteUndefinedBehavior();
   }
   return true;
 }
@@ -8835,6 +8860,12 @@
          HandleConversionToBool(Scratch.Val, Result);
 }
 
+static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result,
+                                      Expr::SideEffectsKind SEK) {
+  return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) ||
+         (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior);
+}
+
 bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx,
                          SideEffectsKind AllowSideEffects) const {
   if (!getType()->isIntegralOrEnumerationType())
@@ -8842,7 +8873,7 @@
 
   EvalResult ExprResult;
   if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() ||
-      (!AllowSideEffects && ExprResult.HasSideEffects))
+      hasUnacceptableSideEffect(ExprResult, AllowSideEffects))
     return false;
 
   Result = ExprResult.Val.getInt();
@@ -8905,9 +8936,10 @@
 
 /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
 /// constant folded, but discard the result.
-bool Expr::isEvaluatable(const ASTContext &Ctx) const {
+bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const {
   EvalResult Result;
-  return EvaluateAsRValue(Result, Ctx) && !Result.HasSideEffects;
+  return EvaluateAsRValue(Result, Ctx) &&
+         !hasUnacceptableSideEffect(Result, SEK);
 }
 
 APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx,