@@ -10801,6 +10801,26 @@ static void DiagnoseImpCast(Sema &S, Expr *E, QualType T,
1080110801 DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow);
1080210802}
1080310803
10804+ static bool isObjCSignedCharBool(Sema &S, QualType Ty) {
10805+ return Ty->isSpecificBuiltinType(BuiltinType::SChar) &&
10806+ S.getLangOpts().ObjC && S.NSAPIObj->isObjCBOOLType(Ty);
10807+ }
10808+
10809+ static void adornObjCBoolConversionDiagWithTernaryFixit(
10810+ Sema &S, Expr *SourceExpr, const Sema::SemaDiagnosticBuilder &Builder) {
10811+ Expr *Ignored = SourceExpr->IgnoreImplicit();
10812+ if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ignored))
10813+ Ignored = OVE->getSourceExpr();
10814+ bool NeedsParens = isa<AbstractConditionalOperator>(Ignored) ||
10815+ isa<BinaryOperator>(Ignored) ||
10816+ isa<CXXOperatorCallExpr>(Ignored);
10817+ SourceLocation EndLoc = S.getLocForEndOfToken(SourceExpr->getEndLoc());
10818+ if (NeedsParens)
10819+ Builder << FixItHint::CreateInsertion(SourceExpr->getBeginLoc(), "(")
10820+ << FixItHint::CreateInsertion(EndLoc, ")");
10821+ Builder << FixItHint::CreateInsertion(EndLoc, " ? YES : NO");
10822+ }
10823+
1080410824/// Diagnose an implicit cast from a floating point value to an integer value.
1080510825static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
1080610826 SourceLocation CContext) {
@@ -10820,6 +10840,13 @@ static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
1082010840 bool IsConstant =
1082110841 E->EvaluateAsFloat(Value, S.Context, Expr::SE_AllowSideEffects);
1082210842 if (!IsConstant) {
10843+ if (isObjCSignedCharBool(S, T)) {
10844+ return adornObjCBoolConversionDiagWithTernaryFixit(
10845+ S, E,
10846+ S.Diag(CContext, diag::warn_impcast_float_to_objc_signed_char_bool)
10847+ << E->getType());
10848+ }
10849+
1082310850 return DiagnoseImpCast(S, E, T, CContext,
1082410851 diag::warn_impcast_float_integer, PruneWarnings);
1082510852 }
@@ -10831,6 +10858,23 @@ static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
1083110858 llvm::APFloat::opStatus Result = Value.convertToInteger(
1083210859 IntegerValue, llvm::APFloat::rmTowardZero, &isExact);
1083310860
10861+ // FIXME: Force the precision of the source value down so we don't print
10862+ // digits which are usually useless (we don't really care here if we
10863+ // truncate a digit by accident in edge cases). Ideally, APFloat::toString
10864+ // would automatically print the shortest representation, but it's a bit
10865+ // tricky to implement.
10866+ SmallString<16> PrettySourceValue;
10867+ unsigned precision = llvm::APFloat::semanticsPrecision(Value.getSemantics());
10868+ precision = (precision * 59 + 195) / 196;
10869+ Value.toString(PrettySourceValue, precision);
10870+
10871+ if (isObjCSignedCharBool(S, T) && IntegerValue != 0 && IntegerValue != 1) {
10872+ return adornObjCBoolConversionDiagWithTernaryFixit(
10873+ S, E,
10874+ S.Diag(CContext, diag::warn_impcast_constant_value_to_objc_bool)
10875+ << PrettySourceValue);
10876+ }
10877+
1083410878 if (Result == llvm::APFloat::opOK && isExact) {
1083510879 if (IsLiteral) return;
1083610880 return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_float_integer,
@@ -10874,16 +10918,6 @@ static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
1087410918 DiagID = diag::warn_impcast_float_to_integer;
1087510919 }
1087610920
10877- // FIXME: Force the precision of the source value down so we don't print
10878- // digits which are usually useless (we don't really care here if we
10879- // truncate a digit by accident in edge cases). Ideally, APFloat::toString
10880- // would automatically print the shortest representation, but it's a bit
10881- // tricky to implement.
10882- SmallString<16> PrettySourceValue;
10883- unsigned precision = llvm::APFloat::semanticsPrecision(Value.getSemantics());
10884- precision = (precision * 59 + 195) / 196;
10885- Value.toString(PrettySourceValue, precision);
10886-
1088710921 SmallString<16> PrettyTargetValue;
1088810922 if (IsBool)
1088910923 PrettyTargetValue = Value.isZero() ? "false" : "true";
@@ -11160,14 +11194,10 @@ static bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T,
1116011194 return true;
1116111195}
1116211196
11163- static bool isObjCSignedCharBool(Sema &S, QualType Ty) {
11164- return Ty->isSpecificBuiltinType(BuiltinType::SChar) &&
11165- S.getLangOpts().ObjC && S.NSAPIObj->isObjCBOOLType(Ty);
11166- }
11167-
11168- static void
11169- CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
11170- bool *ICContext = nullptr) {
11197+ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
11198+ SourceLocation CC,
11199+ bool *ICContext = nullptr,
11200+ bool IsListInit = false) {
1117111201 if (E->isTypeDependent() || E->isValueDependent()) return;
1117211202
1117311203 const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
@@ -11214,19 +11244,13 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
1121411244 if (isObjCSignedCharBool(S, T) && Source->isIntegralType(S.Context)) {
1121511245 Expr::EvalResult Result;
1121611246 if (E->EvaluateAsInt(Result, S.getASTContext(),
11217- Expr::SE_AllowSideEffects) &&
11218- Result.Val.getInt() != 1 && Result.Val.getInt() != 0) {
11219- auto Builder = S.Diag(CC, diag::warn_impcast_constant_int_to_objc_bool)
11220- << Result.Val.getInt().toString(10);
11221- Expr *Ignored = E->IgnoreImplicit();
11222- bool NeedsParens = isa<AbstractConditionalOperator>(Ignored) ||
11223- isa<BinaryOperator>(Ignored) ||
11224- isa<CXXOperatorCallExpr>(Ignored);
11225- SourceLocation EndLoc = S.getLocForEndOfToken(E->getEndLoc());
11226- if (NeedsParens)
11227- Builder << FixItHint::CreateInsertion(E->getBeginLoc(), "(")
11228- << FixItHint::CreateInsertion(EndLoc, ")");
11229- Builder << FixItHint::CreateInsertion(EndLoc, " ? YES : NO");
11247+ Expr::SE_AllowSideEffects)) {
11248+ if (Result.Val.getInt() != 1 && Result.Val.getInt() != 0) {
11249+ adornObjCBoolConversionDiagWithTernaryFixit(
11250+ S, E,
11251+ S.Diag(CC, diag::warn_impcast_constant_value_to_objc_bool)
11252+ << Result.Val.getInt().toString(10));
11253+ }
1123011254 return;
1123111255 }
1123211256 }
@@ -11421,6 +11445,14 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
1142111445 if (Target->isSpecificBuiltinType(BuiltinType::Bool))
1142211446 return;
1142311447
11448+ if (isObjCSignedCharBool(S, T) && !Source->isCharType() &&
11449+ !E->isKnownToHaveBooleanValue()) {
11450+ return adornObjCBoolConversionDiagWithTernaryFixit(
11451+ S, E,
11452+ S.Diag(CC, diag::warn_impcast_int_to_objc_signed_char_bool)
11453+ << E->getType());
11454+ }
11455+
1142411456 IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated());
1142511457 IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target);
1142611458