WhyIsItReal
WhyIsItReal

Reputation: 81

Unable to disable extern indentation with clang-format

I'm not sure if this is a limitation or bug with clang-format (built from source, clang-format version 12.0.0 ([email protected]:llvm/llvm-project.git d4ce062340064c3f73b8f6136c7350a5abe83cac)), but I am unable to disable indentation after extern "C" {.

My current .clang-format:

Language: Cpp
Standard: Latest

UseTab: Never
IndentWidth: 4
AccessModifierOffset: -2
SpaceBeforeParens: Never
ColumnLimit: 80
SpacesBeforeTrailingComments: 1
BreakBeforeBraces: Allman

FixNamespaceComments: true
SortIncludes: true
SortUsingDeclarations: true
IncludeBlocks: Regroup

IndentPPDirectives: AfterHash
IndentCaseLabels: true
IndentExternBlock: NoIndent
NamespaceIndentation: All

AlignTrailingComments: true
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignConsecutiveBitFields: true
AlignConsecutiveMacros: true
AlignAfterOpenBracket: AlwaysBreak

AllowShortFunctionsOnASingleLine: None
AllowShortBlocksOnASingleLine: Never
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortLambdasOnASingleLine: None
AlwaysBreakTemplateDeclarations: Yes

BinPackArguments: false
BinPackParameters: false
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
PenaltyBreakBeforeFirstCallParameter: 500 # basically always break

# Note: must have my custom build (https://github.com/jasperswallen/llvm-project/tree/pointeralignment-right) to properly enable these options
BreakBeforeConceptDeclarations: true
PointerAlignment: Right

This example file is the "formatted" result:

#ifdef __cplusplus
extern "C"
{
#endif

    void example(void);

#ifdef __cplusplus
}
#endif

but I want something like:

#ifdef __cplusplus
extern "C"
{
#endif

void example(void);

#ifdef __cplusplus
}
#endif

It seems like IndentExternBlock: NoIndent should be the correct option to force this, but it's still indenting even with that set.

Is it possible that BreakBeforeBraces: Allman is overriding this setting? I assumed that IndentExternBlock would override braces unless set to AfterExternBlock.

Upvotes: 4

Views: 1401

Answers (1)

puchu
puchu

Reputation: 3652

This is a bug 37272, but there is just a little chance that it will be fixed because this option (IndentExternBlock) was forced by expand preset function. Please review the following problematic commit.

We can see that llvm developers broke config inheritance and nobody cares about a year. It means that we have to fix config inheritance in a way that won't depend on llvm developers. Please review the following solution:

scripts/clang/config-format/config-source.yml

Language: Cpp
BreakBeforeBraces: Allman

scripts/clang/config-format/config-updates.yml

BraceWrapping:
  AfterExternBlock: false
BreakBeforeBraces: Custom
IndentExternBlock: false

scripts/clang/config-format/update.sh

#!/bin/bash
set -e

DIR=$(dirname "${BASH_SOURCE[0]}")
cd "$DIR"

SOURCE="config-source.yml"
UPDATES="config-updates.yml"
DESTINATION="../../../.clang-format"

echo "# This file has been auto generated, please don't edit directly." \
  > "$DESTINATION"

SOURCE_STYLE=$(yq -cs ".[0]" < "$SOURCE")

clang-format -style="$SOURCE_STYLE" --dump-config | \
  yq -sy ".[0] * .[1]" - "$UPDATES" >> "$DESTINATION"

Please install yq. After running ./scripts/clang/config-format/update.sh you will receive proper .clang-config for your requirements.

Upvotes: 3

Related Questions