Add a clang-tidy check for using func__/FUNCTION__ inside lambdas. This evaluates to the string operator(), which is almost never useful and almost certainly not what the author intended.
Details
Diff Detail
Event Timeline
- What about __PRETTY_FUNCTION__ ?
- Consider following generic error handling macro:
(ThrowException is some template function)
#undef STR #define STR(a) XSTR(a) #define ThrowExceptionHelper(CLASS, fmt, ...) ThrowException<CLASS>(__FILE__ ":" STR(__LINE__) ": %s: " fmt, __PRETTY_FUNCTION__, ##__VA_ARGS__) #endif
Which is called like if(somethig) ThrowException(std::exception, "%s", "bar");
Even though the function name may be useless, file/line info is still there and is(?) correct.
Perhaps there should not be a warning in such a case?
__PRETTY_FUNCTION__ is a little more useful, it at least tells you which function the lambda is defined in:
#include <stdio.h> int main() { auto f = [] { printf("__func__: %s\n", __func__); printf("__FUNCTION__: %s\n", __FUNCTION__); printf("__PRETTY_FUNCTION__: %s\n", __PRETTY_FUNCTION__); }; f(); }
results in the output:
__func__: operator() __FUNCTION__: operator() __PRETTY_FUNCTION__: auto main()::(anonymous class)::operator()() const
I think __PRETTY_FUNCTION__ inside a lambda is useful enough not to warn about.
- Consider following generic error handling macro:
(ThrowException is some template function)
#undef STR #define STR(a) XSTR(a) #define ThrowExceptionHelper(CLASS, fmt, ...) ThrowException<CLASS>(__FILE__ ":" STR(__LINE__) ": %s: " fmt, __PRETTY_FUNCTION__, ##__VA_ARGS__) #endifWhich is called like if(somethig) ThrowException(std::exception, "%s", "bar");
Even though the function name may be useless, file/line info is still there and is(?) correct.
Perhaps there should not be a warning in such a case?
That's a good point. I'll look into suppressing the warning if we're in a macro definition where __FILE__ and __LINE__ are both used. It may suppress some warnings that would be legitimate (such as if __FILE__/__LINE__ are written but not actually output anywhere), but in those cases it's probably impossible to figure out the author's intention.
Then that should be checked by the test
- Consider following generic error handling macro:
(ThrowException is some template function)
That's a good point. I'll look into suppressing the warning if we're in a macro definition where __FILE__ and __LINE__ are both used. It may suppress some warnings that would be legitimate (such as if __FILE__/__LINE__ are written but not actually output anywhere), but in those cases it's probably impossible to figure out the author's intention.
Makes sense
Addressed the following review comments:
- Added a test to make sure we don't warn on PRETTY_FUNCTION
- Suppressed warnings when in a macro that also uses FILE and LINE
- Updated docs/ReleaseNotes.rst.
docs/ReleaseNotes.rst | ||
---|---|---|
83 ↗ | (On Diff #100149) | Please highlight func and FUNCTION with ``. |
docs/ReleaseNotes.rst | ||
---|---|---|
83 ↗ | (On Diff #100149) | I meant double `, not single . |
docs/ReleaseNotes.rst | ||
---|---|---|
83 ↗ | (On Diff #100149) | Sorry, I had Markdown on my brain. |
clang-tidy/misc/LambdaFunctionNameCheck.cpp | ||
---|---|---|
62–63 | llvm::make_unique<MacroExpansionsWithFileAndLine>(...) | |
68–69 | nit: I'd use the early return style here. | |
74–75 | I'm afraid this can become extremely slow on large files with boilerplate/generated code. Since the code is just looking for exact matches (and not any overlapping ranges, for example), we could replace the vector with a (hash?) map to limit the worst case complexity. |
llvm::make_unique<MacroExpansionsWithFileAndLine>(...)