Clang: checker vs. plugin

Reading the docs through carefully, I have realized that plugins are used by the compiler, whereas checkers are used by the analyzer. Sorry for such a trivial question.

Cheers.

2014-04-19 13:43 GMT+02:00 Aitor San Juan <aitor.sj@opendeusto.es>:

That’s not quite the distinction, but it’s probably close enough for your purposes.

In Clang, “plugin” means a shared library (DLL, .so, .dylib) that can be loaded by the compiler. The most common use of plugins is to provide additional “actions” to perform on an AST after it has been parsed; the ‘-plugin’ flag is used to select which plugin actions to run. See http://clang.llvm.org/docs/ClangPlugins.html and the PrintFunctionNames plugin in the examples/ directory.

A “checker” is used by the analyzer to improve knowledge about the program it’s analyzing; it’s a sort of visitor that can get callbacks for each expression that gets evaluated. The analyzer has a number of built-in checkers, just like the compiler has several built-in AST actions. Plugins (i.e. loaded libraries) can also add additional checkers, though support for this is a bit brittle.* The only real documentation on this is in include/clang/StaticAnalyzer/Core/CheckerRegistry.h, plus the tiny checker plugin in the examples/ directory.

Hope that helps clear things up a bit.
Jordan

  • I was the one who added support for checker plugins many years ago (before joining Apple), but no one’s really taken ownership in the past few years. We’re pretty much just keeping the existing support limping along, no improvements.

Many thanks for the details, Jordan.

Now new questions arise:

1)From your comments, may I conclude that checker-plugins are not in the current development path for Clang/Analyzer? Is that path currently somehow frozen?

  1. What additional “actions” could be perfomed on an AST? I can only think of programatically modifying the AST, i.e., programatically changing the source code to make it, for example, compliant with coding rules or the like. Any other uses? I’m still (in the process of) becoming more familiar with this.

  2. You say that plugins can also add additional checkers. From the example you mention (MainCallChecker.cpp) and from the documentation in CheckerRegistry.h, what do you exactly mean by “add”? Are you referring to the fact that you register the checker? Am I right if I conclude that if a plugin adds several checkers, these are packed/compiled in the same final DLL for the plugin, and, thus, that’s why the plugin needs loading to be able to use its checkers? (in this last case, would it be necessary to rebuild Clang as with a normal checker? I guess it wouldn’t).

Thanks a lot for your reply.

Aitor.

Sorry for the delayed response.

Many thanks for the details, Jordan.

Now new questions arise:

1)From your comments, may I conclude that checker-plugins are not in the current development path for Clang/Analyzer? Is that path currently somehow frozen?

There's no intended restriction here, there's just no one working on it. If you run into an issue using checker-plugins, it's likely to go to the bottom of everyone's list. Patches to fix issues with plugins will still be reviewed and accepted, though.

2) What additional "actions" could be perfomed on an AST? I can only think of programatically modifying the AST, i.e., programatically changing the source code to make it, for example, compliant with coding rules or the like. Any other uses? I'm still (in the process of) becoming more familiar with this.

We don't actually allow mutation of a built AST, so you don't even get that. But here are some of the actions that happen within Clang's source tree:

- Generate LLVM IR (normal compilation).
- Run the analyzer.
- Run some ASTMatcher-based action (e.g. http://clang.llvm.org/docs/LibASTMatchersTutorial.html)
- Pretty-print the source (I don't think we have this yet).
- Generate a PCH from the parsed AST (-emit-pch).
- Run some refactoring action, like the Objective-C modernizer.
- Do nothing (-fsyntax-only)

There are also actions that consume preprocessor output instead of an AST, but I don't think those can be run from a Plugin in the same way. Not sure, though.

3) You say that plugins can also add additional checkers. From the example you mention (MainCallChecker.cpp) and from the documentation in CheckerRegistry.h, what do you exactly mean by "add"? Are you referring to the fact that you register the checker? Am I right if I conclude that if a plugin adds several checkers, these are packed/compiled in the same final DLL for the plugin, and, thus, that's why the plugin needs loading to be able to use its checkers? (in this last case, would it be necessary to rebuild Clang as with a normal checker? I guess it wouldn't).

Right, it wouldn't. CheckerRegistry uses static constructors to do its job, meaning that code is run simply by loading the plugin's DLL. One plugin-DLL can contain any number of checkers, which each get registered with the main executable's CheckerRegistry. At one point I remember hearing that this had issues on Windows, but I don't know what they were and I can't remember any recent complaints. (I work primarily with OS X, but other contributors to the analyzer use Linux, FreeBSD, and Windows.)

Jordan

Jordan, don’t worry for the belated answer. There must be other issues more important and urgent, but I very much appreciate the clarifying comments.

Just skimming over the API, I once came across with ASTWriter, which made me (wrongly) think its use was for programatically changing the AST. It makes sense to prohibit such modifications. One could end up generating invalid code. Having read through more carefully, I’ve realized that its purpose is deserialization (there exists the counterpart ASTReader).

May I ask one last question on this? Let’s say you want to make sure developers follow specific coding rules, you can do that by applying a checker or a plugin and integrate it into the build or compile process. I guess for this particular task a plugin would best fit. Am I correct?

However, to what extent can a checker or a plugin influence in the build and/or compile process? As far as I know, a checker cannot interfere in the compile process. In the checker dev. manual (“bug reports” section) it says that a checker (depending on the detected issue) may stop the analysis. When talking about “stopping the analysis”, I understand that it always refers to stopping the analysis along the current execution path, not to the fact that by emitting a report from one checker you might tell the analyzer to stop and terminate. Am I right? I guess the case of a plugin is similar: I mean you cannot tell the compiler to stop compiling by emitting warnings from within a plugin.

Many thanks.