[clang] 2a06850 - [-Wcompletion-handler] Fix a non-termination issue (#78380)

via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 26 11:23:19 PST 2024


Author: Ziqing Luo
Date: 2024-01-26T11:23:15-08:00
New Revision: 2a068507016e476893b6b1b9c55b255dbae5829e

URL: https://github.com/llvm/llvm-project/commit/2a068507016e476893b6b1b9c55b255dbae5829e
DIFF: https://github.com/llvm/llvm-project/commit/2a068507016e476893b6b1b9c55b255dbae5829e.diff

LOG: [-Wcompletion-handler] Fix a non-termination issue (#78380)

The Called-Once dataflow analysis could never terminate as a
consequence of non-monotonic update on states.  States of kind Escape
can override states leading to non-monotonic update.

This fix disallows the `Escape` state to override the `Reported`
state.

rdar://119671856

Added: 
    

Modified: 
    clang/lib/Analysis/CalledOnceCheck.cpp
    clang/test/SemaObjC/warn-called-once.m

Removed: 
    


################################################################################
diff  --git a/clang/lib/Analysis/CalledOnceCheck.cpp b/clang/lib/Analysis/CalledOnceCheck.cpp
index 04c5f6aa9c7450..30cbd257b65e8f 100644
--- a/clang/lib/Analysis/CalledOnceCheck.cpp
+++ b/clang/lib/Analysis/CalledOnceCheck.cpp
@@ -163,7 +163,7 @@ class ParameterStatus {
     NotVisited = 0x8, /* 1000 */
     // We already reported a violation and stopped tracking calls for this
     // parameter.
-    Reported = 0x15, /* 1111 */
+    Reported = 0xF, /* 1111 */
     LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Reported)
   };
 
@@ -932,7 +932,8 @@ class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> {
     ParameterStatus &CurrentParamStatus = CurrentState.getStatusFor(Index);
 
     // Escape overrides whatever error we think happened.
-    if (CurrentParamStatus.isErrorStatus()) {
+    if (CurrentParamStatus.isErrorStatus() &&
+        CurrentParamStatus.getKind() != ParameterStatus::Kind::Reported) {
       CurrentParamStatus = ParameterStatus::Escaped;
     }
   }

diff  --git a/clang/test/SemaObjC/warn-called-once.m b/clang/test/SemaObjC/warn-called-once.m
index dbe8dc1cf1ae17..f23e41e00ee298 100644
--- a/clang/test/SemaObjC/warn-called-once.m
+++ b/clang/test/SemaObjC/warn-called-once.m
@@ -1194,6 +1194,16 @@ - (void)test_escape_after_branch:(int)cond
   escape(handler);
 }
 
+- (void)test_termination:(int)cond
+                  withCompletion:(void (^)(void))handler {
+  // The code below was able to cause non-termination but should be
+  // fixed now:
+  do {
+    escape(handler);    
+    handler();    // expected-warning{{completion handler is called twice}} expected-note{{previous call is here; set to nil to indicate it cannot be called afterwards}}
+  } while (cond);
+}
+
 typedef void (^DeferredBlock)(void);
 static inline void DefferedCallback(DeferredBlock *inBlock) { (*inBlock)(); }
 #define _DEFERCONCAT(a, b) a##b


        


More information about the cfe-commits mailing list