I would like to write a clang-tidy
check that adds an lvalue ref qualifier to certain C++ methods. I have managed to detect the methods to fix, but I have troubles finding the right source location to add the qualifier to.
My attempt is this one:
void MyCheck::check(const MatchFinder::MatchResult &Result) {
const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXMethodDecl>("x");
if (RQ_None != MatchedDecl->getRefQualifier()) {
return;
}
diag(MatchedDecl->getBeginLoc(),
"Member Function %0 should have lvalue ref qualifier.")
<< MatchedDecl
<< FixItHint::CreateInsertion(
MatchedDecl->getTypeSpecEndLoc().getLocWithOffset(1), " &");
diag(MatchedDecl->getTypeSpecEndLoc().getLocWithOffset(1),
"Add ref-qualifier for lvalues.", DiagnosticIDs::Note);
}
It works well, if the C++ method that has been found specifies the return value before the method name:
Test& modify1();
is being fixed like this:
Test& modify1() &;
But if the method has a trailing return type, my source location for the insertion is not correct.
auto modify2() -> Test&
is being fixed like this:
auto modify2() -> Test& &;
which has a syntax error.
Instead of getTypeSpecEndLoc().getLocWithOffset(1)
I should use the source code location where ref qualifiers are expected. How to figure out the location from the AST matcher?
As specified in section dcl.fct of the C++ standard, the ref-qualifier goes after the cv-qualifiers:
D1 ( parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifieropt noexcept-specifieropt attribute-specifier-seqopt trailing-return-typeopt
Clang does not record a source location that precisely identifies the
location "after cv-qualifiers", i.e., where the ref-qualifier would go.
The closest it records is the location of the right parenthesis at the
end of the parameter list. This can be retrieved from a
FunctionDecl
by calling getFunctionTypeLoc()
to get a
FunctionTypeLoc
,
and calling getRParenLoc()
on that object.
From there, you have to inspect the tokens at that location to check
for and skip const
and volatile
. See the question
Getting the token sequence from clang AST node
for information about how to retrieve and inspect tokens.