@@ -9818,15 +9818,36 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
98189818 ((getLangOpts().C23 && RHS.get()->getType()->isNullPtrType()) ||
98199819 RHS.get()->isNullPointerConstant(Context,
98209820 Expr::NPC_ValueDependentIsNull))) {
9821+ AssignConvertType Ret = Compatible;
98219822 if (Diagnose || ConvertRHS) {
98229823 CastKind Kind;
98239824 CXXCastPath Path;
98249825 CheckPointerConversion(RHS.get(), LHSType, Kind, Path,
98259826 /*IgnoreBaseAccess=*/false, Diagnose);
9827+
9828+ // If there is a conversion of some kind, check to see what kind of
9829+ // pointer conversion happened so we can diagnose a C++ compatibility
9830+ // diagnostic if the conversion is invalid. This only matters if the RHS
9831+ // is some kind of void pointer.
9832+ if (Kind != CK_NoOp && !getLangOpts().CPlusPlus) {
9833+ QualType CanRHS =
9834+ RHS.get()->getType().getCanonicalType().getUnqualifiedType();
9835+ QualType CanLHS = LHSType.getCanonicalType().getUnqualifiedType();
9836+ if (CanRHS->isVoidPointerType() && CanLHS->isPointerType()) {
9837+ Ret = checkPointerTypesForAssignment(*this, CanLHS, CanRHS,
9838+ RHS.get()->getExprLoc());
9839+ // Anything that's not considered perfectly compatible would be
9840+ // incompatible in C++.
9841+ if (Ret != Compatible)
9842+ Ret = CompatibleVoidPtrToNonVoidPtr;
9843+ }
9844+ }
9845+
9846+
98269847 if (ConvertRHS)
98279848 RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_PRValue, &Path);
98289849 }
9829- return Compatible ;
9850+ return Ret ;
98309851 }
98319852 // C23 6.5.16.1p1: the left operand has type atomic, qualified, or
98329853 // unqualified bool, and the right operand is a pointer or its type is
@@ -13946,10 +13967,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
1394613967 LHSType->isObjCObjectPointerType())))
1394713968 ConvTy = Compatible;
1394813969
13949- if (ConvTy == Compatible &&
13950- LHSType->isObjCObjectType())
13951- Diag(Loc, diag::err_objc_object_assignment)
13952- << LHSType;
13970+ if (IsAssignConvertCompatible(ConvTy) && LHSType->isObjCObjectType())
13971+ Diag(Loc, diag::err_objc_object_assignment) << LHSType;
1395313972
1395413973 // If the RHS is a unary plus or minus, check to see if they = and + are
1395513974 // right next to each other. If so, the user may have typo'd "x =+ 4"
@@ -13971,7 +13990,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
1397113990 }
1397213991 }
1397313992
13974- if (ConvTy == Compatible ) {
13993+ if (IsAssignConvertCompatible( ConvTy) ) {
1397513994 if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong) {
1397613995 // Warn about retain cycles where a block captures the LHS, but
1397713996 // not if the LHS is a simple variable into which the block is
0 commit comments