llvm / llvm/llvm-project

[BUG] ClangFormat behaves strangely if it believes a code block is inactive

Open
#163,394 1 comment 0 reactions 0 assignees View on GitHub
clang-format
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

```c
#if 0

struct my_struct {
int a: 1;
int long_c: 1;
int b;
};

int * a ;

char* foo( ) {
int b = 4 * 9;
}

#define MACRO( ) "blabla"

//comment
#define LONG_LONG_LONG_MACRO( ) "blabla"

#endif
```

Practically almost nothing gets formatted, the only things that get formatted are the 2 macros, which by the way are formatted incorrectly since they have been aligned even though they shouldn't be, as the [`AlignConsecutiveMacros: Consecutive`](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignconsecutivemacros) option should only align them if they are consecutive
```c
#if 0

struct my_struct {
int a: 1;
int long_c: 1;
int b;
};

int * a ;

char* foo( ) {
int b = 4 * 9;
}

#define MACRO() "blabla"

//comment
#define LONG_LONG_LONG_MACRO() "blabla"

#endif
```

The same behavior also occurs if I change the condition from `#if 0` to `#if 0 == MY_CONDITION`
```c
#if 0 == MY_CONDITION

struct my_struct {
int a: 1;
int long_c: 1;
int b;
};

int * a ;

char* foo( ) {
int b = 4 * 9;
}

#define MACRO() "blabla"

//comment
#define LONG_LONG_LONG_MACRO() "blabla"

#endif
```

By enabling the `#if 1` block or strangely by inverting the condition to `#if MY_CONDITION == 0`, or by using the parentheses like `#if (0 == MY_CONDITION)` or `#if (0)` the code gets formatted correctly
```c
#if MY_CONDITION == 0 // Same behaviour with #if 1, #if (0 == MY_CONDITION) or #if (0)

struct my_struct
{
int a : 1;
int long_c : 1;
int b;
};

int *a;

char *foo()
{
int b = 4 * 9;
}

#define MACRO() "blabla"

// comment
#define LONG_LONG_LONG_MACRO() "blabla"

#endif
```

My `.clang-format` file:
```yaml
BreakBeforeBraces: Allman # Allman indentation style
SortIncludes: false # Avoid sorting `#include` directives alphabetically
ColumnLimit: 100 # Max 100 characters per line
UseTab: Never # Use spaces instead tabulation
IndentWidth: 4 # Use 4 spaces for indentations
IndentCaseLabels: true # Use indentation on switch-case labels

AlignConsecutiveMacros: Consecutive # Align consecutive `#define` values
AlignConsecutiveAssignments: Consecutive # Align consecutive assignment values
AlignConsecutiveBitFields: Consecutive # Align consecutive bit-field values

AllowShortFunctionsOnASingleLine: None # Avoid single line function: `int f() { return 0; }`
AllowShortIfStatementsOnASingleLine: Never # Avoid single line: `if (a) return;`

SeparateDefinitionBlocks: Always # Add empty line between one definition and the next

PenaltyBreakAssignment: 21 # Prefer starting rvalue of assignment on same line
PenaltyReturnTypeOnItsOwnLine: 100 # Keeps return type and function name on same line

QualifierAlignment: Custom # Enforce qualifier order
QualifierOrder: [static, inline, const, volatile, type]

KeepEmptyLines: # Empty lines options:
AtStartOfFile: false # No empty lines at start of file
AtEndOfFile: false # No empty lines at end of file
AtStartOfBlock: false # No empty lines before open curly brace

LineEnding: LF # Use `\n` character for new lines instead of `\r\n`

InsertBraces: true # Add {} after `if`, `else`, `for`, `do`, and `while`
InsertNewlineAtEOF: true # Add blank line at EOF for C standard compliance

```

Contributor guide

Open the contributing guide

Research direction

Reproduce the issue with the provided C snippets, .clang-format settings, and clang-format entry point, comparing inactive preprocessor branches and macro alignment. Trace how #if conditions are classified and formatted; done when code in inactive branches is formatted consistently and AlignConsecutiveMacros respects non-consecutive definitions.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.