We have a Clang Static Analyzer plugin that exposes several custom checkers. Currently I’m working on a checker that aims to enforce the practice that it is the responsibility of the class ctors to initialize all member variables.
Unfortunately, this requires the Static Analyzer to analyze the constructor, which does not happen without having the ctor called from a global function, which the SA treats as entry points.
This, however, leads to a problem: in production code, the definition of the class members and the user of the class are usually in different TUs, i.e. the SA won’t be able to analyze the ctor call.
Therefore, I’d like to make the SA treat constructors as entry points. More generally, how can I control which functions are analyzed (i.e. treated as entry points)? If this is not really something that can be done externally (i.e. outside Clang itself), where should I look inside the Clang source for this logic? (We can then create a patch, and ship a custom-patched version of Clang alongside with our checker library.)
If it doesn't already exist (I don't know), a general mechanism to specify a set of entry points would be a useful mechanism to add. For example, I'd like every test to be considered a valid entry point to the program. This could be faked of course (via calls to the test runner in the program main or by analyzing the test driver itself), but being able to simply specify the list at analysis time would be helpful.
By default, the static analyzer treats all functions declared in the main source file as possible entry points, then removes those that get called from another function being analyzed. That should include constructors and other member functions. There's a scan-build option (whose name escapes me right now) to also analyze functions declared in header files, and there's a secret (-cc1) option -analyze-function=NAME that only analyzes decls with a matching name. (I'm not sure if that works for constructors.)
To Philip's point, being able to specify explicit entry points does seem reasonable; a patch to specify this in scan-build and thread it through to AnalysisConsumer would probably be accepted. Specifically, check out getModeForDecl.
Ah, that changes things. I just did some tests, and indeed, when there is just a class definition in a translation unit, the class’ ctor is indeed treated as an entry point.
Unfortunately, as far as I can tell, checkPreCall is NOT called on it - when it calls other functions, I get a checkPreCall for them, but not for the entry point itself.
We’re using Clang 3.3. Is this by design? Is there a way I can get notified of this?
checkPreCall wouldn’t work for this, because there’s no CallEvent for the entry point, because there’s no call expression or argument values. It’s definitely a flaw that we don’t have a checkInitialConditons or something for this, though…we’ve needed it several times.
If you’re interested, patches welcome. In theory it shouldn’t be too difficult; the current equivalent is the hardcoded ExprEngine::getInitialState.