vsavchenko created this revision.
vsavchenko added a reviewer: NoQ.
Herald added a subscriber: Charusso.
vsavchenko requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
It is very common to check callbacks and completion handlers for null.
This patch supports such checks using built-in functions:
- __builtin_expect
- __builtin_expect_with_probablity
- __builtin_unpredictable
rdar://73455388
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D96268
Files:
clang/lib/Analysis/CalledOnceCheck.cpp
clang/test/SemaObjC/warn-called-once.m
Index: clang/test/SemaObjC/warn-called-once.m
===================================================================
--- clang/test/SemaObjC/warn-called-once.m
+++ clang/test/SemaObjC/warn-called-once.m
@@ -4,6 +4,11 @@
#define nil (id)0
#define CALLED_ONCE __attribute__((called_once))
#define NORETURN __attribute__((noreturn))
+#define LIKELY(X) __builtin_expect(!!(X), 1)
+#define UNLIKELY(X) __builtin_expect(!!(X), 0)
+#define LIKELY_WITH_PROBA(X, P) __builtin_expect_with_probability(!!(X), 1, P)
+#define UNLIKELY_WITH_PROBA(X, P) __builtin_expect_with_probability(!!(X), 0, P)
+#define UNPRED(X) __builtin_unpredictable((long)(X))
@protocol NSObject
@end
@@ -547,6 +552,70 @@
// no-warning
}
+void call_with_builtin_check_1(int (^callback)(void) CALLED_ONCE) {
+ if (LIKELY(callback))
+ callback();
+ // no-warning
+}
+
+void call_with_builtin_check_2(int (^callback)(void) CALLED_ONCE) {
+ if (!UNLIKELY(callback)) {
+ } else {
+ callback();
+ }
+ // no-warning
+}
+
+void call_with_builtin_check_3(int (^callback)(void) CALLED_ONCE) {
+ if (__builtin_expect((long)callback, 0L)) {
+ } else {
+ callback();
+ }
+ // no-warning
+}
+
+void call_with_builtin_check_4(int (^callback)(void) CALLED_ONCE) {
+ if (__builtin_expect(0L, (long)callback)) {
+ } else {
+ callback();
+ }
+ // no-warning
+}
+
+void call_with_builtin_check_5(int (^callback)(void) CALLED_ONCE) {
+ if (LIKELY_WITH_PROBA(callback, 0.9))
+ callback();
+ // no-warning
+}
+
+void call_with_builtin_check_6(int (^callback)(void) CALLED_ONCE) {
+ if (!UNLIKELY_WITH_PROBA(callback, 0.9)) {
+ } else {
+ callback();
+ }
+ // no-warning
+}
+
+void call_with_builtin_check_7(int (^callback)(void) CALLED_ONCE) {
+ if (UNPRED(callback)) {
+ } else {
+ callback();
+ }
+ // no-warning
+}
+
+void call_with_builtin_check_8(int (^callback)(void) CALLED_ONCE) {
+ if (LIKELY(callback != nil))
+ callback();
+ // no-warning
+}
+
+void call_with_builtin_check_9(int (^callback)(void) CALLED_ONCE) {
+ if (!UNLIKELY(callback == NULL))
+ callback();
+ // no-warning
+}
+
void unreachable_true_branch(void (^callback)(void) CALLED_ONCE) {
if (0) {
Index: clang/lib/Analysis/CalledOnceCheck.cpp
===================================================================
--- clang/lib/Analysis/CalledOnceCheck.cpp
+++ clang/lib/Analysis/CalledOnceCheck.cpp
@@ -22,6 +22,7 @@
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/BitVector.h"
@@ -330,6 +331,29 @@
return Visit(OVE->getSourceExpr());
}
+ const DeclRefExpr *VisitCallExpr(const CallExpr *CE) {
+ if (!ShouldRetrieveFromComparisons)
+ return nullptr;
+
+ // We want to see through some of the boolean builtin functions
+ // that we are likely to see in conditions.
+ switch (CE->getBuiltinCallee()) {
+ case Builtin::BI__builtin_expect:
+ case Builtin::BI__builtin_expect_with_probability: {
+ assert(CE->getNumArgs() >= 2);
+
+ const DeclRefExpr *Candidate = Visit(CE->getArg(0));
+ return Candidate != nullptr ? Candidate : Visit(CE->getArg(1));
+ }
+
+ case Builtin::BI__builtin_unpredictable:
+ return Visit(CE->getArg(0));
+
+ default:
+ return nullptr;
+ }
+ }
+
const DeclRefExpr *VisitExpr(const Expr *E) {
// It is a fallback method that gets called whenever the actual type
// of the given expression is not covered.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits