This is an archive of the discontinued LLVM Phabricator instance.

[clang-format] Fix namespace format when the name is a macro expansion
ClosedPublic

Authored by zequanwu on Mar 3 2022, 12:10 PM.

Details

Summary

Originally filed at https://bugs.chromium.org/p/chromium/issues/detail?id=1184570.
Example:

$ cat a.cpp
#define M(x)
namespace M(ns) {
  void test() {}
}

$ clang-format a.cpp
#define M(x)
namespace M(ns) {
  void test() {}
} // namespace )

When the name of a namespace is a macro that takes arguments,

  • It fixed the indentation.
  • It fixed the namespace end comments.

Diff Detail

Event Timeline

zequanwu created this revision.Mar 3 2022, 12:10 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 3 2022, 12:10 PM
zequanwu requested review of this revision.Mar 3 2022, 12:10 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 3 2022, 12:10 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
zequanwu edited the summary of this revision. (Show Details)Mar 3 2022, 12:11 PM
MyDeveloperDay edited projects, added Restricted Project; removed Restricted Project.
Herald added a project: Restricted Project. · View Herald TranscriptMar 3 2022, 2:41 PM
MyDeveloperDay added inline comments.Mar 3 2022, 2:48 PM
clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
76

but its not an anonymous namespace?

would

'''
}// namespace M(x)
'''

be clearer?

86

same here its not A::M is it? at best its A::x but it depends on the macro ? or have I miss understood?

zequanwu updated this revision to Diff 412856.Mar 3 2022, 4:08 PM
zequanwu marked 2 inline comments as done.

Address comment.

clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
86

Yes, you are right. Fixed to include the macro literally.
Ideally, it should expand the macro to get the name or ignore the macro.

Please update the summary, the name is no longer empty. Also, if you can add some info in the summary about how it looked before (copying a part of the Chromium bug report seems enough), it would be awesome.
Otherwise, some small comments only.

clang/lib/Format/NamespaceEndCommentsFixer.cpp
59
60
68

It should be simpler when written as !Tok->isOneOf(...).

curdeius retitled this revision from [clang-format] fix namepsace format when the name is macro expansion to [clang-format] Fix namespace format when the name is a macro expansion.Mar 4 2022, 10:15 AM
curdeius added a reviewer: curdeius.
MyDeveloperDay added inline comments.Mar 4 2022, 10:31 AM
clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
112

Is this 2 bugs in one? I notice you also handling attributes? is this a different bug? (if so it should really be separate (but we can let it slide as long as the tests are thorough)

can you test:

namespace /* comment  */ [[ xxx ]]  /* comment */  A {
int i;
int j;
}  // namespace  A

namespace /* comment  */ [[ xxx ]]   A {
int i;
int j;
}  //  namespace A

namespace /* comment  */ [[ xxx ]]   /* comment */ M(x) {
int i;
int j;
}  // namespace  M(x)

namespace /* comment  */ [[ xxx ]]   /* comment */  A::M(x) {
int i;
int j;
}  // namespace  A::M(x)

namespace /* comment  */ [[ xxx ]]   /* comment */ M(x)  /* comment */ {
int i;
int j;
}  // namespace  M(x)  

namespace /* comment  */ [[ xxx ]]   /* comment */  A::M(x) /* comment */  {
int i;
int j;
}  // namespace  A::M(x)

Its assignment only happens in MacroExpander which is never used

This is something that @klimek was working on.

zequanwu updated this revision to Diff 413109.Mar 4 2022, 12:48 PM
zequanwu marked 4 inline comments as done.

Address comments.

clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
112

Is this 2 bugs in one? I notice you also handling attributes?

No. This tests with attribute is here to test that candidate name doesn't include attributes, but that is unnecessary. Added the 6 tests above for testing that.

zequanwu edited the summary of this revision. (Show Details)Mar 4 2022, 12:49 PM
MyDeveloperDay added inline comments.Mar 4 2022, 12:55 PM
clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
112

Where are you checking the addition of this

if (Tok && Tok->is(tok::l_square)) {
      int NestLevel = 1;
      while (Tok && NestLevel > 0) {
        Tok = Tok->getNextNonComment();
        if (Tok) {
          if (Tok->is(tok::l_square))
            ++NestLevel;
          if (Tok->is(tok::r_square))
            --NestLevel;
        }
      }
      if (Tok)
        Tok = Tok->getNextNonComment();
    }
zequanwu added inline comments.Mar 4 2022, 1:05 PM
clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
112

That part of code skips attribute so that FirstNSName doesn't add attribute string into its name.
In the following test case. it's tested.

namespace /* comment  */ [[ xxx ]]   /* comment */  A::M(x) {
int i;
int j;
}  // namespace  A::M(x)
owenpan added inline comments.Mar 4 2022, 1:54 PM
clang/lib/Format/NamespaceEndCommentsFixer.cpp
45–54

To make the loop simpler and more efficient.

59–60

Move "as a name candidate" to between "namespace" and "until".

owenpan added inline comments.Mar 4 2022, 2:00 PM
clang/lib/Format/NamespaceEndCommentsFixer.cpp
59–60

Move "as a name candidate" to between "namespace" and "until".

Or move it to after "Use", i.e. "Use as a name candidate the string after ...".

zequanwu updated this revision to Diff 413139.Mar 4 2022, 2:12 PM
zequanwu marked 2 inline comments as done.

update.

owenpan accepted this revision.Mar 4 2022, 2:58 PM

LGTM, but please wait for other reviewers in case they have more comments.

This revision is now accepted and ready to land.Mar 4 2022, 2:58 PM
MyDeveloperDay accepted this revision.Mar 4 2022, 3:00 PM
This revision was landed with ongoing or failed builds.Mar 4 2022, 4:01 PM
This revision was automatically updated to reflect the committed changes.