[clang-tidy] Adding a new use nodiscard checker (help needed)

I’m trying to write a “use [[nodiscard]]” clang-tidy checker/fix-it to advise when a function might benefit from having [[nodiscard]] added

Mostly this is working working except I’m finding the wrong location for the place to put the [[nodiscard]] for functions which have const,inline or virtual kewords infront of the return type.


test.cxx:18:5: warning: function ’ empty ’ should be made [[nodiscard]] [modernize-use-nodiscard]
bool empty() const
test.cxx:26:5: warning: function ’ empty’ should be made [[nodiscard]] [modernize-use-nodiscard]
bool empty(const A &val) const
test.cxx:50:11: warning: function ’ empty’ should be made [[nodiscard]] [modernize-use-nodiscard]
const bool empty() const
test.cxx:55:18: warning: function ’ empty ’ should be made [[nodiscard]] [modernize-use-nodiscard]
inline const bool empty() const

And some compilers don’t like the [[nodiscard] being placed in between those keywords and the return type (preferring them to be at the front of the function)

I’m currently using (following a series of trail and errors) to find the location just before the return type


// This function could be marked [[nodiscard]]
“function %0 should be marked [[nodiscard]]”)
<< MatchedDecl
<< FixItHint::CreateInsertion(
"[[nodiscard]] ");

Does anyone know how I should correctly identify the position in front of all the keywords(virtual,inline,const)?

Especially in the case where the return type is on a different source code line

const bool full()

Many thanks in advance, feel free to point out any other “errors of my ways” as this is my first ever checker.


a current copy of the current checker code is presented here for completeness

Here are the locations you can get for FunctionDecls:


See also if you have not already:

Future Developments in clang-query | Steveire's Blog

If there isn't a location in that output for what you need, then you are going to have to check the tokens yourself. Many existing clang tidy checks do things like this due to lack of location for a particular need.



Thanks for the pointers… this led me to look a little deeper at some of the other checkers

looks like ConstReturnTypeCheck uses getInnerLocStart() to locate the return type

Substituting this in seems to find the correct location, but I suspect this doesn’t work well for the training return type

auto retLoc = MatchedDecl->getInnerLocStart();

// This function could be marked [[nodiscard]]
diag(retLoc, “function %0 should be marked [[nodiscard]]”)
<< MatchedDecl << FixItHint::CreateInsertion(retLoc, "[[nodiscard]] ");