This is an archive of the discontinued LLVM Phabricator instance.

[clang-format] Don't use 'PPIndentWidth' inside multi-line macros
ClosedPublic

Authored by goldstein.w.n on Nov 1 2022, 11:36 AM.

Details

Summary

I.e with:
PPIndentWidth = 1
IndentWidth = 4

#ifdef foo
#define bar() if (A) { B(); } C();
#endif

Assume ColumnLimit Here: |

IndentPPDirectives: None

#ifdef foo
#define bar()               \
    if (A) {                \
        B();                \
    }                       \
    C();                    \
#endif

As opposed to

#ifdef foo
#define bar()               \
  if (A) {                  \
   B();                     \
  }                         \
  C();
#endif

IndentPPDirectives: AfterHash

#ifdef foo
# define bar()              \
    if (A) {                \
        B();                \
    }                       \
    C();                    \
#endif

As opposed to

#ifdef foo
# define bar()              \
  if (A) {                  \
   B();                     \
  }                         \
  C();
#endif

IndentPPDirectives: BeforeHash

#ifdef foo
 #define bar()              \
    if (A) {                \
        B();                \
    }                       \
    C();                    \
#endif

As opposed to

#ifdef foo
 #define bar()              \
  if (A) {                  \
   B();                     \
  }                         \
  C();
#endif

Diff Detail

Event Timeline

goldstein.w.n created this revision.Nov 1 2022, 11:36 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 1 2022, 11:36 AM
goldstein.w.n requested review of this revision.Nov 1 2022, 11:36 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 1 2022, 11:36 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
goldstein.w.n added projects: Restricted Project, Restricted Project.
MyDeveloperDay removed a project: Restricted Project.

This needs a unit test in clang/unittest/Format

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Added unit tests.

Can you fix the format of the summary?

clang/unittests/Format/FormatTest.cpp
5024

Don't add an empty line here.

5044

Do you need it?

5046

Do you need to enclose the macro definition in #ifdef/#endif?

5053–5055

You can delete them.

5065–5067

Delete them or change to multiline format like lines 5048-5052.

5077–5079

Same here.

goldstein.w.n added inline comments.Nov 2 2022, 12:24 PM
clang/unittests/Format/FormatTest.cpp
5024

Will drop for V2.

5044

No, copied along when I was looking for examples of unit-tests with trailing '\'. I'll drop for V2

5046

No, but figured since this change is related to PP indentation the tests should have it. You would prefer I make the test just:

verifyFormat("#define bar() \\\n"
             "    if (A) {  \\\n"
             "        B();  \\\n"
             "    }         \\\n"
             "    C();\n",
             "#define bar() if (A) { B(); } C();\n",
             style);

?

5053–5055

Them being the ifdef/endif? If so will do for V2.

5065–5067

Delete the test of the ifndef/endif? Can do either for V2.

5077–5079

Same question as above, otherwise will do for V2.

Can you fix the format of the summary?

I see the misindentation of the After/Before hash examples. Will fix those for V2.
Anything else?

owenpan added inline comments.Nov 2 2022, 1:13 PM
clang/unittests/Format/FormatTest.cpp
5046

My bad. Please ignore my comment.

5053–5055

Them being lines 5054-5056. (If you mouse over the comment, the lines will be highlighted.)

5065–5067

Actually, delete lines 5066-5068. There are mainly two ways to use verifyFormat: verifyFormat(Expected, Input, ...) and verifyFormat(Input, ...). Here we can use the latter, in which Input is also expected output.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create
  1. Fixed indentation in commit
  2. Fixed format nits in tests
  3. Remove initial code from tests
goldstein.w.n marked an inline comment as done.Nov 2 2022, 2:16 PM

This needs a unit test in clang/unittest/Format

Fixed in V2 I think but not sure as the summary doesn't seem to have changed.

clang/unittests/Format/FormatTest.cpp
5053–5055

Got it. Dropped in V2.

5065–5067

Got it. Dropped in V2.

owenpan added inline comments.Nov 2 2022, 6:22 PM
clang/unittests/Format/FormatTest.cpp
5056–5059

I just noticed that here and below you got an extra IndentWidth than in the summary, so the patch only works for PPDIS_None?

goldstein.w.n added inline comments.Nov 2 2022, 6:49 PM
clang/unittests/Format/FormatTest.cpp
5056–5059

To a degree.

Level is used by both scope depth and PP depth so nested PP directives with before/after will essentially have IndentWidth * (PPLevel + ScopeLevel) as net indentation.

AFAICT UnwrappedLineParser.cpp::parsePPDefine needs to something other than Line->Level with PBBranchLevel + 1.

I started doing that but the diff got a bit bigger given that it needs to get propegated between Wrapper/Unwrapped/Annotated (AFAICT).

Would you prefer its implemented like that?

owenpan edited the summary of this revision. (Show Details)Nov 2 2022, 9:03 PM
owenpan added a reviewer: rymiel.

With ColumnLimit: 16 and IndentPPDirectives: BeforeHash, the format should be:

#ifdef foo
 #define bar() \
     if (A) {  \
         B();  \
     }         \
     C();
#endif

With IndentPPDirectives: AfterHash, it should look like:

#ifdef foo
# define bar() \
     if (A) {  \
         B();  \
     }         \
     C();
#endif
owenpan added inline comments.Nov 2 2022, 10:29 PM
clang/unittests/Format/FormatTest.cpp
5056–5059
goldstein.w.n added inline comments.Nov 3 2022, 2:49 PM
clang/unittests/Format/FormatTest.cpp
5056–5059

Hmm? What is that suppose to link to?

goldstein.w.n added inline comments.Nov 3 2022, 2:50 PM
clang/unittests/Format/FormatTest.cpp
5056–5059

Err, sorry I see now. Got it.

With ColumnLimit: 16 and IndentPPDirectives: BeforeHash, the format should be:

#ifdef foo
 #define bar() \
     if (A) {  \
         B();  \
     }         \
     C();
#endif

With IndentPPDirectives: AfterHash, it should look like:

#ifdef foo
# define bar() \
     if (A) {  \
         B();  \
     }         \
     C();
#endif

Doesn't that add an arbitrary +1 to the begining of the indentation?
Shouldn't it be:

// IndentPPDirectives: AfterHash
#ifdef foo
# define bar() \\
  if (A) {     \\
      B();     \\
  }            \\
  C();
#endif

// IndentPPDirectives: BeforeHash
#ifdef foo
 #define bar() \\
  if (A) {     \\
      B();     \\
  }            \\
  C();
#endif

// IndentPPDirectives: NoneHash
#ifdef foo
#define bar() \\
 if (A) {     \\
     B();     \\
 }            \\
 C();
#endif

Doesn't that add an arbitrary +1 to the begining of the indentation?
Shouldn't it be:

// IndentPPDirectives: AfterHash
#ifdef foo
# define bar() \\
  if (A) {     \\
      B();     \\
  }            \\
  C();
#endif

// IndentPPDirectives: BeforeHash
#ifdef foo
 #define bar() \\
  if (A) {     \\
      B();     \\
  }            \\
  C();
#endif

// IndentPPDirectives: NoneHash
#ifdef foo
#define bar() \\
 if (A) {     \\
     B();     \\
 }            \\
 C();
#endif

Given the settings used in your example:

PPIndentWidth: 1
IndentWidth: 4

IMO the macro body should be shifted to the right by 1 column (except when IndentPPDirectives is set to None). That is, the indent of the macro body relative to the start of define should be the same with any setting of IndentPPDirective.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Make it so that code indentation always starts where 'd' in "define" is.

Doesn't that add an arbitrary +1 to the begining of the indentation?
Shouldn't it be:

// IndentPPDirectives: AfterHash
#ifdef foo
# define bar() \\
  if (A) {     \\
      B();     \\
  }            \\
  C();
#endif

// IndentPPDirectives: BeforeHash
#ifdef foo
 #define bar() \\
  if (A) {     \\
      B();     \\
  }            \\
  C();
#endif

// IndentPPDirectives: NoneHash
#ifdef foo
#define bar() \\
 if (A) {     \\
     B();     \\
 }            \\
 C();
#endif

Given the settings used in your example:

PPIndentWidth: 1
IndentWidth: 4

IMO the macro body should be shifted to the right by 1 column (except when IndentPPDirectives is set to None). That is, the indent of the macro body relative to the start of define should be the same with any setting of IndentPPDirective.

Okay set it up so that where the 'd' in "define" is is always where indentation starts.
Essentially track PPLevel independently of Level and use the two seperarely.

I probably missed a few places / added in a few bad places.

IMO we should find a simpler way to indent bodies of macro definitions that are nested more than one level deep. I prefer we handle that in another patch and only support the examples in the summary for now.

goldstein.w.n added a comment.EditedNov 6 2022, 2:18 PM

IMO we should find a simpler way to indent bodies of macro definitions that are nested more than one level deep. I prefer we handle that in another patch and only support the examples in the summary for now.

I'm not sure what changes to the patch that would imply?
Also want to note, for the unit tests to all pass only 4-places actually need the
PPLevel tracking.
L373
L1286
L1290
L1312

I can drop the others but seemed likely to cause obscure issues later. Do you want me
to drop them?

I can also drop the double-indented tests but seems to me that it would simply be buggy if it overintented the code due to header guards or if the define was placed in code.

Maybe would be cleaner if we made Level a new struct and overloading +/- to check if in PP region to keep track of PP level?

sstwcw added a comment.Nov 6 2022, 5:52 PM

Here is one problem:

clang-format -style='{IndentPPDirectives: BeforeHash, PPIndentWidth: 1, IndentWidth: 4, IndentCaseLabels: true}'

actual:
#define X                                                                      \
 switch (x) {                                                                  \
     case 0:                                                                   \
      break;                                                                   \
     default:                                                                  \
      break;                                                                   \
 }

expected:
#define X                                                                      \
 switch (x) {                                                                  \
     case 0:                                                                   \
         break;                                                                \
     default:                                                                  \
         break;                                                                \
 }

Me guessing what caused the problem. You intend for PPLevel to mean the depth of #if sections. But you accidentally made it change along with Level where you shouldn't, for example in UnwrappedLineParser.cpp: 600.

In addition, I suggest including PPBranchLevel in PPLevel only instead of also in Level.

clang/lib/Format/UnwrappedLineParser.h
47

Please elaborate what preprocessor indent level means.

IMO we should find a simpler way to indent bodies of macro definitions that are nested more than one level deep. I prefer we handle that in another patch and only support the examples in the summary for now.

I'm not sure what changes to the patch that would imply?

I meant only making changes to UnwrappedLineFormatter.cpp.

Also want to note, for the unit tests to all pass only 4-places actually need the
PPLevel tracking.
L373
L1286
L1290
L1312

I think you were referring to UnwrappedLineParser.cpp here. Anyway, I think most of the added tests are incorrect: the first line in a macro body should be indented 3 columns relative to define as explained in D137181#3910566.

One idea I've experimented with is to pass PPBranchLevel from UnwrappedLine to AnnotatedLine and use that in the unwrapped line formatter. It seems very promising.

Here is one problem:

clang-format -style='{IndentPPDirectives: BeforeHash, PPIndentWidth: 1, IndentWidth: 4, IndentCaseLabels: true}'

actual:
#define X                                                                      \
 switch (x) {                                                                  \
     case 0:                                                                   \
      break;                                                                   \
     default:                                                                  \
      break;                                                                   \
 }

expected:
#define X                                                                      \
 switch (x) {                                                                  \
     case 0:                                                                   \
         break;                                                                \
     default:                                                                  \
         break;                                                                \
 }

Actually, the expected should be:

#define X                                                                         \
    switch (x) {                                                                  \
        case 0:                                                                   \
            break;                                                                \
        default:                                                                  \
            break;                                                                \
    }

@goldstein.w.n do you need to modify MacroCallReconstructor.cpp, Macros.h, and MacroCallReconstructorTest.cpp? Leaving them out wouldn't break any existing tests.

Adding PPBranchLevel (or PPLevel in your case) to UnwrappedLine and AnnotatedLine worked for me. I suggest that you leave PPLevel alone in the annotator and don't change it at various places in the parser.

Here is one problem:

clang-format -style='{IndentPPDirectives: BeforeHash, PPIndentWidth: 1, IndentWidth: 4, IndentCaseLabels: true}'

actual:
#define X                                                                      \
 switch (x) {                                                                  \
     case 0:                                                                   \
      break;                                                                   \
     default:                                                                  \
      break;                                                                   \
 }

expected:
#define X                                                                      \
 switch (x) {                                                                  \
     case 0:                                                                   \
         break;                                                                \
     default:                                                                  \
         break;                                                                \
 }

Actually, the expected should be:

#define X                                                                         \
    switch (x) {                                                                  \
        case 0:                                                                   \
            break;                                                                \
        default:                                                                  \
            break;                                                                \
    }

Was able to fix this, will post new code with a test for it.

goldstein.w.n added a comment.EditedNov 7 2022, 9:59 PM

@goldstein.w.n do you need to modify MacroCallReconstructor.cpp, Macros.h, and MacroCallReconstructorTest.cpp? Leaving them out wouldn't break any existing tests.

Adding PPBranchLevel (or PPLevel in your case) to UnwrappedLine and AnnotatedLine worked for me. I suggest that you leave PPLevel alone in the annotator and don't change it at various places in the parser.

Hi, sorry to go mia all day. We can't drop PPLevel from MacroCallReconstructor because we need it for the createUnwrappedLine MacroCallReconstructor.cpp:L66.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Fixed case statement, remove many unnecessary PPLevel changes.

goldstein.w.n added a comment.EditedNov 7 2022, 10:27 PM

Here is one problem:

clang-format -style='{IndentPPDirectives: BeforeHash, PPIndentWidth: 1, IndentWidth: 4, IndentCaseLabels: true}'

actual:
#define X                                                                      \
 switch (x) {                                                                  \
     case 0:                                                                   \
      break;                                                                   \
     default:                                                                  \
      break;                                                                   \
 }

expected:
#define X                                                                      \
 switch (x) {                                                                  \
     case 0:                                                                   \
         break;                                                                \
     default:                                                                  \
         break;                                                                \
 }

Actually, the expected should be:

#define X                                                                         \
    switch (x) {                                                                  \
        case 0:                                                                   \
            break;                                                                \
        default:                                                                  \
            break;                                                                \
    }

Err I'm not sure that's right. I thought we where going for the C-code should start at the column that the 'd' in define is.
So it would be:

#define X       \
 switch (x) {   \
     case 0:    \
         break; \
     default:   \
         break; \
 }

@goldstein.w.n do you need to modify MacroCallReconstructor.cpp, Macros.h, and MacroCallReconstructorTest.cpp? Leaving them out wouldn't break any existing tests.

Hi, sorry to go mia all day. We can't drop PPLevel from MacroCallReconstructor because we need it for the createUnwrappedLine MacroCallReconstructor.cpp:L66.

Why would you need it for createUnwrappedLine? Can you add test cases for the requirement? Removing all the changes to MacroCallReconstructor doesn't fail any existing and new tests.

Err I'm not sure that's right. I thought we where going for the C-code should start at the column that the 'd' in define is.
So it would be:

#define X       \
 switch (x) {   \
     case 0:    \
         break; \
     default:   \
         break; \
 }

That doesn't make sense IMO. Here is an example:

$ cat foo.cpp
#if X
#define FOO \
    if (a)  \
        b;
#endif
$ clang-format -style="{BasedOnStyle: Chromium, IndentWidth: 4}" foo.cpp > out1
$ diff foo.cpp out1
$ clang-format -style="{BasedOnStyle: Chromium, IndentWidth: 4, PPIndentWidth: 1}" foo.cpp > out2

Now what should out2 look like? Well, it should be no different than out1 (and foo.cpp) because IndentPPDirectives is still None by default. However, the current patch outputs the following instead:

#if X
#define FOO \
 if (a)     \
     b;
#endif

So I really think the first line of a macro definition body should be indented IndentWidth - 1 relative to the letter d in define no matter what IndentPPDirectives and PPIndentWidth are set to.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Remove changes to MacroCallReconstructor

@goldstein.w.n do you need to modify MacroCallReconstructor.cpp, Macros.h, and MacroCallReconstructorTest.cpp? Leaving them out wouldn't break any existing tests.

Hi, sorry to go mia all day. We can't drop PPLevel from MacroCallReconstructor because we need it for the createUnwrappedLine MacroCallReconstructor.cpp:L66.

Why would you need it for createUnwrappedLine? Can you add test cases for the requirement? Removing all the changes to MacroCallReconstructor doesn't fail any existing and new tests.

Okay fair enough. Dropped.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Make code inside macros start at common IndentWidth - 1.

goldstein.w.n added a comment.EditedNov 8 2022, 1:25 AM

Err I'm not sure that's right. I thought we where going for the C-code should start at the column that the 'd' in define is.
So it would be:

#define X       \
 switch (x) {   \
     case 0:    \
         break; \
     default:   \
         break; \
 }

That doesn't make sense IMO. Here is an example:

$ cat foo.cpp
#if X
#define FOO \
    if (a)  \
        b;
#endif
$ clang-format -style="{BasedOnStyle: Chromium, IndentWidth: 4}" foo.cpp > out1
$ diff foo.cpp out1
$ clang-format -style="{BasedOnStyle: Chromium, IndentWidth: 4, PPIndentWidth: 1}" foo.cpp > out2

Now what should out2 look like? Well, it should be no different than out1 (and foo.cpp) because IndentPPDirectives is still None by default. However, the current patch outputs the following instead:

#if X
#define FOO \
 if (a)     \
     b;
#endif

So I really think the first line of a macro definition body should be indented IndentWidth - 1 relative to the letter d in define no matter what IndentPPDirectives and PPIndentWidth are set to.

Fair enough. Adding something like:

if (PPIndentWidth < Style.IndentWidth)
  Indent += Style.IndentWidth - PPIndentWidth;

Works for that and all existing tests pass + added a few tests with varied indentwidth / ppindentwidth.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Elaborate in comments for PPLevel

clang/lib/Format/UnwrappedLineParser.h
47

Done.

You can still simply the changes to UnwrappedLineParser.cpp a lot. In fact, instead of adjusting PPLevel at various places, you only need to set it once when InMacroBody is set.

clang/lib/Format/UnwrappedLineFormatter.cpp
88–89

Please run git-clang-format.

clang/lib/Format/UnwrappedLineParser.cpp
113

Do you need to add PreviousLinePPLevel here? If yes, can you add test cases for it? Otherwise, you don't need to make any changes to ScopedMacroState.

clang/lib/Format/UnwrappedLineParser.h
66

You need to initialize PPLevel in the constructor. FWIW I'd use unsigned to be consistent with Level above.

goldstein.w.n added inline comments.Nov 8 2022, 9:53 PM
clang/lib/Format/UnwrappedLineFormatter.cpp
88–89

Will do for next submissions (thought arc did that automatically on precommit).

clang/lib/Format/UnwrappedLineParser.cpp
113

It's needed.

Without:

Expected equality of these values:
  Expected.str()
    Which is: "#ifndef foo\n#define foo\nif (emacs) {\n#ifdef is\n #define lit           \\\n     if (af) {         \\\n         return duh(); \\\n     }\n#endif\n}\n#endif"
  format(test::messUp(Code), ObjCStyle)
    Which is: "#ifndef foo\n#define foo\nif (emacs) {\n#ifdef is\n #define lit        \\\n  if (af) {         \\\n      return duh(); \\\n  }\n#endif\n}\n#endif"
With diff:
@@ -3,8 +3,8 @@
 if (emacs) {
 #ifdef is
- #define lit           \\
-     if (af) {         \\
-         return duh(); \\
-     }
+ #define lit        \\
+  if (af) {         \\
+      return duh(); \\
+  }
 #endif
 }
clang/lib/Format/UnwrappedLineParser.h
66

Will initialize. It's int because we do a less than zero check in the Formatter.

You can still simply the changes to UnwrappedLineParser.cpp a lot. In fact, instead of adjusting PPLevel at various places, you only need to set it once when InMacroBody is set.

I don't think thats right, it needs to stay updated with the true macro depth (even though we only use PPLevel for formatting InMacroBody lines).

You can still simply the changes to UnwrappedLineParser.cpp a lot. In fact, instead of adjusting PPLevel at various places, you only need to set it once when InMacroBody is set.

I don't think thats right, it needs to stay updated with the true macro depth (even though we only use PPLevel for formatting InMacroBody lines).

My experiment from a few days ago was successful and also passes all the new tests you just added here. If your experience told you otherwise, then perhaps there are some missing test cases.

goldstein.w.n added a comment.EditedNov 8 2022, 10:36 PM

You can still simply the changes to UnwrappedLineParser.cpp a lot. In fact, instead of adjusting PPLevel at various places, you only need to set it once when InMacroBody is set.

I don't think thats right, it needs to stay updated with the true macro depth (even though we only use PPLevel for formatting InMacroBody lines).

I think we can remove the places I set InitialPPLevel and OldPPLevel but anything else I remove causes at least one test to fail.

My experiment from a few days ago was successful and also passes all the new tests you just added here. If your experience told you otherwise, then perhaps there are some missing test cases.

What did you do? Just set PPLevel = PPBranchLevel?

I think we can remove the places I set InitialPPLevel and OldPPLevel but anything else I remove causes at least one test to fail.

What did you do? Just set PPLevel = PPBranchLevel?

Yes, if there is a header guard. Otherwise, set PPLevel to PPBranchLevel + 1.

owenpan added inline comments.Nov 8 2022, 10:58 PM
clang/lib/Format/UnwrappedLineParser.cpp
113

I don't have to touch ScopedMacroState. Perhaps it has something to do with the way you set/adjust/use PPLevel.

goldstein.w.n added a comment.EditedNov 8 2022, 11:09 PM

I think we can remove the places I set InitialPPLevel and OldPPLevel but anything else I remove causes at least one test to fail.

What did you do? Just set PPLevel = PPBranchLevel?

Yes, if there is a header guard. Otherwise, set PPLevel to PPBranchLevel + 1.

That fails alot of the tests for me.

I have a patch attached (applyable on this) maybe you did something different?

The best I'm able to do while this passing all the tests is remove the use setting InitialPPLevel and OldPPLevel. Worth noting in the last few days I've added several new tests (for inside of a scope + case statement + header guard cases and those seem to be the ones failing so it may just be the old tests where insufficient).

owenpan added inline comments.Nov 8 2022, 11:20 PM
clang/lib/Format/UnwrappedLineParser.h
66

It's int because we do a less than zero check in the Formatter.

If you set PPLevel to PPBranchLevel when there is no header guard, and to PPBranchLevel + 1otherwise, PPLevel can never be negative.

Yes, if there is a header guard. Otherwise, set PPLevel to PPBranchLevel + 1.

That fails alot of the tests for me.

maybe you did something different?

Here is what I did:

$ git diff UnwrappedLineParser.cpp
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 25d9018fa109..ab3b9c53ee54 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -197,6 +197,7 @@ public:
     PreBlockLine = std::move(Parser.Line);
     Parser.Line = std::make_unique<UnwrappedLine>();
     Parser.Line->Level = PreBlockLine->Level;
+    Parser.Line->PPLevel = PreBlockLine->PPLevel;
     Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
     Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
   }
@@ -1274,6 +1275,10 @@ void UnwrappedLineParser::parsePPDefine() {
   addUnwrappedLine();
   ++Line->Level;
   Line->InMacroBody = true;
+  if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) {
+    Line->PPLevel =
+        IncludeGuard == IG_Defined ? PPBranchLevel : PPBranchLevel + 1;
+  }
 
   // Errors during a preprocessor directive can only affect the layout of the
   // preprocessor directive, and thus we ignore them. An alternative approach
  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Remove many unnecessary PPLevel changes.

Yes, if there is a header guard. Otherwise, set PPLevel to PPBranchLevel + 1.

That fails alot of the tests for me.

maybe you did something different?

Here is what I did:

$ git diff UnwrappedLineParser.cpp
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 25d9018fa109..ab3b9c53ee54 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -197,6 +197,7 @@ public:
     PreBlockLine = std::move(Parser.Line);
     Parser.Line = std::make_unique<UnwrappedLine>();
     Parser.Line->Level = PreBlockLine->Level;
+    Parser.Line->PPLevel = PreBlockLine->PPLevel;
     Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
     Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
   }
@@ -1274,6 +1275,10 @@ void UnwrappedLineParser::parsePPDefine() {
   addUnwrappedLine();
   ++Line->Level;
   Line->InMacroBody = true;
+  if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) {
+    Line->PPLevel =
+        IncludeGuard == IG_Defined ? PPBranchLevel : PPBranchLevel + 1;
+  }
 
   // Errors during a preprocessor directive can only affect the layout of the
   // preprocessor directive, and thus we ignore them. An alternative approach

You're right this works (but off by one). Updated patch.

maybe you did something different?

Here is what I did:

$ git diff UnwrappedLineParser.cpp
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 25d9018fa109..ab3b9c53ee54 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -197,6 +197,7 @@ public:
     PreBlockLine = std::move(Parser.Line);
     Parser.Line = std::make_unique<UnwrappedLine>();
     Parser.Line->Level = PreBlockLine->Level;
+    Parser.Line->PPLevel = PreBlockLine->PPLevel;
     Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
     Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
   }
@@ -1274,6 +1275,10 @@ void UnwrappedLineParser::parsePPDefine() {
   addUnwrappedLine();
   ++Line->Level;
   Line->InMacroBody = true;
+  if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) {
+    Line->PPLevel =
+        IncludeGuard == IG_Defined ? PPBranchLevel : PPBranchLevel + 1;
+  }
 
   // Errors during a preprocessor directive can only affect the layout of the
   // preprocessor directive, and thus we ignore them. An alternative approach

You're right this works (but off by one). Updated patch.

It was not off by 1, or else it wouldn't have worked. Below is how I defined PPLevel:

$ git diff UnwrappedLineParser.h
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index b9b106bcc89a..a234f6852e0c 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -43,6 +43,9 @@ struct UnwrappedLine {
 
   /// The indent level of the \c UnwrappedLine.
   unsigned Level;
+  /// The \c PPBranchLevel (adjusted for header guards) of the macro definition
+  /// this line belongs to.
+  unsigned PPLevel;
 
   /// Whether this \c UnwrappedLine is part of a preprocessor directive.
   bool InPPDirective;
@@ -358,7 +361,7 @@ struct UnwrappedLineNode {
 };
 
 inline UnwrappedLine::UnwrappedLine()
-    : Level(0), InPPDirective(false), InPragmaDirective(false),
+    : Level(0), PPLevel(0), InPPDirective(false), InPragmaDirective(false),
       InMacroBody(false), MustBeDeclaration(false),
       MatchingOpeningBlockLineIndex(kInvalidIndex) {}

Conceptually, I think it's more accurate to make PPLevel to mean the PP branching level of the #define line, not the first line of the macro body. IMO it may simplify the changes you made to the formatter.

BTW you still need to change PPLevel to unsigned and initialize it as requested in D137181#inline-1328385.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Make PPLevel unsigned + Initialize in constructor.

maybe you did something different?

Here is what I did:

$ git diff UnwrappedLineParser.cpp
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 25d9018fa109..ab3b9c53ee54 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -197,6 +197,7 @@ public:
     PreBlockLine = std::move(Parser.Line);
     Parser.Line = std::make_unique<UnwrappedLine>();
     Parser.Line->Level = PreBlockLine->Level;
+    Parser.Line->PPLevel = PreBlockLine->PPLevel;
     Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
     Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
   }
@@ -1274,6 +1275,10 @@ void UnwrappedLineParser::parsePPDefine() {
   addUnwrappedLine();
   ++Line->Level;
   Line->InMacroBody = true;
+  if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) {
+    Line->PPLevel =
+        IncludeGuard == IG_Defined ? PPBranchLevel : PPBranchLevel + 1;
+  }
 
   // Errors during a preprocessor directive can only affect the layout of the
   // preprocessor directive, and thus we ignore them. An alternative approach

You're right this works (but off by one). Updated patch.

It was not off by 1, or else it wouldn't have worked. Below is how I defined PPLevel:

$ git diff UnwrappedLineParser.h
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index b9b106bcc89a..a234f6852e0c 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -43,6 +43,9 @@ struct UnwrappedLine {
 
   /// The indent level of the \c UnwrappedLine.
   unsigned Level;
+  /// The \c PPBranchLevel (adjusted for header guards) of the macro definition
+  /// this line belongs to.
+  unsigned PPLevel;
 
   /// Whether this \c UnwrappedLine is part of a preprocessor directive.
   bool InPPDirective;
@@ -358,7 +361,7 @@ struct UnwrappedLineNode {
 };
 
 inline UnwrappedLine::UnwrappedLine()
-    : Level(0), InPPDirective(false), InPragmaDirective(false),
+    : Level(0), PPLevel(0), InPPDirective(false), InPragmaDirective(false),
       InMacroBody(false), MustBeDeclaration(false),
       MatchingOpeningBlockLineIndex(kInvalidIndex) {}

Conceptually, I think it's more accurate to make PPLevel to mean the PP branching level of the #define line, not the first line of the macro body. IMO it may simplify the changes you made to the formatter.

Hmm? Not sure what you mean.

BTW you still need to change PPLevel to unsigned and initialize it as requested in D137181#inline-1328385.

Fixed.

clang/lib/Format/UnwrappedLineParser.h
66

Sorry didnt see your reply. Fixed

Below is how I defined PPLevel:

$ git diff UnwrappedLineParser.h
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index b9b106bcc89a..a234f6852e0c 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -43,6 +43,9 @@ struct UnwrappedLine {
 
   /// The indent level of the \c UnwrappedLine.
   unsigned Level;
+  /// The \c PPBranchLevel (adjusted for header guards) of the macro definition
+  /// this line belongs to.
+  unsigned PPLevel;
 
   /// Whether this \c UnwrappedLine is part of a preprocessor directive.
   bool InPPDirective;
@@ -358,7 +361,7 @@ struct UnwrappedLineNode {
 };
 
 inline UnwrappedLine::UnwrappedLine()
-    : Level(0), InPPDirective(false), InPragmaDirective(false),
+    : Level(0), PPLevel(0), InPPDirective(false), InPragmaDirective(false),
       InMacroBody(false), MustBeDeclaration(false),
       MatchingOpeningBlockLineIndex(kInvalidIndex) {}

Conceptually, I think it's more accurate to make PPLevel to mean the PP branching level of the #define line, not the first line of the macro body. IMO it may simplify the changes you made to the formatter.

Hmm? Not sure what you mean.

Does the comments above unsigned PPLevel; in the above git diff output help? Anyway, you already addressed my comment by decreasing PPLevel by 1, so it's ok now.

Below is how I defined PPLevel:

$ git diff UnwrappedLineParser.h
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index b9b106bcc89a..a234f6852e0c 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -43,6 +43,9 @@ struct UnwrappedLine {
 
   /// The indent level of the \c UnwrappedLine.
   unsigned Level;
+  /// The \c PPBranchLevel (adjusted for header guards) of the macro definition
+  /// this line belongs to.
+  unsigned PPLevel;
 
   /// Whether this \c UnwrappedLine is part of a preprocessor directive.
   bool InPPDirective;
@@ -358,7 +361,7 @@ struct UnwrappedLineNode {
 };
 
 inline UnwrappedLine::UnwrappedLine()
-    : Level(0), InPPDirective(false), InPragmaDirective(false),
+    : Level(0), PPLevel(0), InPPDirective(false), InPragmaDirective(false),
       InMacroBody(false), MustBeDeclaration(false),
       MatchingOpeningBlockLineIndex(kInvalidIndex) {}

Conceptually, I think it's more accurate to make PPLevel to mean the PP branching level of the #define line, not the first line of the macro body. IMO it may simplify the changes you made to the formatter.

Hmm? Not sure what you mean.

Does the comments above unsigned PPLevel; in the above git diff output help? Anyway, you already addressed my comment by decreasing PPLevel by 1, so it's ok now.

Got it. Is the patch okay?

I think we are close to the finishing line. Can you revisit the change to the formatter and clean it up? For example, casting PPLevel to unsigned is redundant now. IMO you can simply the change too.

clang/lib/Format/UnwrappedLineFormatter.cpp
63–67

You don't need to add this condition.

Can you make TokenAnnotator::printDebugInfo print PPLevel?

Since you changed the rules for indentation in UnwrappedLineFormatter, do you also need to change UnwrappedLineParser::mightFitOnOneLine?

clang/lib/Format/UnwrappedLineFormatter.cpp
69–73

What is this test for?

clang-format -style='{IndentPPDirective: BeforeHash, PPIndentWidth: 2, IndentWidth: 4, ColumnLimit: 40}'

actual:
#define X                              \
  {                                    \
    x;                                 \
    x;                                 \
  }

expected:
#define X                              \
    {                                  \
        x;                             \
        x;                             \
    }
73

What is this for?

clang-format -style='{IndentPPDirective: BeforeHash, PPIndentWidth: 4, IndentWidth: 1, ColumnLimit: 40}'

actual:
#if X
    #define X                          \
        {                              \
         x;                            \
         x;                            \
        }
#endif

expected:
#if X
    #define X                          \
     {                                 \
      x;                               \
      x;                               \
     }
#endif
  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Cleanup logic in Formatter

I think we are close to the finishing line. Can you revisit the change to the formatter and clean it up? For example, casting PPLevel to unsigned is redundant now. IMO you can simply the change too.

Cleaned up the logic a bit.

goldstein.w.n marked 2 inline comments as done.Nov 13 2022, 9:55 PM
goldstein.w.n added inline comments.
clang/lib/Format/UnwrappedLineFormatter.cpp
69–73

You're right, unneeded. Fixed and added test for it.

73

You're right, unneeded. Fixed and added test for it.

Can you make TokenAnnotator::printDebugInfo print PPLevel?

@goldstein.w.n can you add it as follows?

$ git diff TokenAnnotator.cpp
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 75570552146c..536472e9d136 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5093,8 +5093,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
 }
 
 void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
-  llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", T=" << Line.Type
-               << ", C=" << Line.IsContinuation << "):\n";
+  llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel
+               << ", T=" << Line.Type << ", C=" << Line.IsContinuation
+               << "):\n";
   const FormatToken *Tok = Line.First;
   while (Tok) {
     llvm::errs() << " M=" << Tok->MustBreakBefore

Since you changed the rules for indentation in UnwrappedLineFormatter, do you also need to change UnwrappedLineParser::mightFitOnOneLine?

mightFitOnOneLine is not called on PPDirective lines, but it's a good idea to add an assertion.

clang/lib/Format/UnwrappedLineParser.cpp
836–838

We don't call mightFitOnOneLine on PPDirective lines.

goldstein.w.n marked 2 inline comments as done.
  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Add PPLevel to debug printout + assert not in macro in mightFitOnOneLine

Can you make TokenAnnotator::printDebugInfo print PPLevel?

@goldstein.w.n can you add it as follows?

$ git diff TokenAnnotator.cpp
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 75570552146c..536472e9d136 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5093,8 +5093,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
 }
 
 void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
-  llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", T=" << Line.Type
-               << ", C=" << Line.IsContinuation << "):\n";
+  llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel
+               << ", T=" << Line.Type << ", C=" << Line.IsContinuation
+               << "):\n";
   const FormatToken *Tok = Line.First;
   while (Tok) {
     llvm::errs() << " M=" << Tok->MustBreakBefore

Done.

Since you changed the rules for indentation in UnwrappedLineFormatter, do you also need to change UnwrappedLineParser::mightFitOnOneLine?

mightFitOnOneLine is not called on PPDirective lines, but it's a good idea to add an assertion.

Added assert.

Please mark review comments as done if you have addressed them. Can you also clean up the test cases, removing overlapping/redundant ones, making sure a test case doesn't end with a newline (e.g., line 5380), etc?

clang/lib/Format/UnwrappedLineFormatter.cpp
63–67

Please ignore my comment above.

69–74

To make it simpler and clearer.

clang/lib/Format/UnwrappedLineParser.cpp
1280

We don't need the if statement anymore. Actually, it's better to always set PPLevel for InMacroBody lines.

clang/lib/Format/UnwrappedLineParser.h
47–65

We probably don't need the (outdated) examples as we can print PPLevel in TokenAnnotator::printDebugInfo now.

clang/unittests/Format/FormatTest.cpp
5382–5384

Please delete.

owenpan added inline comments.Nov 17 2022, 9:20 PM
clang/lib/Format/UnwrappedLineParser.cpp
838

Shouldn't it be assert(!Line.InMacroBody && !InPPDirective) instead? You can also assert Line.PPLevel == 0.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Fix some nits.

clang/lib/Format/UnwrappedLineFormatter.cpp
69–74

Done.

clang/lib/Format/UnwrappedLineParser.cpp
838

I guess the goal was to assert condition where PPLevel would be used to calculate if a line might find (if both InMacroBody and InPPDirective) are true. But your assert should also works fine so fixed.

1280

Fixed.

clang/unittests/Format/FormatTest.cpp
5382–5384

Fixed.

Please mark review comments as done if you have addressed them. Can you also clean up the test cases, removing overlapping/redundant ones, making sure a test case doesn't end with a newline (e.g., line 5380), etc?

Regarding newlines. I have new line before changing the style. Otherwise done. (let me know if you want me to remove those).

Regarding removing redundant test cases. I think I've had each of them fail independently at some point (although many when I was doing the previous PPLevel tracking) so I wouldn't call any of them truly redundant.
I could remove either the PPDIS_BeforeHash or PPDIS_AfterHash though as the they really no independent logic in this commit.

Thoughts?

goldstein.w.n marked 22 inline comments as done.Nov 17 2022, 10:35 PM

Please mark review comments as done if you have addressed them. Can you also clean up the test cases, removing overlapping/redundant ones, making sure a test case doesn't end with a newline (e.g., line 5380), etc?

Regarding newlines. I have new line before changing the style. Otherwise done. (let me know if you want me to remove those).

Sorry, it's line 5379 and several other places that have an ending newline. (Just search for \n",.) You only need to remove them in the new test cases. We can fix the existing ones in a separate NFC patch.

Regarding removing redundant test cases. I think I've had each of them fail independently at some point (although many when I was doing the previous PPLevel tracking) so I wouldn't call any of them truly redundant.

I know, but IMO some of the failures (e.g. the switch statement) during development shouldn't automatically go in. This file already has a humongous size. Maybe do the best you can here.

I could remove either the PPDIS_BeforeHash or PPDIS_AfterHash though as the they really no independent logic in this commit.

Yes, please. Or better yet, alternate a little bit between the two.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Cleanup tests file

Please mark review comments as done if you have addressed them. Can you also clean up the test cases, removing overlapping/redundant ones, making sure a test case doesn't end with a newline (e.g., line 5380), etc?

Regarding newlines. I have new line before changing the style. Otherwise done. (let me know if you want me to remove those).

Sorry, it's line 5379 and several other places that have an ending newline. (Just search for \n",.) You only need to remove them in the new test cases. We can fix the existing ones in a separate NFC patch.

Done. Sorry I had thought you mean the newline in the file between the test cases.

Regarding removing redundant test cases. I think I've had each of them fail independently at some point (although many when I was doing the previous PPLevel tracking) so I wouldn't call any of them truly redundant.

I know, but IMO some of the failures (e.g. the switch statement) during development shouldn't automatically go in. This file already has a humongous size. Maybe do the best you can here.

I could remove either the PPDIS_BeforeHash or PPDIS_AfterHash though as the they really no independent logic in this commit.

Yes, please. Or better yet, alternate a little bit between the two.

Done.

I could remove either the PPDIS_BeforeHash or PPDIS_AfterHash though as the they really no independent logic in this commit.

Yes, please. Or better yet, alternate a little bit between the two.

My bad. I meant splitting the test cases between the two. Can you regroup them (lines 5137-5258) as follows?

style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash;
style.IndentWidth = 4;
style.PPIndentWidth = 1;
verifyFormat("#ifdef foo\n"
             "# define bar() \\\n"
             "     if (A) {  \\\n"
             "         B();  \\\n"
             "     }         \\\n"
             "     C();\n"
             "#endif",
             style);
verifyFormat("#if abc\n"
             "# ifdef foo\n"
             "#  define bar()    \\\n"
             "      if (A) {     \\\n"
             "          if (B) { \\\n"
             "              C(); \\\n"
             "          }        \\\n"
             "      }            \\\n"
             "      D();\n"
             "# endif\n"
             "#endif",
             style);
verifyFormat("#ifndef foo\n"
             "#define foo\n"
             "if (emacs) {\n"
             "#ifdef is\n"
             "# define lit           \\\n"
             "     if (af) {         \\\n"
             "         return duh(); \\\n"
             "     }\n"
             "#endif\n"
             "}\n"
             "#endif",
             style);
verifyFormat("#define X  \\\n"
             "    {      \\\n"
             "        x; \\\n"
             "        x; \\\n"
             "    }",
             style);

style.IndentWidth = 8;
style.PPIndentWidth = 2;
verifyFormat("#ifdef foo\n"
             "#  define bar()        \\\n"
             "          if (A) {     \\\n"
             "                  B(); \\\n"
             "          }            \\\n"
             "          C();\n"
             "#endif",
             style);

style.IndentWidth = 1;
style.PPIndentWidth = 4;
verifyFormat("#define X \\\n"
             " {        \\\n"
             "  x;      \\\n"
             "  x;      \\\n"
             " }",
             style);

style.IndentPPDirectives = FormatStyle::PPDIS_BeforeHash;
style.IndentWidth = 4;
style.PPIndentWidth = 1;
verifyFormat("if (emacs) {\n"
             "#ifdef is\n"
             " #define lit           \\\n"
             "     if (af) {         \\\n"
             "         return duh(); \\\n"
             "     }\n"
             "#endif\n"
             "}",
             style);
verifyFormat("#if abc\n"
             " #ifdef foo\n"
             "  #define bar() \\\n"
             "      if (A) {  \\\n"
             "          B();  \\\n"
             "      }         \\\n"
             "      C();\n"
             " #endif\n"
             "#endif",
             style);
verifyFormat("#if 1\n"
             " #define X  \\\n"
             "     {      \\\n"
             "         x; \\\n"
             "         x; \\\n"
             "     }\n"
             "#endif",
             style);

style.PPIndentWidth = 2;
verifyFormat("#ifdef foo\n"
             "  #define bar() \\\n"
             "      if (A) {  \\\n"
             "          B();  \\\n"
             "      }         \\\n"
             "      C();\n"
             "#endif",
             style);

style.IndentWidth = 1;
style.PPIndentWidth = 4;
verifyFormat("#if 1\n"
             "    #define X \\\n"
             "     {        \\\n"
             "      x;      \\\n"
             "      x;      \\\n"
             "     }\n"
             "#endif",
             style);
clang/lib/Format/UnwrappedLineParser.cpp
838
error: use of undeclared identifier 'InPPDirective'
  assert(!Line.InMacroBody && !InPPDirective);
                               ^

Also, can you break it into two assertions as suggested so that we know which one failed even without a debugger?

1281

In case PPLevel is negative.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

De-interleave test cases.
Cleanup asserts.

goldstein.w.n marked an inline comment as done.Nov 18 2022, 8:33 PM

I could remove either the PPDIS_BeforeHash or PPDIS_AfterHash though as the they really no independent logic in this commit.

Yes, please. Or better yet, alternate a little bit between the two.

My bad. I meant splitting the test cases between the two. Can you regroup them (lines 5137-5258) as follows?

style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash;
style.IndentWidth = 4;
style.PPIndentWidth = 1;
verifyFormat("#ifdef foo\n"
             "# define bar() \\\n"
             "     if (A) {  \\\n"
             "         B();  \\\n"
             "     }         \\\n"
             "     C();\n"
             "#endif",
             style);
verifyFormat("#if abc\n"
             "# ifdef foo\n"
             "#  define bar()    \\\n"
             "      if (A) {     \\\n"
             "          if (B) { \\\n"
             "              C(); \\\n"
             "          }        \\\n"
             "      }            \\\n"
             "      D();\n"
             "# endif\n"
             "#endif",
             style);
verifyFormat("#ifndef foo\n"
             "#define foo\n"
             "if (emacs) {\n"
             "#ifdef is\n"
             "# define lit           \\\n"
             "     if (af) {         \\\n"
             "         return duh(); \\\n"
             "     }\n"
             "#endif\n"
             "}\n"
             "#endif",
             style);
verifyFormat("#define X  \\\n"
             "    {      \\\n"
             "        x; \\\n"
             "        x; \\\n"
             "    }",
             style);

style.IndentWidth = 8;
style.PPIndentWidth = 2;
verifyFormat("#ifdef foo\n"
             "#  define bar()        \\\n"
             "          if (A) {     \\\n"
             "                  B(); \\\n"
             "          }            \\\n"
             "          C();\n"
             "#endif",
             style);

style.IndentWidth = 1;
style.PPIndentWidth = 4;
verifyFormat("#define X \\\n"
             " {        \\\n"
             "  x;      \\\n"
             "  x;      \\\n"
             " }",
             style);

style.IndentPPDirectives = FormatStyle::PPDIS_BeforeHash;
style.IndentWidth = 4;
style.PPIndentWidth = 1;
verifyFormat("if (emacs) {\n"
             "#ifdef is\n"
             " #define lit           \\\n"
             "     if (af) {         \\\n"
             "         return duh(); \\\n"
             "     }\n"
             "#endif\n"
             "}",
             style);
verifyFormat("#if abc\n"
             " #ifdef foo\n"
             "  #define bar() \\\n"
             "      if (A) {  \\\n"
             "          B();  \\\n"
             "      }         \\\n"
             "      C();\n"
             " #endif\n"
             "#endif",
             style);
verifyFormat("#if 1\n"
             " #define X  \\\n"
             "     {      \\\n"
             "         x; \\\n"
             "         x; \\\n"
             "     }\n"
             "#endif",
             style);

style.PPIndentWidth = 2;
verifyFormat("#ifdef foo\n"
             "  #define bar() \\\n"
             "      if (A) {  \\\n"
             "          B();  \\\n"
             "      }         \\\n"
             "      C();\n"
             "#endif",
             style);

style.IndentWidth = 1;
style.PPIndentWidth = 4;
verifyFormat("#if 1\n"
             "    #define X \\\n"
             "     {        \\\n"
             "      x;      \\\n"
             "      x;      \\\n"
             "     }\n"
             "#endif",
             style);

Yes done.

clang/lib/Format/UnwrappedLineParser.cpp
1281

Done.

goldstein.w.n marked 2 inline comments as done.Nov 18 2022, 8:35 PM
goldstein.w.n added inline comments.
clang/lib/Format/UnwrappedLineParser.cpp
838

Fixed. Sorry. Had only been rebuilting formattests. Figured everything else must have a dep.

This revision is now accepted and ready to land.Nov 18 2022, 10:37 PM
goldstein.w.n marked an inline comment as done.Nov 18 2022, 10:52 PM

LGTM

Awesome! Thanks for sticking with it through all these revisions :)

Anything left for me todo (can't imagine I have push access).

Anything left for me todo (can't imagine I have push access).

See here. We will need your name and email.

  1. Updating D137181: [clang-format] Don't use 'PPIndentWidth' inside multi-line macros #
  2. Enter a brief description of the changes included in this update.
  3. The first line is used as subject, next lines as comment. #
  4. If you intended to create a new revision, use:
  5. $ arc diff --create

Add tag to commit message

Anything left for me todo (can't imagine I have push access).

See here. We will need your name and email.

Added [clang-format] tag to commit message.

Name: Noah Goldstein
email: goldstein.w.n@gmail.com

but that is already in the commit info.

This revision was landed with ongoing or failed builds.Nov 19 2022, 11:54 PM
This revision was automatically updated to reflect the committed changes.