diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index dbd3a6e70f037..5877b0a612474 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -61,6 +61,7 @@ namespace format { TYPE(CSharpStringLiteral) \ TYPE(CtorInitializerColon) \ TYPE(CtorInitializerComma) \ + TYPE(CtorDtorDeclName) \ TYPE(DesignatedInitializerLSquare) \ TYPE(DesignatedInitializerPeriod) \ TYPE(DictLiteral) \ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 3ea65707da903..6f879006465ec 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3210,12 +3210,12 @@ static bool isCtorOrDtorName(const FormatToken *Tok) { } void TokenAnnotator::annotate(AnnotatedLine &Line) { - for (auto &Child : Line.Children) - annotate(*Child); - AnnotatingParser Parser(Style, Line, Keywords, Scopes); Line.Type = Parser.parseLine(); + for (auto &Child : Line.Children) + annotate(*Child); + // With very deep nesting, ExpressionParser uses lots of stack and the // formatting algorithm is very slow. We're not going to do a good job here // anyway - it's probably generated code being formatted by mistake. @@ -3233,7 +3233,7 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) { auto *Tok = getFunctionName(Line); if (Tok && ((!Scopes.empty() && Scopes.back() == ST_Class) || Line.endsWith(TT_FunctionLBrace) || isCtorOrDtorName(Tok))) { - Tok->setFinalizedType(TT_FunctionDeclarationName); + Tok->setFinalizedType(TT_CtorDtorDeclName); } } @@ -3447,9 +3447,13 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { Tok = Tok->Next) { if (Tok->Previous->EndsCppAttributeGroup) AfterLastAttribute = Tok; - if (isFunctionDeclarationName(Style.isCpp(), *Tok, Line, ClosingParen)) { - LineIsFunctionDeclaration = true; - Tok->setFinalizedType(TT_FunctionDeclarationName); + if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName); + IsCtorOrDtor || + isFunctionDeclarationName(Style.isCpp(), *Tok, Line, ClosingParen)) { + if (!IsCtorOrDtor) { + LineIsFunctionDeclaration = true; + Tok->setFinalizedType(TT_FunctionDeclarationName); + } if (AfterLastAttribute && mustBreakAfterAttributes(*AfterLastAttribute, Style)) { AfterLastAttribute->MustBreakBefore = true; diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 2cbde3da212ec..9061e07add545 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -975,11 +975,7 @@ void WhitespaceManager::alignConsecutiveDeclarations() { AlignTokens( Style, [](Change const &C) { - if (C.Tok->is(TT_FunctionDeclarationName) && C.Tok->Previous && - C.Tok->Previous->isNot(tok::tilde)) { - return true; - } - if (C.Tok->is(TT_FunctionTypeLParen)) + if (C.Tok->isOneOf(TT_FunctionDeclarationName, TT_FunctionTypeLParen)) return true; if (C.Tok->isNot(TT_StartOfName)) return false; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 246de2f89fccc..2ef3c9b299bca 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -10622,6 +10622,12 @@ TEST_F(FormatTest, WrapsAtNestedNameSpecifiers) { verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa::\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" " .aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa();"); + + verifyFormat( + "LongClassNameToShowTheIssue::AndAnotherLongClassNameToShowTheIssue::\n" + " AndAnotherLongClassNameToShowTheIssue() {}\n" + "LongClassNameToShowTheIssue::AndAnotherLongClassNameToShowTheIssue::\n" + " ~AndAnotherLongClassNameToShowTheIssue() {}"); } TEST_F(FormatTest, UnderstandsTemplateParameters) { @@ -16339,7 +16345,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("int f();", SpaceFuncDef); verifyFormat("void f (int a, T b) {}", SpaceFuncDef); - verifyFormat("A::A () : a(1) {}", SpaceFuncDef); + verifyFormat("A::A() : a(1) {}", SpaceFuncDef); verifyFormat("void f() __attribute__((asdf));", SpaceFuncDef); verifyFormat("#define A(x) x", SpaceFuncDef); verifyFormat("#define A (x) x", SpaceFuncDef); @@ -16364,7 +16370,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { // verifyFormat("T A::operator() () {}", SpaceFuncDef); verifyFormat("auto lambda = [] () { return 0; };", SpaceFuncDef); verifyFormat("int x = int(y);", SpaceFuncDef); - verifyFormat("M (std::size_t R, std::size_t C) : C(C), data(R) {}", + verifyFormat("M(std::size_t R, std::size_t C) : C(C), data(R) {}", SpaceFuncDef); FormatStyle SpaceIfMacros = getLLVMStyle(); diff --git a/clang/unittests/Format/FormatTestMacroExpansion.cpp b/clang/unittests/Format/FormatTestMacroExpansion.cpp index 1ac5ac0d84f12..bc698c60c107d 100644 --- a/clang/unittests/Format/FormatTestMacroExpansion.cpp +++ b/clang/unittests/Format/FormatTestMacroExpansion.cpp @@ -47,10 +47,9 @@ TEST_F(FormatTestMacroExpansion, UnexpandConfiguredMacros) { { ID(a *b); }); )", Style); - verifyIncompleteFormat(R"(ID3({, ID(a *b), - ; - }); -)", + verifyIncompleteFormat("ID3({, ID(a *b),\n" + " ;\n" + " });", Style); verifyFormat("ID(CALL(CALL(return a * b;)));", Style); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index a8259543dc488..62ec460eba7fd 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1631,65 +1631,77 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); - Tokens = annotate("class Foo { public: Foo(); };"); + Tokens = annotate("#define FOO Foo::\n" + "FOO Foo();"); + ASSERT_EQ(Tokens.size(), 11u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::identifier, TT_FunctionDeclarationName); + + Tokens = annotate("struct Foo {\n" + " Bar (*func)();\n" + "};"); + ASSERT_EQ(Tokens.size(), 14u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::identifier, TT_Unknown); + EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_FunctionTypeLParen); +} + +TEST_F(TokenAnnotatorTest, UnderstandsCtorAndDtorDeclNames) { + auto Tokens = annotate("class Foo { public: Foo(); };"); ASSERT_EQ(Tokens.size(), 12u) << Tokens; - EXPECT_TOKEN(Tokens[5], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[5], tok::identifier, TT_CtorDtorDeclName); Tokens = annotate("class Foo { public: ~Foo(); };"); ASSERT_EQ(Tokens.size(), 13u) << Tokens; - EXPECT_TOKEN(Tokens[6], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[6], tok::identifier, TT_CtorDtorDeclName); Tokens = annotate("struct Foo { [[deprecated]] Foo() {} };"); ASSERT_EQ(Tokens.size(), 16u) << Tokens; - EXPECT_TOKEN(Tokens[8], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[8], tok::identifier, TT_CtorDtorDeclName); EXPECT_TOKEN(Tokens[11], tok::l_brace, TT_FunctionLBrace); Tokens = annotate("struct Foo { [[deprecated]] ~Foo() {} };"); ASSERT_EQ(Tokens.size(), 17u) << Tokens; - EXPECT_TOKEN(Tokens[9], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[9], tok::identifier, TT_CtorDtorDeclName); EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_FunctionLBrace); Tokens = annotate("struct Foo { Foo() [[deprecated]] {} };"); ASSERT_EQ(Tokens.size(), 16u) << Tokens; - EXPECT_TOKEN(Tokens[3], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[3], tok::identifier, TT_CtorDtorDeclName); EXPECT_TOKEN(Tokens[11], tok::l_brace, TT_FunctionLBrace); Tokens = annotate("struct Foo { ~Foo() [[deprecated]] {} };"); ASSERT_EQ(Tokens.size(), 17u) << Tokens; - EXPECT_TOKEN(Tokens[4], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[4], tok::identifier, TT_CtorDtorDeclName); EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_FunctionLBrace); Tokens = annotate("struct Foo { [[deprecated]] explicit Foo() {} };"); ASSERT_EQ(Tokens.size(), 17u) << Tokens; - EXPECT_TOKEN(Tokens[9], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[9], tok::identifier, TT_CtorDtorDeclName); EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_FunctionLBrace); Tokens = annotate("struct Foo { virtual [[deprecated]] ~Foo() {} };"); ASSERT_EQ(Tokens.size(), 18u) << Tokens; - EXPECT_TOKEN(Tokens[10], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[10], tok::identifier, TT_CtorDtorDeclName); EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_FunctionLBrace); Tokens = annotate("Foo::Foo() {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; - EXPECT_TOKEN(Tokens[2], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[2], tok::identifier, TT_CtorDtorDeclName); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_FunctionLBrace); Tokens = annotate("Foo::~Foo() {}"); ASSERT_EQ(Tokens.size(), 9u) << Tokens; - EXPECT_TOKEN(Tokens[3], tok::identifier, TT_FunctionDeclarationName); + EXPECT_TOKEN(Tokens[3], tok::identifier, TT_CtorDtorDeclName); EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_FunctionLBrace); - Tokens = annotate("#define FOO Foo::\n" - "FOO Foo();"); - ASSERT_EQ(Tokens.size(), 11u) << Tokens; - EXPECT_TOKEN(Tokens[6], tok::identifier, TT_FunctionDeclarationName); - - Tokens = annotate("struct Foo {\n" - " Bar (*func)();\n" + Tokens = annotate("struct Test {\n" + " Test()\n" + " : l([] {\n" + " Short::foo();\n" + " }) {}\n" "};"); - ASSERT_EQ(Tokens.size(), 14u) << Tokens; - EXPECT_TOKEN(Tokens[3], tok::identifier, TT_Unknown); - EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_FunctionTypeLParen); + ASSERT_EQ(Tokens.size(), 25u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::identifier, TT_CtorDtorDeclName); + EXPECT_TOKEN(Tokens[14], tok::identifier, TT_Unknown); } TEST_F(TokenAnnotatorTest, UnderstandsC11GenericSelection) {