BT_dispatchOnce.reset(new BugType("Improper use of 'dispatch_once'",
"Mac OS X API"));
+ // Handle _dispatch_once, which in some versions of the OS X SDK that
+ // dispatch_once is a macro that wraps a call to _dispatch_once, which
+ // then calls the real dispatch_once. Users do not care; they just
+ // want the warning at the top-level call.
+ if (CE->getLocStart().isMacroID()) {
+ StringRef TrimmedFName = FName.ltrim("_");
+ if (TrimmedFName != FName)
+ FName = TrimmedFName;
+ }
+
SmallString<256> S;
llvm::raw_svector_ostream os(S);
os << "Call to '" << FName << "' uses";
SubChecker SC =
llvm::StringSwitch<SubChecker>(Name)
- .Cases("dispatch_once", "dispatch_once_f",
+ .Cases("dispatch_once",
+ "_dispatch_once",
+ "dispatch_once_f",
&MacOSXAPIChecker::CheckDispatchOnce)
.Default(NULL);
foo[i] = 0;
}
}
+
+// Test dispatch_once being a macro that wraps a call to _dispatch_once, which in turn
+// calls the real dispatch_once.
+
+static inline void _dispatch_once(dispatch_once_t *predicate, dispatch_block_t block)
+{
+ dispatch_once(predicate, block);
+}
+
+#define dispatch_once _dispatch_once
+
+void test_dispatch_once_in_macro() {
+ dispatch_once_t pred = 0;
+ dispatch_once(&pred, ^(){}); // expected-warning {{Call to 'dispatch_once' uses the local variable 'pred' for the predicate value}}
+}