How to rewrite a header file?

Hi everyone,

my tool changes the signatures of some annotated C functions in .c files.

Now I am facing the problem that I have to propaged this changes into
the corresponding

header file.

How can I do this? Can I use something like ASTConsumer/RecursiveAstVisitor?

Any hint and/or idea is welcome. Is there some example code available?

Thanks

Marcel

Hi,

my tool changes the signatures of some annotated C functions in .c files.

Now I am facing the problem that I have to propaged this changes into
the corresponding

header file.

How can I do this? Can I use something like ASTConsumer/RecursiveAstVisitor?

Any hint and/or idea is welcome. Is there some example code available?

Look at clang-tools-extra for examples. Rewriting in header files
happens out of the box, but if you want to check if your location is in
the "main" file or in a header file, you can use the source manager's
isInMainFile() for that purpose. See e.g.
tools/clang/tools/extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp:55
for a place where that happens.

Regards,

Miklos

Hi Miklos,

thanks for your hint. What do you mean by “Rewriting in header files happens out of the box…”?

When I rewrite with my tools some definition in a header file I’ll get an error message from the rewriter:

<<>>

My code snippet looks something like this:

bool TransformFunctionReturnTypeDef(FunctionDecl *funcdecl)
{
if (funcdecl->getPreviousDecl())
{
TypeSourceInfo *TI = funcdecl->getTypeSourceInfo();
TypeLoc TL = TI->getTypeLoc();
FunctionTypeLoc FTL = TL.getAsAdjusted();

clang::SourceLocation l1 = FTL.getLParenLoc();
clang::SourceLocation l2 = FTL.getRParenLoc();

int offset = Lexer::MeasureTokenLength(l1,
TheRewriter.getSourceMgr(),
TheRewriter.getLangOpts());

int offset2 = Lexer::MeasureTokenLength(l2,
TheRewriter.getSourceMgr(),
TheRewriter.getLangOpts());

SourceLocation END1 = l1.getLocWithOffset(offset);
SourceLocation END2 = l2.getLocWithOffset(offset2 - 1);
SourceRange range(END1, END2);
std::stringstream SSBefore;

if (auto typ = dyn_cast_or_null(funcdecl->getReturnType().getTypePtr())) {
SSBefore << “, " << funcdecl->getReturnType().getAsString() << " new_param”;
}
else {
SSBefore << “, " << funcdecl->getReturnType().getAsString() << " *new_param”;
}

TheRewriter.ReplaceText(range, SSBefore.str());
}

return true;
}

Marcel

Hi Marcel,

thanks for your hint. What do you mean by "Rewriting in header files
happens out of the box..."?

When I rewrite with my tools some definition in a header file I'll get
an error message from the rewriter:

<<<INVALID SOURCE LOCATION >>>

My guess is this has little to do with header files. Invalid location
can be also a result of something else. Try to print out the
filename/line/col values for the locations and offsets, hopefully
that'll lead to the place where you first get an invalid location.

Also, as a first iteration try to avoid macros. :slight_smile: Rewriting inside
macros is tricky, but your intention is to just rewrite inside header
files AIUI. In general, it might be a good idea to read the source of
e.g. clang-rename (or some other clang-provided rewriting tool) to see
how rewriting (in header files) works.

Regards,

Miklos