This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy: modernize] modernize-redundant-void-arg crashes when a function body is in a macro
ClosedPublic

Authored by IdrissRio on Jul 25 2018, 8:09 AM.

Details

Summary

Hello, i would like to suggest a fix for one of the checks in clang-tidy. The bug was reported in https://bugs.llvm.org/show_bug.cgi?id=28406 where you can find more information.

With the following code:

#define BODY {}
void foo(void) {
  [] () BODY;
}

we have got this crash:

clang-tidy -checks='-*,modernize-redundant-void-arg' t.cc -- -std=c++11
clang-tidy: tools/clang/include/clang/Basic/SourceManager.h:414: const clang::SrcMgr::ExpansionInfo &clang::SrcMgr::SLocEntry::getExpansion() const: Assertion `isExpansion() && "Not a macro expansion SLocEntry!

Hope this can help.
I also have add a new test.

Diff Detail

Repository
rL LLVM

Event Timeline

IdrissRio created this revision.Jul 25 2018, 8:09 AM
IdrissRio edited the summary of this revision. (Show Details)Jul 25 2018, 8:12 AM
IdrissRio edited the summary of this revision. (Show Details)
IdrissRio edited the summary of this revision. (Show Details)Jul 25 2018, 1:16 PM
alexfh requested changes to this revision.Jul 26 2018, 7:06 AM

Thank you for working on this!

clang-tidy/modernize/RedundantVoidArgCheck.cpp
241 ↗(On Diff #157272)

Let's pull Lambda->getBody()->getLocStart() to a variable to avoid repetition.

242–244 ↗(On Diff #157272)

The fix looks limited to the specific test case. Let's try other cases (see the comment below).

test/clang-tidy/modernize-redundant-void-arg.cpp
454 ↗(On Diff #157272)

I'd like to see more tests here with different macro-related cases. These come to mind, but if you come up with more distinct cases, that would be even better:

#define LAMBDA1 [](void){}
(void)LAMBDA1;
#define LAMBDA2 [](void)BODY
(void)LAMBDA2;
#define LAMBDA3(captures, args, body) [captures](args){body}
(void)LAMBDA3(=, void, BODY);
#define LAMBDA4(captures, args, body) captures args body
(void)LAMBDA4([], (void), BODY);
#define LAMBDAS1 \
  (void)LAMBDA1; \
  (void)LAMBDA2; \
  (void)LAMBDA3(=, void, BODY); \
  (void)LAMBDA4([], (void), BODY)

LAMBDAS1;
#define WRAP(...) __VA_ARGS__
WRAP((void)WRAP(WRAP(LAMBDA4(WRAP([]), WRAP((void)), WRAP(BODY)))));
(void)WRAP([](void){});
This revision now requires changes to proceed.Jul 26 2018, 7:06 AM
IdrissRio updated this revision to Diff 159179.EditedAug 4 2018, 4:47 AM

Thank you @alexfh. You where right. This update is more general. And I also have modified the removeVoidArgumentTokens. This because if we consider the following case:

WRAP((void)WRAP(WRAP(LAMBDA3(WRAP([]), WRAP((void)), WRAP(BODY)))));

We find the correct range, and the DeclText variable inside the function is WRAP((void)).
In the while loop we fine the first occurrence of l_paren and so State = SawLeftParent, and when we find the second occurrence of l_paren this is lost because the case SawLeftParent
doesn't handle a second occurrence of l_paren.

Hope this can help.

alexfh added inline comments.Aug 9 2018, 3:34 PM
clang-tidy/modernize/RedundantVoidArgCheck.cpp
246–247 ↗(On Diff #159179)

Will this code also work in the non-macro case?

IdrissRio updated this revision to Diff 160039.Aug 9 2018, 5:45 PM

Yes it works also for the non macro. It is actually more general.
This update have passed all the tests.

alexfh accepted this revision.Aug 10 2018, 5:55 AM

LG with a couple of nits. Do you need someone to commit the patch for you?

clang-tidy/modernize/RedundantVoidArgCheck.cpp
241 ↗(On Diff #160039)

s/auto /SourceManager */

242 ↗(On Diff #160039)

Use the actual type name here as well.

This revision is now accepted and ready to land.Aug 10 2018, 5:55 AM
This revision was automatically updated to reflect the committed changes.

I've fixed the comments and committed the patch myself. Hope that's fine by you.