[cfe-dev] Repeated clang-format'ting keeps changing code / use of clang-format in CI

Nico Weber via cfe-dev cfe-dev at lists.llvm.org
Mon Jul 29 06:16:23 PDT 2019


Thanks!

Here's a (not minimal) reduction of the first issue; it looks like the
other issues are basically the same thing:

$ cat fmt.c
void cdataSectionTok()
{
  switch (1) {
#define LEAD_CASE(n) \
  case BT_LEAD ## n: \
    break
  LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
#undef LEAD_CASE
  default:
    break;
  }
}

$ out/gn/bin/clang-format fmt.c
void cdataSectionTok() {
  switch (1) {
#define LEAD_CASE(n)
    \
  case BT_LEAD##n:
    \
    break
    LEAD_CASE(2)
    LEAD_CASE(3) LEAD_CASE(4)
#undef LEAD_CASE
        default : break;
  }
}

As you can see by the weird "default : break" at the end, clang-format gets
confused about the whole switch statement. It looks like the macros confuse
it. Just adding semicolons after it is sufficient to unconfuse it:

$ cat fmt.c
void cdataSectionTok()
{
  switch (1) {
#define LEAD_CASE(n) \
  case BT_LEAD ## n: \
    break
  LEAD_CASE(2); LEAD_CASE(3); LEAD_CASE(4);
#undef LEAD_CASE
  default:
    break;
  }
}

$ out/gn/bin/clang-format fmt.c
void cdataSectionTok() {
  switch (1) {
#define LEAD_CASE(n)
    \
  case BT_LEAD##n:
    \
    break
    LEAD_CASE(2);
    LEAD_CASE(3);
    LEAD_CASE(4);
#undef LEAD_CASE
  default:
    break;
  }
}

If you're able to change expat's source, this might be a good approach.

Else, you can explicitly tell clang-format the name of macros that should
be handled as statements in your .clang-format file like so:

StatementMacros: ['LEAD_CASE']

That helps with LEAD_CASE. (clang-format should still converge within one
round, but it's going to converge to something bad without either of the
two things I suggest, so it wouldn't help you much).

Like Raphaƫl's mail says, XCS is slightly different because it's not a
statement. clang-format has special logic for formatting sequences of
string literals, and that doesn't fire if each literal is surrounded by a
macro.

You can fix this by doing `XCS("foo" "bar")` (with a linebreak in between
foo and bar) instead of `XCS("foo") XCS("bar")`. Semantically they do the
same thing as far as I can tell, but clang-format does much better with the
first form. Having done this transformation locally, this is arguably
easier to read for humans too.

There isn't a .clang-format setting for this case as far as I know.

(Again, clang-format should reach a fixed point in one hop, but again the
one hop gives you pretty bad formatting so fixing that bug wouldn't help
you all that much.)

With these two changes, clang-format does reach an end state in one step,
and its output (for the two cases I looked at) looks good too.

Hope this helps!

On Fri, Jul 26, 2019 at 5:03 PM Sebastian Pipping <sebastian at pipping.org>
wrote:

> Hi Nico,
>
>
> that's great to hear.  I have attached a script to reproduce the issue
> from public code of libexpat 2.2.7 as well as the second iteration diff
> I get from clang-format version 10.0.0
> (/var/tmp/portage/sys-devel/clang-10.0.0.9999/work/x/y/clang-10.0.0.9999
> c0048be7ff340ebba3092e95d82147bc9928b909) of Gentoo.
>
> Best
>
>
>
> Sebastian
>
>
> On 26.07.19 22:07, Nico Weber wrote:
> > clang-cl is supposed to reach a fixpoint in one iteration. If it
> > doesn't, that's a bug. If you can, please post a reduced repro case :)
> >
> > On Thu, Jul 25, 2019 at 5:38 PM Sebastian Pipping via cfe-dev
> > <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
> >
> >     Hi!
> >
> >
> >     I'm trying to integrate clang-format version 9 with CI in a way that
> the
> >     CI run only passes if applying clang-format yields the exact same
> >     code, i.e. "git diff --exit-code" returns 0.  The idea is that every
> >     pull request would only pass if clang-format
> >
> >     When trying to put that approach to action with libexpat [1]
> >     I noticed that multiple runs to clang-format do not seem to produce
> the
> >     same code, at least not with the two version of Clang 9 that I tested
> >     [2], and at least not with libexpat code.
> >
> >     I wonder if that's a known problem, if it's fixed in later versions
> >     of clang-format, if you are aware of workarounds, or if I just need
> >     to say goodbye to combining clang-format and CI for stable style
> >     checking.
> >
> >     Thanks in advance!
> >
> >     Best
> >
> >
> >
> >     Sebastian
> >
> >
> >     [1] https://github.com/libexpat/libexpat/pull/293
> >     [2] 9.0.0.9999 commit 28c954cf961a846789a972a8ed179b7108244ae7
> >     _______________________________________________
> >     cfe-dev mailing list
> >     cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
> >     https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20190729/aafc4ac0/attachment.html>


More information about the cfe-dev mailing list