Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
10 changes: 10 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7503,6 +7503,16 @@ the configuration (without a prefix: ``Auto``).
``SpacesInParensOptions`` to ``true`` except for ``InCStyleCasts`` and
``InEmptyParentheses``.

.. _SpacesInSplicers:

**SpacesInSplicers** (``Boolean``) :versionbadge:`clang-format 23` :ref:`¶ <SpacesInSplicers>`
If ``true``, spaces will be inserted after ``[:`` and before ``:]``.

.. code-block:: c++

true: false:
[: ^^int :] i; vs. [:^^int:] i;

.. _SpacesInSquareBrackets:

**SpacesInSquareBrackets** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <SpacesInSquareBrackets>`
Expand Down
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ clang-format
- Extend ``BreakBinaryOperations`` to accept a structured configuration with
per-operator break rules and minimum chain length gating via ``PerOperator``.
- Add ``AllowShortRecordOnASingleLine`` option and set it to ``EmptyAndAttached`` for LLVM style.
- Add initial support for C++26 reflection, including the new option ``SpacesInSplicers``.

libclang
--------
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -5734,6 +5734,14 @@ struct FormatStyle {
/// \version 17
SpacesInParensCustom SpacesInParensOptions;

/// If ``true``, spaces will be inserted after ``[:`` and before ``:]``.
/// \code
/// true: false:
/// [: ^^int :] i; vs. [:^^int:] i;
/// \endcode
/// \version 23
bool SpacesInSplicers;

/// If ``true``, spaces will be inserted after ``[`` and before ``]``.
/// Lambdas without arguments or unspecified size array declarations will not
/// be affected.
Expand Down Expand Up @@ -6201,6 +6209,7 @@ struct FormatStyle {
R.SpacesInLineCommentPrefix.Maximum &&
SpacesInParens == R.SpacesInParens &&
SpacesInParensOptions == R.SpacesInParensOptions &&
SpacesInSplicers == R.SpacesInSplicers &&
SpacesInSquareBrackets == R.SpacesInSquareBrackets &&
Standard == R.Standard &&
StatementAttributeLikeMacros == R.StatementAttributeLikeMacros &&
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,7 @@ template <> struct MappingTraits<FormatStyle> {
Style.SpacesInLineCommentPrefix);
IO.mapOptional("SpacesInParens", Style.SpacesInParens);
IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions);
IO.mapOptional("SpacesInSplicers", Style.SpacesInSplicers);
IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
IO.mapOptional("Standard", Style.Standard);
IO.mapOptional("StatementAttributeLikeMacros",
Expand Down Expand Up @@ -1970,6 +1971,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpacesInLineCommentPrefix = {
/*Minimum=*/1, /*Maximum=*/std::numeric_limits<unsigned>::max()};
LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never;
LLVMStyle.SpacesInSplicers = false;
LLVMStyle.SpacesInSquareBrackets = false;
LLVMStyle.Standard = FormatStyle::LS_Latest;
LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
Expand Down Expand Up @@ -4405,12 +4407,11 @@ tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
LangOptions LangOpts;

auto LexingStd = Style.Standard;
if (LexingStd == FormatStyle::LS_Auto || LexingStd == FormatStyle::LS_Latest)
LexingStd = FormatStyle::LS_Cpp20;
const auto LexingStd = Style.Standard;

const bool SinceCpp11 = LexingStd >= FormatStyle::LS_Cpp11;
const bool SinceCpp20 = LexingStd >= FormatStyle::LS_Cpp20;
const bool SinceCpp26 = LexingStd >= FormatStyle::LS_Cpp26;

switch (Style.Language) {
case FormatStyle::LK_C:
Expand All @@ -4425,7 +4426,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
LangOpts.CPlusPlus20 = SinceCpp20;
LangOpts.CPlusPlus23 = LexingStd >= FormatStyle::LS_Cpp23;
LangOpts.CPlusPlus26 = LexingStd >= FormatStyle::LS_Cpp26;
LangOpts.CPlusPlus26 = SinceCpp26;
[[fallthrough]];
default:
LangOpts.CPlusPlus = 1;
Expand All @@ -4437,6 +4438,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
// the sequence "<::" will be unconditionally treated as "[:".
// Cf. Lexer::LexTokenInternal.
LangOpts.Digraphs = SinceCpp11;
LangOpts.Reflection = SinceCpp26;

LangOpts.LineComment = 1;
LangOpts.Bool = 1;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ namespace format {
TYPE(RangeBasedForLoopColon) \
TYPE(RecordLBrace) \
TYPE(RecordRBrace) \
TYPE(ReflectionOperator) \
TYPE(RegexLiteral) \
TYPE(RequiresClause) \
TYPE(RequiresClauseInARequiresExpression) \
Expand All @@ -160,6 +161,8 @@ namespace format {
* field name in the C++ struct literal. Also the method or parameter name \
* in the Objective-C method declaration or call. */ \
TYPE(SelectorName) \
TYPE(SpliceCloser) \
TYPE(SpliceOpener) \
TYPE(StartOfName) \
TYPE(StatementAttributeLikeMacro) \
TYPE(StatementMacro) \
Expand Down
21 changes: 18 additions & 3 deletions clang/lib/Format/FormatTokenLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ void FormatTokenLexer::tryMergePreviousTokens() {
if (tryMergeForEach())
return;

if (LangOpts.Reflection && tryMergeSplicer())
return;

if ((Style.Language == FormatStyle::LK_Cpp ||
Style.Language == FormatStyle::LK_ObjC) &&
tryMergeUserDefinedLiteral()) {
Expand All @@ -182,6 +185,7 @@ void FormatTokenLexer::tryMergePreviousTokens() {
if (tryMergeTokens(NullishCoalescingOperator, TT_NullCoalescingOperator)) {
// Treat like the "||" operator (as opposed to the ternary ?).
Tokens.back()->Tok.setKind(tok::pipepipe);
Tokens.back()->overwriteFixedType(TT_NullCoalescingOperator);
return;
}
if (tryMergeTokens(NullPropagatingOperator, TT_NullPropagatingOperator)) {
Expand Down Expand Up @@ -272,8 +276,9 @@ void FormatTokenLexer::tryMergePreviousTokens() {
// already a merged token.
if (Tokens.back()->TokenText.size() == 1 &&
tryMergeTokensAny({{tok::caret, tok::tilde}, {tok::tilde, tok::caret}},
TT_BinaryOperator)) {
TT_Unknown)) {
Tokens.back()->Tok.setKind(tok::caret);
Tokens.back()->overwriteFixedType(TT_Unknown);
return;
}
// Signed shift and distribution weight.
Expand Down Expand Up @@ -468,7 +473,8 @@ bool FormatTokenLexer::tryMergeNullishCoalescingEqual() {
StringRef(NullishCoalescing->TokenText.begin(),
Equal->TokenText.end() - NullishCoalescing->TokenText.begin());
NullishCoalescing->ColumnWidth += Equal->ColumnWidth;
NullishCoalescing->setType(TT_NullCoalescingEqual);
NullishCoalescing->overwriteFixedType(TT_NullCoalescingEqual);
NullishCoalescing->setFinalizedType(TT_NullCoalescingEqual);
Tokens.erase(Tokens.end() - 1);
return true;
}
Expand Down Expand Up @@ -606,6 +612,15 @@ bool FormatTokenLexer::tryMergeUserDefinedLiteral() {
return true;
}

bool FormatTokenLexer::tryMergeSplicer() {
if (tryMergeTokens({tok::l_square, tok::colon}, TT_SpliceOpener))
return true;
if (!tryMergeTokens({tok::colon, tok::r_square}, TT_SpliceCloser))
return false;
Tokens.back()->Tok.setKind(tok::r_square);
return true;
}

bool FormatTokenLexer::tryMergeTokens(ArrayRef<tok::TokenKind> Kinds,
TokenType NewType) {
if (Tokens.size() < Kinds.size())
Expand Down Expand Up @@ -637,7 +652,7 @@ bool FormatTokenLexer::tryMergeTokens(size_t Count, TokenType NewType) {
First[0]->TokenText = StringRef(First[0]->TokenText.data(),
First[0]->TokenText.size() + AddLength);
First[0]->ColumnWidth += AddLength;
First[0]->setType(NewType);
First[0]->setFinalizedType(NewType);
return true;
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/FormatTokenLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class FormatTokenLexer {
bool tryMergeNullishCoalescingEqual();
bool tryTransformCSharpForEach();
bool tryMergeForEach();
bool tryMergeSplicer();

// Merge the most recently lexed tokens into a single token if their kinds are
// correct.
Expand Down
21 changes: 15 additions & 6 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,8 @@ class AnnotatingParser {
bool StartsObjCMethodExpr =
!IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&
IsCpp && !IsCpp11AttributeSpecifier && !IsCSharpAttributeSpecifier &&
Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
Contexts.back().CanBeExpression &&
Left->isNoneOf(TT_LambdaLSquare, TT_SpliceOpener) &&
CurrentToken->isNoneOf(tok::l_brace, tok::r_square) &&
// Do not consider '[' after a comma inside a braced initializer the
// start of an ObjC method expression. In braced initializer lists,
Expand Down Expand Up @@ -1836,6 +1837,9 @@ class AnnotatingParser {
if (Style.isTableGen() && !parseTableGenValue())
return false;
break;
case tok::caretcaret:
Tok->setFinalizedType(TT_ReflectionOperator);
break;
default:
break;
}
Expand Down Expand Up @@ -4902,6 +4906,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
LSquareTok.endsSequence(tok::l_square, tok::colon,
TT_SelectorName));
};
if (Left.is(TT_SpliceOpener) || Right.is(TT_SpliceCloser))
return Style.SpacesInSplicers;
if (Left.is(tok::l_square)) {
return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) &&
SpaceRequiredForArrayInitializerLSquare(Left, Style)) ||
Expand All @@ -4920,9 +4926,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
TT_LambdaLSquare)));
}
if (Right.is(tok::l_square) &&
Right.isNoneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
TT_DesignatedInitializerLSquare,
TT_StructuredBindingLSquare, TT_AttributeLSquare) &&
Right.isNoneOf(
TT_ObjCMethodExpr, TT_LambdaLSquare, TT_DesignatedInitializerLSquare,
TT_StructuredBindingLSquare, TT_AttributeLSquare, TT_SpliceOpener) &&
Left.isNoneOf(tok::numeric_constant, TT_DictLiteral) &&
!(Left.isNot(tok::r_square) && Style.SpaceBeforeSquareBrackets &&
Right.is(TT_ArraySubscriptLSquare))) {
Expand Down Expand Up @@ -5093,6 +5099,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
// void Fn() const &;
return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
}
if (Left.is(TT_ReflectionOperator))
return false;

return true;
}
Expand Down Expand Up @@ -6641,10 +6649,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
}

return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
tok::kw_class, tok::kw_struct, tok::comment) ||
tok::kw_class, tok::kw_struct, tok::comment,
TT_SpliceCloser) ||
Right.isMemberAccess() ||
Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless,
tok::colon, tok::l_square, tok::at) ||
tok::colon, tok::l_square, tok::at, TT_SpliceOpener) ||
(Left.is(tok::r_paren) &&
Right.isOneOf(tok::identifier, tok::kw_const)) ||
(Left.is(tok::l_paren) && Right.isNot(tok::r_paren)) ||
Expand Down
1 change: 1 addition & 0 deletions clang/unittests/Format/ConfigParseTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(RemoveEmptyLinesInUnwrappedLines);
CHECK_PARSE_BOOL(RemoveSemicolon);
CHECK_PARSE_BOOL(SkipMacroDefinitionBody);
CHECK_PARSE_BOOL(SpacesInSplicers);
CHECK_PARSE_BOOL(SpacesInSquareBrackets);
CHECK_PARSE_BOOL(SpacesInContainerLiterals);
CHECK_PARSE_BOOL(SpaceAfterCStyleCast);
Expand Down
13 changes: 13 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26306,6 +26306,19 @@ TEST_F(FormatTest, LambdaArrowAsTrailingReturnArrow) {
verifyNoCrash("void foo()([] consteval -> int {}())");
}

TEST_F(FormatTest, Reflection) {
verifyFormat("typename [:^^int:] i = 42;");
verifyFormat("obj.[:sub:]");
verifyFormat("auto foo() { return [:bar:]; }");
verifyFormat("auto x = ^^Bar;");

auto Style = getLLVMStyle();
Style.SpacesInSplicers = true;
verifyFormat("typename [: ^^int :] i = 42;", Style);
verifyFormat("obj.[: sub :]", Style);
verifyFormat("auto foo() { return [: bar :]; }", Style);
}

} // namespace
} // namespace test
} // namespace format
Expand Down
39 changes: 39 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4505,6 +4505,45 @@ TEST_F(TokenAnnotatorTest, AttributeSquares) {
EXPECT_TRUE(Tokens[15]->EndsCppAttributeGroup);
}

TEST_F(TokenAnnotatorTest, UnderstandsReflection) {
auto Tokens = annotate("auto x = ^^int;");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::caretcaret, TT_ReflectionOperator);

Tokens = annotate("auto x = ^^static_cast<void(*)(int)>(&foo);");
ASSERT_EQ(Tokens.size(), 20u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::caretcaret, TT_ReflectionOperator);

Tokens = annotate("[: x :]");
ASSERT_EQ(Tokens.size(), 4u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_SpliceOpener);
EXPECT_TOKEN(Tokens[2], tok::r_square, TT_SpliceCloser);

Tokens = annotate("[: ^^int :]");
ASSERT_EQ(Tokens.size(), 5u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_SpliceOpener);
EXPECT_TOKEN(Tokens[1], tok::caretcaret, TT_ReflectionOperator);
EXPECT_TOKEN(Tokens[3], tok::r_square, TT_SpliceCloser);

Tokens = annotate("[: ^^&T::member :]");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_SpliceOpener);
EXPECT_TOKEN(Tokens[1], tok::caretcaret, TT_ReflectionOperator);
EXPECT_TOKEN(Tokens[6], tok::r_square, TT_SpliceCloser);

Tokens = annotate("[: func() :]");
ASSERT_EQ(Tokens.size(), 6u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_SpliceOpener);
EXPECT_TOKEN(Tokens[4], tok::r_square, TT_SpliceCloser);

Tokens = annotate("[: condition ? ^^int : ^^double :]");
ASSERT_EQ(Tokens.size(), 10u) << Tokens;
EXPECT_TOKEN(Tokens[0], tok::l_square, TT_SpliceOpener);
EXPECT_TOKEN(Tokens[3], tok::caretcaret, TT_ReflectionOperator);
EXPECT_TOKEN(Tokens[6], tok::caretcaret, TT_ReflectionOperator);
EXPECT_TOKEN(Tokens[8], tok::r_square, TT_SpliceCloser);
}

} // namespace
} // namespace format
} // namespace clang
Loading