This is an archive of the discontinued LLVM Phabricator instance.

[clang-format] [PR45338] AllowShortIfStatementsOnASingleLine: WithoutElse follows the documented behaviour
Needs ReviewPublic

Authored by Bouska on Jun 14 2020, 9:32 AM.

Details

Summary

According to clang-format documentation, the value WithoutElse of the option AllowShortIfStatementsOnASingleLine is expected to "put short ifs on the same line only if the else is not a compound statement". However, with the current code, and the option AllowShortBlocksOnASingleLine: Always, a short if block is always put on a single line whatever the following else statement is compound or not, and a short if statement is never put on a single line whatever the following else statement is compound or not. With this patch, the formatting is as documented.

Fixes #45338

If this patch fixes the simple example given on the documentation, the formatting or more complex code with else if and nested if (or loops) is not what I would expect from this option. Here are some formatted examples (with the options {BasedOnStyle: google, BreakBeforeBraces: Allman, AllowShortBlocksOnASingleLine: Always, AllowShortIfStatementsOnASingleLine: WithoutElse} and proposed patch):

int main()
{
  if (true) { function(); }

  if (true) function();

  if (true) { function(); }
  else
    function();

  if (true)
  {
    function();
  }
  else
  {
    function();
  }

  if (true) function();
  else
    function();

  if (true)
    function();
  else
  {
    function();
  }

  if (true) function();
  else if (false)
    function();
  else
  {
    function();
  }

  if (true) { function(); }
  else if (false)
    function();
  else
    function();

  if (true)
    function();
  else if (false)
  {
    function();
  }
  else
    function();

  if (true) function();
  else if (true)
    if (false) function();

  if (true) function();
  else if (true)
    if (false) { function(); }

  if (true) { function(); }
  else if (true)
    if (false) function();

  if (true) { function(); }
  else if (true)
    if (false) { function(); }
}

The first behaviour I would expect is that a short if statement is either never put in a short line if there is more than one else or only put on a single line when none of the else statement are compound. The second behaviour I would expect is that a nested if (or loop) is considered as a compound statement and prevents the is statement to be put in a single line.

Diff Detail

Event Timeline

Bouska created this revision.Jun 14 2020, 9:32 AM
clang/unittests/Format/FormatTest.cpp
518

So I'd only expect this to get merged if it didn't have an else

Bouska marked an inline comment as done.Jun 14 2020, 11:45 AM
Bouska added inline comments.
clang/unittests/Format/FormatTest.cpp
518

If it was just up to me, that would also be the behaviour I would expect but it doesn't match the current documentation... (and for Always, I would also expect the else if to be merged, but that's another subject)

This comment was removed by MyDeveloperDay.

Are all the cases from the summary contained in the unit tests?

Are all the cases from the summary contained in the unit tests?

No, not all. Here is the detail:

int main()
{
  if (true) { function(); }  // Yes, FormatTests.cpp line 603

  if (true) function();  // Yes, FormatTests.cpp line 494

  if (true) { function(); }  // Yes, FormatTests.cpp line 661
  else
    function();

  if (true)  // Yes similar, FormatTests.cpp line 654
  {
    function();
  }
  else
  {
    function();
  }

  if (true) function();  // Yes, FormatTests.cpp line 514
  else
    function();

  if (true)  // Yes similar, FormatTests.cpp line 508 
    function();
  else
  {
    function();
  }

  if (true) function();  // No
  else if (false)
    function();
  else
  {
    function();
  }

  if (true) { function(); }  // No
  else if (false)
    function();
  else
    function();

  if (true)  // No
    function();
  else if (false)
  {
    function();
  }
  else
    function();

  if (true) function();  // No
  else if (true)
    if (false) function();

  if (true) function();  // No
  else if (true)
    if (false) { function(); }

  if (true) { function(); }  // No
  else if (true)
    if (false) function();

  if (true) { function(); }  // No
  else if (true)
    if (false) { function(); }
}

I think we should add all the other cases to ensure we don't break them down the road

Wasn't this fixed/superseded by https://reviews.llvm.org/rG8d93d7ffedebc5f18dee22ba954d38a1d2d0affa? And so, the bug report might be closed (the old Always option should be avoided as it's a misnomer).