@@ -1208,21 +1208,32 @@ class TransferFunctions {
12081208 }
12091209 }
12101210 }
1211- if (!Narrowed && isNonnullInit (RHS ))
1212- Narrowed = true ;
1213- if (!Narrowed && isNonnullType (BO ->getRHS ()->getType ()))
1214- Narrowed = true ;
1215-
1216- if (Narrowed) {
1217- if (IsThisMember)
1218- State.NarrowedThisMembers .insert (FD );
1219- else if (BaseVD)
1220- State.NarrowedMembers .insert ({BaseVD, FD });
1221- } else if (isNullableType (BO ->getRHS ()->getType (), StrictMode,
1222- DefaultNullability) ||
1223- isNullableInit (RHS )) {
1211+ // Null constant assigned to _Nonnull member — warn immediately.
1212+ // Check before isNonnullInit/isNonnullType because implicit
1213+ // casts can propagate _Nonnull from the LHS onto the RHS type.
1214+ if (!Narrowed && isNonnullType (FD ->getType ()) &&
1215+ isNullableInit (RHS ) && !isNonnullInit (RHS )) {
12241216 if (IsThisMember)
12251217 State.NullableThisMembers .insert (FD );
1218+ ++NumAssignmentWarnings;
1219+ Handler.handleNullableMemberAssignment (BO , FD );
1220+ } else {
1221+ if (!Narrowed && isNonnullInit (RHS ))
1222+ Narrowed = true ;
1223+ if (!Narrowed && isNonnullType (BO ->getRHS ()->getType ()))
1224+ Narrowed = true ;
1225+
1226+ if (Narrowed) {
1227+ if (IsThisMember)
1228+ State.NarrowedThisMembers .insert (FD );
1229+ else if (BaseVD)
1230+ State.NarrowedMembers .insert ({BaseVD, FD });
1231+ } else if (isNullableType (BO ->getRHS ()->getType (), StrictMode,
1232+ DefaultNullability) ||
1233+ isNullableInit (RHS )) {
1234+ if (IsThisMember)
1235+ State.NullableThisMembers .insert (FD );
1236+ }
12261237 }
12271238
12281239 // Emit evidence for cross-TU inference.
@@ -1284,18 +1295,23 @@ class TransferFunctions {
12841295 }
12851296 }
12861297 }
1287- if (isNonnullInit (RHS )) {
1298+ // Null constant assigned to _Nonnull — warn immediately.
1299+ // Check before isNonnullInit/isNonnullType because implicit
1300+ // casts can propagate _Nonnull from the LHS onto the RHS type.
1301+ if (isNonnullType (VD ->getType ()) && isNullableInit (RHS ) &&
1302+ !isNonnullInit (RHS )) {
1303+ State.NullableVars .insert (VD );
1304+ ++NumAssignmentWarnings;
1305+ Handler.handleNullableAssignment (BO , VD );
1306+ } else if (isNonnullInit (RHS )) {
12881307 State.NarrowedVars .insert (VD );
12891308 return ;
1290- }
1291- if (isNonnullType (BO ->getRHS ()->getType ())) {
1309+ } else if (isNonnullType (BO ->getRHS ()->getType ())) {
12921310 State.NarrowedVars .insert (VD );
12931311 } else if (isNullableType (BO ->getRHS ()->getType (), StrictMode,
12941312 DefaultNullability) ||
12951313 isNullableInit (RHS )) {
12961314 State.NullableVars .insert (VD );
1297- // Flow-sensitive assignment check: warn when assigning a
1298- // nullable value to a _Nonnull variable.
12991315 if (isNonnullType (VD ->getType ())) {
13001316 ++NumAssignmentWarnings;
13011317 Handler.handleNullableAssignment (BO , VD );
@@ -1861,8 +1877,14 @@ class TransferFunctions {
18611877
18621878 if (const auto *FD = dyn_cast<FieldDecl>(ME ->getMemberDecl ())) {
18631879 if (isa<CXXThisExpr>(Base)) {
1864- if (!isThisMemberNarrowed (FD ))
1880+ // If flow analysis marked this member nullable (e.g. assigned nullptr),
1881+ // that overrides the declared _Nonnull type.
1882+ if (State.NullableThisMembers .contains (FD )) {
1883+ ++NumDereferenceWarnings;
1884+ Handler.handleNullableDereference (DerefExpr, ME ->getType ());
1885+ } else if (!isThisMemberNarrowed (FD )) {
18651886 checkDeref (DerefExpr, ME ->getType ());
1887+ }
18661888 } else if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
18671889 if (const auto *BaseVD = dyn_cast<VarDecl>(DRE ->getDecl ())) {
18681890 if (!isMemberNarrowed (BaseVD, FD ))
@@ -1913,6 +1935,10 @@ class ReturnNonnullTracker : public FlowNullabilityHandler {
19131935 void handleNullableAssignment (const Expr *E, const VarDecl *V) override {
19141936 Inner.handleNullableAssignment (E, V);
19151937 }
1938+ void handleNullableMemberAssignment (const Expr *E,
1939+ const FieldDecl *M) override {
1940+ Inner.handleNullableMemberAssignment (E, M);
1941+ }
19161942 void handleNullableArgument (const Expr *E, const ParmVarDecl *P) override {
19171943 Inner.handleNullableArgument (E, P);
19181944 }
0 commit comments