I'm still forming some thoughts on this. My initial impression while I think this is a good direction, it really does feel overly complicated, particularly with the use of clang_getCheckersForPackage_PACKAGE functions.
I'm most mixed about the CheckerPackage abstraction. How would it actually be used? It seems to me that:
(a) First a plugin must be loaded, e.g. using llvm::sys::DynamicLibrary.
(b) Then the CheckerPackage::create() function is called to register checkers, but this seems to require a priori knowledge of the package name.
In your code snippet below, it's not clear to me where (b) lives. Does it live in the plugin? If so, this seems like a lot of indirection, when we could possibly instead use the plugin registry mechanism instead to find the CheckerManager and then register the checkers. What's the benefit of the clang_getCheckersForPackage abstraction?
The mechanism I had more in mind was that a user writes a plugin, which links against clang and the static analyzer libraries. It uses the llvm::Registry mechanism to load checkers using static constructors when the plugin is loaded. This would be very simple, akin to what we can do with optimization passes:
In that example, we have RegisterRegAlloc, but instead we could have something like "RegisterCheckers". It could take as an argument a function that returns a factory object (perhaps CheckerPackage?) that allows one to instantiate checkers given a CheckerManager. The key thing to keep in mind is that his simple approach is very flexible. One could possibly register several checkers into different packages. We can also probably decouple checker registration from package registration. Packages are just groups; when a checker gets loaded, it could just declare that it goes into a specific package. If that group doesn't exist, the CheckerManager just creates one with the default visibility. If the package gets explicitly registered (using a similar mechanism, e.g. "RegisterCheckerPackage"), that registration could provide enabled/disabled information for that package, visibility, and strings to describe that package.
In this mode, we get a nice decoupling. Checker writers only have to declare the package the checker goes into by providing a package string. They can also provide strings that describe the checker, which is then used by the registration mechanism. Packages can be managed and registered separately.
This simpler, declarative approach also resolves the -print-help problem. Instead of -print-help, I would expect we move in a direction where checkers just provide descriptive strings, and the help is formatted by whoever cares about it. Checkers, and packages, should not get in the business of printing out anything. That should be up to the client of the CheckerManager.
Anyhow, I'm stilling mulling this over, but I think we want to keep this simple and flexible.
What do you think?