[cfe-dev] Who's your daddy?
Csaba Raduly
rcsaba at gmail.com
Tue Dec 16 01:04:37 PST 2014
Hi,
In our project (which can be built with either GCC or clang) we have
the convention that every 'if' must have an 'else'; this way we can
use line coverage to simulate branch coverage. We have a macro that
can be added at the end of an if statement:
#define ELSE_NOTHING_TO_DO else { asm("nop"); }
Now I'm writing a clang plugin that emits a warning when it sees an if
without an else. However, some if statements should get an exemption:
{
if (....) {
return;
}
another statement;
}
An 'if' statement whose 'then' clause ends with a
return/goto/break/continue/throw, and has a "next statement", doesn't
need an else because the coverage of the next statement can be used to
verify that both branches have been taken.
It's the "next statement" which is a bit tricky, because I need to get
the parent of the 'if' to check if it's a compound statement. I
couldn't figure out how to get a ParentMap inside VisitStmt(), so I
came up with the following instead:
class IfCheckVisitor : public RecursiveASTVisitor<IfCheckVisitor>
{
private:
ASTContext *context;
std::unique_ptr<ParentMap> pm;
public:
bool VisitDecl(Decl *d) {
switch (d->getKind()) {
case Decl::Function: {
FunctionDecl *fd = static_cast<FunctionDecl *>(d);
SourceManager & sm = context->getSourceManager();
SourceRange const& r = d->getSourceRange();
SourceLocation const& b = r.getBegin();
if (!sm.isInMainFile(b))
return true; // avoid spamming for headers
if (fd->hasBody()) {
pm.reset(new ParentMap{fd->getBody()});
}
//else { // must be a forward decl of a function. keep quiet
//}
break; }
default:
break;
}
return true;
}
bool VisitStmt(Stmt *s) {
switch (s->getStmtClass()) {
case Stmt::IfStmtClass: {
IfStmt const *iff = static_cast<IfStmt*>(s);
// if it has 'else', return
// if the 'then' is not break/continue/return/..., complain
Stmt const *ifparent = pm->getParent(iff);
// if no "next" inside ifparent, complain
break;
} // case IfStmt
default:
break;
} // switch statement class
}
};
Is this a good idea? Is it guaranteed that the right ParentMap will be
active when I get calls to VisitStmt (i.e. when a statements is
visited, the last function declaration is the function the statement
is in)?
Csaba
--
GCS a+ e++ d- C++ ULS$ L+$ !E- W++ P+++$ w++$ tv+ b++ DI D++ 5++
The Tao of math: The numbers you can count are not the real numbers.
Life is complex, with real and imaginary parts.
"Ok, it boots. Which means it must be bug-free and perfect. " -- Linus Torvalds
"People disagree with me. I just ignore them." -- Linus Torvalds
More information about the cfe-dev
mailing list