This is an archive of the discontinued LLVM Phabricator instance.

[clang-format] Don’t propagate AvoidBinPacking into argument subexpressions
ClosedPublic

Authored by jtbandes on Apr 25 2017, 12:50 AM.

Details

Reviewers
djasper
bkramer
Summary

This is an attempt to fix the issue described in my recent email: http://lists.llvm.org/pipermail/cfe-dev/2017-April/053632.html

After digging in for a while, I learned that:

  • the spurious line breaks were occurring inside the condition Current.is(TT_BinaryOperator) && Current.CanBreakBefore && State.Stack.back().BreakBeforeParameter.
  • BreakBeforeParameter was being set to true because AvoidBinPacking was true.
  • AvoidBinPacking was true because it propagated all the way along the stack starting from the ( "scope opener".

Given the above, it seemed to make sense to reset AvoidBinPacking to false when propagating it into a subexpression.

👋 hello @djasper — you seem to be the most prolific clang-formatter — please feel free to tear this apart 😅

Event Timeline

jtbandes created this revision.Apr 25 2017, 12:50 AM

Not exactly sure who is the right person for this.

djasper edited edge metadata.Apr 26 2017, 11:06 AM

What happens if the function call where this happens actually does not have multiple parameters but one parameter with many operands, e.g. changing your test case to:

arg3____________________________ + is + quite + long + so + it
    + f(arguments << of << its << subexpressions << lengthy << as << they
                  << may << or__ << may)
lib/Format/ContinuationIndenter.cpp
924

I think you cannot get here if .size() is 0 as this is iterating over the elements.

925

LLVM coding style doesn't use braces for single-statement-ifs

unittests/Format/FormatTest.cpp
2596

Is this important?

2597

Does this bug only happen when breaking before operators? If not can you add a test case with None?

2599

This is not tested/changed at all, I think.

2600

Don't use raw strings to be more consistent with the rest. If we want, we should eventually convert all of the tests in one go.

Also, try to come up with a small reduced test case. Here you are actually testing much more than you want to test. Also, you set the ColumnLimit of Style in order to force earlier linebreaks.

Thanks for the feedback, I'll work on making those changes.

What happens if the function call where this happens actually does not have multiple parameters but one parameter with many operands, e.g. changing your test case to:

arg3____________________________ + is + quite + long + so + it
    + f(arguments << of << its << subexpressions << lengthy << as << they
                  << may << or__ << may)

I don't think this is relevant to what I am trying to fix. The issue being fixed is specifically with multiple arguments: I don't want BinPackArguments=false to affect bin-packing of an individual argument. For completeness, though, I can include a test case with one argument.

lib/Format/ContinuationIndenter.cpp
924

Good point, thanks.

unittests/Format/FormatTest.cpp
2596

Not really. I can remove it.

jtbandes added inline comments.Apr 26 2017, 12:02 PM
lib/Format/ContinuationIndenter.cpp
924

Actually, I can probably just use *I > prec::Comma.

My point is though that even with only one argument, the BinPackArguments setting might lead to this bug. If not, that's good :).

jtbandes added inline comments.Apr 26 2017, 1:23 PM
unittests/Format/FormatTest.cpp
2597

Yeah it is only when breaking before operators, because the condition which causes mustBreak to be true includes Current.CanBreakBefore.

2599

That's a good point. I had this because my test code is a function call at the top level, which is treated as a signature rather than a call. I will wrap it in another block and remove the BinPackParameters setting.

jtbandes updated this revision to Diff 96815.Apr 26 2017, 1:49 PM
jtbandes marked 6 inline comments as done.

Updates from review

@djasper how does this look?

I could try to simplify the examples further, but I feel it's important to have calls with many subexpressions to exercise this behavior properly. FWIW, my real-world use case is with << appearing as an output stream operator inside a macro invocation.

Friendly ping :) happy to make more changes if needed. Thanks again for your time.

djasper accepted this revision.May 8 2017, 8:21 AM

Submitted as r302427.

This revision is now accepted and ready to land.May 8 2017, 8:21 AM
djasper closed this revision.May 8 2017, 8:21 AM