Propagate SanitizerKind into CodeGenFunction::EmitCheck() call.

Make sure CodeGenFunction::EmitCheck() knows which sanitizer
it emits check for. Make CheckRecoverableKind enum an
implementation detail and move it away from header.

Currently CheckRecoverableKind is determined by the type of
sanitizer ("unreachable" and "return" are unrecoverable,
"vptr" is always-recoverable, all the rest are recoverable).
This will change in future if we allow to specify which sanitizers
are recoverable, and which are not by -fsanitize-recover= flag.

No functionality change.

llvm-svn: 221635
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 533d158..3086de6 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -476,8 +476,8 @@
     if (SanOpts.has(SanitizerKind::Unreachable)) {
       SanitizerScope SanScope(this);
       EmitCheck(Builder.getFalse(), "builtin_unreachable",
-                EmitCheckSourceLocation(E->getExprLoc()),
-                None, CRK_Unrecoverable);
+                EmitCheckSourceLocation(E->getExprLoc()), None,
+                SanitizerKind::Unreachable);
     } else
       Builder.CreateUnreachable();
 
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 6f2a27f..ca5db85 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2300,7 +2300,8 @@
             EmitCheckSourceLocation(EndLoc),
             EmitCheckSourceLocation(RetNNAttr->getLocation()),
         };
-        EmitCheck(Cond, "nonnull_return", StaticData, None, CRK_Recoverable);
+        EmitCheck(Cond, "nonnull_return", StaticData, None,
+                  SanitizerKind::ReturnsNonnullAttribute);
       }
     }
     Ret = Builder.CreateRet(RV);
@@ -2636,7 +2637,7 @@
       llvm::ConstantInt::get(CGF.Int32Ty, ArgNo + 1),
   };
   CGF.EmitCheck(Cond, "nonnull_arg", StaticData, None,
-                CodeGenFunction::CRK_Recoverable);
+                SanitizerKind::NonnullAttribute);
 }
 
 void CodeGenFunction::EmitCallArgs(CallArgList &Args,
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index e1b9b7b..389cd00 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -475,6 +475,7 @@
   if (Address->getType()->getPointerAddressSpace())
     return;
 
+  SmallVector<SanitizerKind, 3> Kinds;
   SanitizerScope SanScope(this);
 
   llvm::Value *Cond = nullptr;
@@ -496,6 +497,8 @@
       Builder.CreateCondBr(Cond, Rest, Done);
       EmitBlock(Rest);
       Cond = nullptr;
+    } else {
+      Kinds.push_back(SanitizerKind::Null);
     }
   }
 
@@ -514,6 +517,7 @@
         Builder.CreateICmpUGE(Builder.CreateCall2(F, CastAddr, Min),
                               llvm::ConstantInt::get(IntPtrTy, Size));
     Cond = Cond ? Builder.CreateAnd(Cond, LargeEnough) : LargeEnough;
+    Kinds.push_back(SanitizerKind::ObjectSize);
   }
 
   uint64_t AlignVal = 0;
@@ -531,6 +535,7 @@
       llvm::Value *Aligned =
         Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
       Cond = Cond ? Builder.CreateAnd(Cond, Aligned) : Aligned;
+      Kinds.push_back(SanitizerKind::Alignment);
     }
   }
 
@@ -541,7 +546,7 @@
       llvm::ConstantInt::get(SizeTy, AlignVal),
       llvm::ConstantInt::get(Int8Ty, TCK)
     };
-    EmitCheck(Cond, "type_mismatch", StaticData, Address, CRK_Recoverable);
+    EmitCheck(Cond, "type_mismatch", StaticData, Address, Kinds);
   }
 
   // If possible, check that the vptr indicates that there is a subobject of
@@ -606,9 +611,8 @@
         llvm::ConstantInt::get(Int8Ty, TCK)
       };
       llvm::Value *DynamicData[] = { Address, Hash };
-      EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash),
-                "dynamic_type_cache_miss", StaticData, DynamicData,
-                CRK_AlwaysRecoverable);
+      EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash), "dynamic_type_cache_miss",
+                StaticData, DynamicData, SanitizerKind::Vptr);
     }
   }
 
@@ -696,7 +700,8 @@
   };
   llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
                                 : Builder.CreateICmpULE(IndexVal, BoundVal);
-  EmitCheck(Check, "out_of_bounds", StaticData, Index, CRK_Recoverable);
+  EmitCheck(Check, "out_of_bounds", StaticData, Index,
+            SanitizerKind::ArrayBounds);
 }
 
 
@@ -1151,8 +1156,11 @@
       CGM.DecorateInstruction(Load, TBAAPath, false/*ConvertTypeToTag*/);
   }
 
-  if ((SanOpts.has(SanitizerKind::Bool) && hasBooleanRepresentation(Ty)) ||
-      (SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>())) {
+  bool NeedsBoolCheck =
+      SanOpts.has(SanitizerKind::Bool) && hasBooleanRepresentation(Ty);
+  bool NeedsEnumCheck =
+      SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>();
+  if (NeedsBoolCheck || NeedsEnumCheck) {
     SanitizerScope SanScope(this);
     llvm::APInt Min, End;
     if (getRangeForType(*this, Ty, Min, End, true)) {
@@ -1173,7 +1181,7 @@
         EmitCheckTypeDescriptor(Ty)
       };
       EmitCheck(Check, "load_invalid_value", StaticArgs, EmitCheckValue(Load),
-                CRK_Recoverable);
+                NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool);
     }
   } else if (CGM.getCodeGenOpts().OptimizationLevel > 0)
     if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty))
@@ -2169,14 +2177,45 @@
   return llvm::ConstantStruct::getAnon(Data);
 }
 
+namespace {
+/// \brief Specify under what conditions this check can be recovered
+enum class CheckRecoverableKind {
+  /// Always terminate program execution if this check fails
+  Unrecoverable,
+  /// Check supports recovering, allows user to specify which
+  Recoverable,
+  /// Runtime conditionally aborts, always need to support recovery.
+  AlwaysRecoverable
+};
+}
+
+static CheckRecoverableKind getRecoverableKind(SanitizerKind Kind) {
+  switch (Kind) {
+  case SanitizerKind::Vptr:
+    return CheckRecoverableKind::AlwaysRecoverable;
+  case SanitizerKind::Return:
+  case SanitizerKind::Unreachable:
+    return CheckRecoverableKind::Unrecoverable;
+  default:
+    return CheckRecoverableKind::Recoverable;
+  }
+}
+
 void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
                                 ArrayRef<llvm::Constant *> StaticArgs,
                                 ArrayRef<llvm::Value *> DynamicArgs,
-                                CheckRecoverableKind RecoverKind) {
+                                ArrayRef<SanitizerKind> Kinds) {
   assert(IsSanitizerScope);
+  assert(Kinds.size() > 0);
+  CheckRecoverableKind RecoverKind = getRecoverableKind(Kinds[0]);
+  for (int i = 1, n = Kinds.size(); i < n; ++i)
+    assert(RecoverKind == getRecoverableKind(Kinds[i]) &&
+           "All recoverable kinds in a single check must be same!");
+  for (auto Kind : Kinds)
+    assert(SanOpts.has(Kind));
 
   if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) {
-    assert (RecoverKind != CRK_AlwaysRecoverable &&
+    assert (RecoverKind != CheckRecoverableKind::AlwaysRecoverable &&
             "Runtime call required for AlwaysRecoverable kind!");
     return EmitTrapCheck(Checked);
   }
@@ -2217,8 +2256,8 @@
     ArgTypes.push_back(IntPtrTy);
   }
 
-  bool Recover = RecoverKind == CRK_AlwaysRecoverable ||
-                 (RecoverKind == CRK_Recoverable &&
+  bool Recover = RecoverKind == CheckRecoverableKind::AlwaysRecoverable ||
+                 (RecoverKind == CheckRecoverableKind::Recoverable &&
                   CGM.getCodeGenOpts().SanitizeRecover);
 
   llvm::FunctionType *FnType =
@@ -2231,7 +2270,7 @@
   B.addAttribute(llvm::Attribute::UWTable);
 
   // Checks that have two variants use a suffix to differentiate them
-  bool NeedsAbortSuffix = RecoverKind != CRK_Unrecoverable &&
+  bool NeedsAbortSuffix = RecoverKind != CheckRecoverableKind::Unrecoverable &&
                           !CGM.getCodeGenOpts().SanitizeRecover;
   std::string FunctionName = ("__ubsan_handle_" + CheckName +
                               (NeedsAbortSuffix? "_abort" : "")).str();
@@ -3260,11 +3299,8 @@
         EmitCheckSourceLocation(E->getLocStart()),
         EmitCheckTypeDescriptor(CalleeType)
       };
-      EmitCheck(CalleeRTTIMatch,
-                "function_type_mismatch",
-                StaticData,
-                Callee,
-                CRK_Recoverable);
+      EmitCheck(CalleeRTTIMatch, "function_type_mismatch", StaticData, Callee,
+                SanitizerKind::Function);
 
       Builder.CreateBr(Cont);
       EmitBlock(Cont);
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 36a001f..1009422 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -85,7 +85,8 @@
     return CGF.EmitCheckedLValue(E, TCK);
   }
 
-  void EmitBinOpCheck(Value *Check, const BinOpInfo &Info);
+  void EmitBinOpCheck(Value *Check, const BinOpInfo &Info,
+                      ArrayRef<SanitizerKind> Kinds);
 
   Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
     return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal();
@@ -726,7 +727,7 @@
     CGF.EmitCheckTypeDescriptor(DstType)
   };
   CGF.EmitCheck(Check, "float_cast_overflow", StaticArgs, OrigSrc,
-                CodeGenFunction::CRK_Recoverable);
+                SanitizerKind::FloatCastOverflow);
 }
 
 /// EmitScalarConversion - Emit a conversion from the specified type to the
@@ -885,7 +886,8 @@
 /// \brief Emit a sanitization check for the given "binary" operation (which
 /// might actually be a unary increment which has been lowered to a binary
 /// operation). The check passes if \p Check, which is an \c i1, is \c true.
-void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) {
+void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info,
+                                       ArrayRef<SanitizerKind> Kinds) {
   assert(CGF.IsSanitizerScope);
   StringRef CheckName;
   SmallVector<llvm::Constant *, 4> StaticData;
@@ -915,7 +917,7 @@
       CheckName = "divrem_overflow";
       StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty));
     } else {
-      // Signed arithmetic overflow (+, -, *).
+      // Arithmetic overflow (+, -, *).
       switch (Opcode) {
       case BO_Add: CheckName = "add_overflow"; break;
       case BO_Sub: CheckName = "sub_overflow"; break;
@@ -928,8 +930,7 @@
     DynamicData.push_back(Info.RHS);
   }
 
-  CGF.EmitCheck(Check, CheckName, StaticData, DynamicData,
-                CodeGenFunction::CRK_Recoverable);
+  CGF.EmitCheck(Check, CheckName, StaticData, DynamicData, Kinds);
 }
 
 //===----------------------------------------------------------------------===//
@@ -2179,9 +2180,12 @@
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
     const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
   llvm::Value *Cond = nullptr;
+  SmallVector<SanitizerKind, 2> Kinds;
 
-  if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero))
+  if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
     Cond = Builder.CreateICmpNE(Ops.RHS, Zero);
+    Kinds.push_back(SanitizerKind::IntegerDivideByZero);
+  }
 
   if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
       Ops.Ty->hasSignedIntegerRepresentation()) {
@@ -2195,10 +2199,11 @@
     llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
     llvm::Value *Overflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
     Cond = Cond ? Builder.CreateAnd(Cond, Overflow, "and") : Overflow;
+    Kinds.push_back(SanitizerKind::SignedIntegerOverflow);
   }
 
   if (Cond)
-    EmitBinOpCheck(Cond, Ops);
+    EmitBinOpCheck(Cond, Ops, Kinds);
 }
 
 Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
@@ -2212,7 +2217,8 @@
     } else if (CGF.SanOpts.has(SanitizerKind::FloatDivideByZero) &&
                Ops.Ty->isRealFloatingType()) {
       llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
-      EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops);
+      EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops,
+                     SanitizerKind::FloatDivideByZero);
     }
   }
 
@@ -2297,7 +2303,9 @@
     // runtime. Otherwise, this is a -ftrapv check, so just emit a trap.
     if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) {
       CodeGenFunction::SanitizerScope SanScope(&CGF);
-      EmitBinOpCheck(Builder.CreateNot(overflow), Ops);
+      EmitBinOpCheck(Builder.CreateNot(overflow), Ops,
+                     isSigned ? SanitizerKind::SignedIntegerOverflow
+                              : SanitizerKind::UnsignedIntegerOverflow);
     } else
       CGF.EmitTrapCheck(Builder.CreateNot(overflow));
     return result;
@@ -2687,7 +2695,7 @@
       Valid = P;
     }
 
-    EmitBinOpCheck(Valid, Ops);
+    EmitBinOpCheck(Valid, Ops, SanitizerKind::Shift);
   }
   // OpenCL 6.3j: shift values are effectively % word size of LHS.
   if (CGF.getLangOpts().OpenCL)
@@ -2706,7 +2714,9 @@
   if (CGF.SanOpts.has(SanitizerKind::Shift) && !CGF.getLangOpts().OpenCL &&
       isa<llvm::IntegerType>(Ops.LHS->getType())) {
     CodeGenFunction::SanitizerScope SanScope(&CGF);
-    EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops);
+    EmitBinOpCheck(
+        Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops,
+        SanitizerKind::Shift);
   }
 
   // OpenCL 6.3j: shift values are effectively % word size of LHS.
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 5853e07..cbedf61 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -900,8 +900,8 @@
     if (SanOpts.has(SanitizerKind::Return)) {
       SanitizerScope SanScope(this);
       EmitCheck(Builder.getFalse(), "missing_return",
-                EmitCheckSourceLocation(FD->getLocation()),
-                None, CRK_Unrecoverable);
+                EmitCheckSourceLocation(FD->getLocation()), None,
+                SanitizerKind::Return);
     } else if (CGM.getCodeGenOpts().OptimizationLevel == 0)
       Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap));
     Builder.CreateUnreachable();
@@ -1562,7 +1562,7 @@
             };
             EmitCheck(Builder.CreateICmpSGT(Size, Zero),
                       "vla_bound_not_positive", StaticArgs, Size,
-                      CRK_Recoverable);
+                      SanitizerKind::VLABound);
           }
 
           // Always zexting here would be wrong if it weren't
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index a683e88..de2f4da 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2649,23 +2649,13 @@
   /// passing to a runtime sanitizer handler.
   llvm::Constant *EmitCheckSourceLocation(SourceLocation Loc);
 
-  /// \brief Specify under what conditions this check can be recovered
-  enum CheckRecoverableKind {
-    /// Always terminate program execution if this check fails
-    CRK_Unrecoverable,
-    /// Check supports recovering, allows user to specify which
-    CRK_Recoverable,
-    /// Runtime conditionally aborts, always need to support recovery.
-    CRK_AlwaysRecoverable
-  };
-
   /// \brief Create a basic block that will call a handler function in a
   /// sanitizer runtime with the provided arguments, and create a conditional
   /// branch to it.
   void EmitCheck(llvm::Value *Checked, StringRef CheckName,
                  ArrayRef<llvm::Constant *> StaticArgs,
                  ArrayRef<llvm::Value *> DynamicArgs,
-                 CheckRecoverableKind Recoverable);
+                 ArrayRef<SanitizerKind> Kinds);
 
   /// \brief Create a basic block that will call the trap intrinsic, and emit a
   /// conditional branch to it, for the -ftrapv checks.