Skip to content

[clang-format] Add an option to control indentation of export { ... } #110381

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ C++23 Feature Support

- Extend lifetime of temporaries in mem-default-init for P2718R0. Clang now fully
supports `P2718R0 Lifetime extension in range-based for loops <https://wg21.link/P2718R0>`_.

- ``__cpp_explicit_this_parameter`` is now defined. (#GH82780)

C++20 Feature Support
Expand Down Expand Up @@ -715,7 +715,7 @@ Improvements to Clang's diagnostics

- Clang now diagnoses dangling references for C++20's parenthesized aggregate initialization (#101957).

- Fixed a bug where Clang would not emit ``-Wunused-private-field`` warnings when an unrelated class
- Fixed a bug where Clang would not emit ``-Wunused-private-field`` warnings when an unrelated class
defined a defaulted comparison operator (#GH116270).

.. code-block:: c++
Expand Down Expand Up @@ -935,7 +935,7 @@ Bug Fixes to C++ Support
- Fixed an assertion failure caused by invalid default argument substitutions in non-defining
friend declarations. (#GH113324)
- Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659)
- Fixed a parser crash when using pack indexing as a nested name specifier. (#GH119072)
- Fixed a parser crash when using pack indexing as a nested name specifier. (#GH119072)
- Fixed a null pointer dereference issue when heuristically computing ``sizeof...(pack)`` expressions. (#GH81436)
- Fixed an assertion failure caused by mangled names with invalid identifiers. (#GH112205)
- Fixed an incorrect lambda scope of generic lambdas that caused Clang to crash when computing potential lambda
Expand Down Expand Up @@ -1211,6 +1211,17 @@ clang-format
------------

- Adds ``BreakBinaryOperations`` option.
- Adds ``TemplateNames`` option.
- Adds ``AlignFunctionDeclarations`` option to ``AlignConsecutiveDeclarations``.
- Adds ``IndentOnly`` suboption to ``ReflowComments`` to fix the indentation of
multi-line comments without touching their contents, renames ``false`` to
``Never``, and ``true`` to ``Always``.
- Adds ``RemoveEmptyLinesInUnwrappedLines`` option.
- Adds ``KeepFormFeed`` option and set it to ``true`` for ``GNU`` style.
- Adds ``AllowShortNamespacesOnASingleLine`` option.
- Adds ``VariableTemplates`` option.
- Adds support for bash globstar in ``.clang-format-ignore``.
- Adds ``WrapNamespaceBodyWithEmptyLines`` option.
- Adds the ``ExportBlockIndentation`` option.

libclang
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1551,7 +1551,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
LLVMStyle.ExperimentalAutoDetectBinPacking = false;
LLVMStyle.ExportBlockIndentation = false;
LLVMStyle.ExportBlockIndentation = true;
LLVMStyle.FixNamespaceComments = true;
LLVMStyle.ForEachMacros.push_back("foreach");
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Format/TokenAnnotator.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ class AnnotatedLine {
startsWith(tok::kw_export, tok::kw_namespace);
}

/// \c true if this line starts a C++ export block.
bool startsWithExportBlock() const {
return startsWith(tok::kw_export, tok::l_brace);
}

FormatToken *getFirstNonComment() const {
assert(First);
return First->is(tok::comment) ? First->getNextNonComment() : First;
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/Format/UnwrappedLineFormatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,9 @@ class LineJoiner {

// Try to merge a control statement block with left brace unwrapped.
if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
TT_ForEachMacro)) {
(FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
TT_ForEachMacro) ||
TheLine->startsWithExportBlock())) {
return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never
? tryMergeSimpleBlock(I, E, Limit)
: 0;
Expand Down Expand Up @@ -832,7 +833,8 @@ class LineJoiner {
if (IsCtrlStmt(Line) ||
Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
tok::kw___finally, tok::r_brace,
Keywords.kw___except)) {
Keywords.kw___except) ||
Line.startsWithExportBlock()) {
if (IsSplitBlock)
return 0;
// Don't merge when we can't except the case when
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3118,7 +3118,7 @@ void UnwrappedLineParser::parseNamespaceOrExportBlock(unsigned AddLevels) {
if (ManageWhitesmithsBraces)
++Line->Level;

// Munch the semicolon after a namespace. This is more common than one would
// Munch the semicolon after the block. This is more common than one would
// think. Putting the semicolon into its own line is very ugly.
parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true,
/*KeepBraces=*/true, /*IfKind=*/nullptr, ManageWhitesmithsBraces);
Expand Down Expand Up @@ -3167,7 +3167,8 @@ void UnwrappedLineParser::parseNamespace() {
}

void UnwrappedLineParser::parseCXXExportBlock() {
parseNamespaceOrExportBlock(Style.ExportBlockIndentation ? 1 : 0);
parseNamespaceOrExportBlock(/*AddLevels=*/Style.ExportBlockIndentation ? 1
: 0);
}

void UnwrappedLineParser::parseNew() {
Expand Down
95 changes: 94 additions & 1 deletion clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9095,6 +9095,96 @@ TEST_F(FormatTest, ExportBlockIndentation) {
Style);
}

TEST_F(FormatTest, ShortExportBlocks) {
FormatStyle Style = getLLVMStyleWithColumns(80);
Style.ExportBlockIndentation = false;

Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
verifyFormat("export {\n"
"}",
Style);

verifyFormat("export {\n"
"int x;\n"
"}",
Style);

verifyFormat("export {\n"
"int x;\n"
"}",
"export\n"
"{\n"
"int x;\n"
"}",
Style);

verifyFormat("export {\n"
"}",
"export {}", Style);

verifyFormat("export {\n"
"int x;\n"
"}",
"export { int x; }", Style);

Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always;
verifyFormat("export {}",
"export {\n"
"}",
Style);

verifyFormat("export { int x; }",
"export {\n"
"int x;\n"
"}",
Style);

verifyFormat("export { int x; }",
"export\n"
"{\n"
"int x;\n"
"}",
Style);

verifyFormat("export {}",
"export {\n"
"}",
Style);

verifyFormat("export { int x; }",
"export {\n"
"int x;\n"
"}",
Style);

Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
verifyFormat("export {}",
"export {\n"
"}",
Style);

verifyFormat("export {\n"
"int x;\n"
"}",
Style);

verifyFormat("export {\n"
"int x;\n"
"}",
"export\n"
"{\n"
"int x;\n"
"}",
Style);

verifyFormat("export {}", Style);

verifyFormat("export {\n"
"int x;\n"
"}",
"export { int x; }", Style);
}

TEST_F(FormatTest, FormatsBuilderPattern) {
verifyFormat("return llvm::StringSwitch<Reference::Kind>(name)\n"
" .StartsWith(\".eh_frame_hdr\", ORDER_EH_FRAMEHDR)\n"
Expand Down Expand Up @@ -26675,7 +26765,10 @@ TEST_F(FormatTest, Cpp20ModulesSupport) {
" int foo;\n"
"};",
Style);
verifyFormat("export { int foo; };", Style);
verifyFormat("export {\n"
" int foo;\n"
"};",
Style);
verifyFormat("export export char const *hello() { return \"hello\"; }");

verifyFormat("import bar;", Style);
Expand Down
Loading