[cfe-dev] Best place for semantic checks
Ted Kremenek
kremenek at apple.com
Tue Jul 8 13:19:45 PDT 2008
On Jul 8, 2008, at 11:55 AM, Martin Doucha wrote:
> Hi,
> I want to write semantic checker for newbie mistakes/undefined
> behavior
> using Clang. Where should I put the code - into Sema module or into a
> new ASTConsumer module crammed between Sema and other ASTConsumers?
>
> Regards,
> Martin
Hi Martin,
You have three options. Put the logic in Sema, create a new
ASTConsumer, or use the AnalysisConsumer interface, which was designed
explicitly for running different kinds of static analysis checks. If
you want your checks committed back to Clang, probably the best place
is to use the new AnalysisConsumer interface (so that it hooks in
nicely with the other static analysis checks), but it's entirely up to
you. Note that the AnalysisConsumer interface is designed to be us
If you use the new AnalysisConsumer interface, you will need to make a
few small changes to AnalysisConsumer.h, AnalysisConsumer.cpp, and a
small place in clang.cpp to hook up your checks to the driver.
AnalysisConsumer calls the dead store checker, the memory leak
checker, and so on. The actual logic for your checks should go into a
separate .cpp file, either in the Driver or in the Analysis library,
with a header file included by AnalysisConsumer.cpp to actually invoke
the logic of your checks.
Eventually, this interface will be further simplified, hopefully
obviating the need to modify AnalysisConsumer.h, AnalysisConsumer.cpp,
and clang.cpp.
Using the AnalysisConsumer interface (or your own ASTConsumer) uses a
different code path than code generation, so using that interface
means the checks won't be performed when code is compiled using
Clang. You can use scan-build/ccc-analyzer, however, to invoke your
checker over an entire code base by modifying the clang command line
invoked by ccc-analyzer.
If your checks prove to be both effective and very quick, this logic
could be migrated to Sema. I only suggest hooking it into
AnalysisConsumer to start with because the logic is easier to work
with than Sema (Sema is doing a lot of things), you get to harness the
scan-build checker harness, and adding a new driver option is a snap.
More specifically, you need to modify the following to use the
AnalysisConsumer interface:
--------------------
Driver/AnalysisConsumer.h:
Add a new value to the enum Analyses:
enum Analyses {
CFGDump,
CFGView,
WarnDeadStores,
WarnUninitVals,
DisplayLiveVariables,
CheckerCFRef,
CheckerSimple,
MyChecker // <--------------------------
};
--------------------
Driver/AnalysisConsumer.cpp:
1) Add a static "Action" function that calls your checker using the
appropriate arguments.
static void ActionMyChecker(AnalysisManager& mgr) {
// Call the checker using arguments provided by queries to
AnalysisManager.
...
}
2) Add a case in CreateAnalysisConsumer for your Analysis using the
enum value you added to Driver/AnalysisConsumer.h:
ASTConsumer* clang::CreateAnalysisConsumer(...) {
...
for ( ; Beg != End ; ++Beg)
switch (*Beg) {
case WarnDeadStores:
C->addCodeAction(&ActionDeadStores);
break;
case WarnUninitVals:
C->addCodeAction(&ActionUninitVals);
break;
// ADD A CASE HERE
case MyChecker:
C->addCodeAction(&ActionMyChecker);
break;
--------------------
Driver/Clang.cpp:
Add your command line argument to "Analyses"
static llvm::cl::list<Analyses>
AnalysisList(llvm::cl::desc("Available Source Code Analyses:"),
llvm::cl::values(
clEnumValN(CFGDump, "cfg-dump", "Display Control-Flow Graphs"),
clEnumValN(CFGView, "cfg-view", "View Control-Flow Graphs using
GraphViz"),
clEnumValN(DisplayLiveVariables, "dump-live-variables",
"Print results of live variable analysis"),
clEnumValN(WarnDeadStores, "warn-dead-stores",
"Flag warnings of stores to dead variables"),
clEnumValN(WarnUninitVals, "warn-uninit-values",
"Flag warnings of uses of unitialized variables"),
clEnumValN(CheckerSimple, "checker-simple",
"Perform simple path-sensitive checks."),
clEnumValN(CheckerCFRef, "checker-cfref",
"Run the [Core] Foundation reference count checker"),
clEnumValnN(MyChecker, "my-checker", //
<------------------------------------------
"My Custom Checker"),
clEnumValEnd));
- Ted
More information about the cfe-dev
mailing list