[StaticAnalyzer]: Cant get my checker to output

Hi,

How do I find out if my checker has run or not? There doesn’t seem to be any option in scan-build that tells us which checkers were run. I tried printing to std::cout, std::cerr but nothing got printed. I tried generating a bug report but that didn’t get generated either. But my checker does show up in the list of checkers when I run scan-build. I have even entered the details in Checkers.td.

Here is what I have tried far:

namespace {
class ConstantConditionChecker : public Checker<check::PostStmt >{
mutable llvm::OwningPtr BT;
public:
void checkPostStmt(const IfStmt *ifStmt, CheckerContext &C) const;
};
}

void ConstantConditionChecker::checkPostStmt(const IfStmt *ifStmt, CheckerContext &C) const
{
ASTContext& astContext = C.getASTContext();
std::string sbuf;
llvm::raw_string_ostream Out(sbuf);

ifStmt->getCond()->printPretty(Out, NULL, PrintingPolicy(astContext.getLangOptions()));
std::cerr << Out.str() << std::endl;
std::cout << “Hello\n” << std::endl;
std::cerr << “Hello cerr” << std::endl;
if (!BT)
BT.reset(new BuiltinBug(Out.str().c_str()));
BugReport* R = new BugReport(*BT, BT->getDescription(), C.getPredecessor());
R->addRange(ifStmt->getSourceRange());
C.EmitReport(R);

}

void ento::registerConstantConditionChecker(CheckerManager &mgr) {
mgr.registerChecker();
}

Hello,

Check if your checker is properly registered. You can use the following command to view the registered checkers:
$ clang -cc1 -analyzer-checker-helpOnly some of them will get executed when scan-build is run (If you see your checker listed in scan-build output, it should be executed).

Are there if statements in your test program? You would see the output only when an if statement is processed.

While developing/debugging a checker, you can use the following command (this will execute only the specified checker):
$ clang -cc1 -analyze -analyzer-checker=core.StackAddressEscape input.cpp

You can print debug messages with:
llvm::errs()<<“Hello”;
llvm::outs()<<“Hello”;

Cheers,
Anna.

Hi,

Thank you for replying. The problem is that clang is running some optimizations before running the analyzer. As a result, my if statement is being optimized out and because of that nothing gets printed. clang should not run optimizations when running in analyze mode otherwise it can’t detect bugs in the original code. Do you agree?

Thanks,
Arjun

Clang does not perform optimizations on the AST.

John.

Not even constant folding and constant propagation?

Arjun

Correct. A few places in the AST, like array dimensions, do compute and store the value of a constant expression, but only in unevaluated contexts, and the original source information is never thrown away.

John.

Not even constant folding and constant propagation?

Yes. Not even constant propagation.

Anna.

Hi Arjun,

Do you have a short example of the code that you are analyzing. It is possible that the static analyzer has determined that the if statement is in a path that never gets executed. It should still be in the AST though. You can use -ast-dump to look at the AST directly.

  - jim

My checker was able to output (the debug messages show up) when I changed the IfStmt to BinaryOperator. So my checker has been registered correctly. It is not able to deal with IfStmt for some reason.

Here is the code I am trying to analyze:

#include<stdio.h>

int foo() { return 2; }

int main(void)
{
int a = foo();
int b = foo();

scanf("%d", &a);

a = a + b;
if (a == 2)
{
a = 4;
}

printf("%d", a);

return 0;
}

Ok I just verified that checkPostStmt is never executed for IfStmt. I changed the target type to “Stmt” and then tried to cast each Stmt to IfStmt. The dynamic cast was never successful. Tried using Stmt::getStmtClass() as well. I tried to prove this by printing out the run-time type by using typeid. But I got a compilation error saying I cannot use typeid with -fno-rtti. I did not know how to get around that. I don’t know what I am missing. You can try it out by using the following:

namespace {
class ConstantConditionChecker : public Checker<check::PostStmt >{
public:
void checkPostStmt(const Stmt *stmt, CheckerContext &C) const;
};
}

void ConstantConditionChecker::checkPostStmt(const Stmt *stmt, CheckerContext &C) const
{
ASTContext& astContext = C.getASTContext();
std::string sbuf;
llvm::raw_string_ostream Out(sbuf);

if (const IfStmt *ifStmt = dyn_cast(stmt))
{
stmt->printPretty(Out, NULL, PrintingPolicy(astContext.getLangOptions()));
llvm::errs()<< Out.str().c_str();
llvm::errs() << “Hello\n”;
}

if (const WhileStmt *whileStmt = dyn_cast(stmt))
{
stmt->printPretty(Out, NULL, PrintingPolicy(astContext.getLangOptions()));
llvm::errs() << Out.str().c_str();
llvm::errs() << “Hello2\n”;
}

if (stmt->getStmtClass() == Stmt::IfStmtClass)
{
llvm::errs() << “StmtClass\n”;
}
}

void ento::registerConstantConditionChecker(CheckerManager &mgr) {
mgr.registerChecker();
}

class

Hi Arjun,

The reason why the callback is not called is that IfStmt is not a CFGElement - it’s a CFGTerminator (it expresses only control flow). See the CFG block dump below. We only call checkPostStmt/checkPreStmt for statements that correspond to CFG elements.

If you want to visit the conditions within the if statements (or other branches), use checkBranchCondition() instead.

Cheers,
Anna.

[ B3 ]
1: foo
2: [B3.1]
3: B3.2
4: int a = foo();
5: foo
6: [B3.5]
7: B3.6
8: int b = foo();
9: a
10: &[B3.9]
11: “%d”
12: [B3.11]
13: [B3.12]
14: scanf
15: [B3.14]
16: [B3.15]([B3.13], [B3.10])
17: a
18: [B3.17]
19: b
20: [B3.19]
21: [B3.18] + [B3.20]
22: a
23: [B3.22] = [B3.21]
24: a
25: [B3.24]
26: 2
27: [B3.25] == [B3.26]
T: if [B3.27]
Predecessors (1): B4
Successors (2): B2 B1