diff options
author | Emilia Kond <emilia@rymiel.space> | 2024-06-22 12:51:36 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-22 12:51:36 +0300 |
commit | 4a7bf42a9b83144db8a11ac06cce4da21166e6a2 (patch) | |
tree | 865e06461041e05c2dd93d3dfe8da288b788ffa2 /clang | |
parent | 8e9c6bfb5075a498344521d5911b6bc9ab9c901f (diff) | |
download | llvm-4a7bf42a9b83144db8a11ac06cce4da21166e6a2.zip llvm-4a7bf42a9b83144db8a11ac06cce4da21166e6a2.tar.gz llvm-4a7bf42a9b83144db8a11ac06cce4da21166e6a2.tar.bz2 |
[clang-format] Don't count template template parameter as declaration (#95025)
In ContinuationIndenter::mustBreak, a break is required between a
template declaration and the function/class declaration it applies to,
if the template declaration spans multiple lines.
However, this also includes template template parameters, which can
cause extra erroneous line breaks in some declarations.
This patch makes template template parameters not be counted as template
declarations.
Fixes https://github.com/llvm/llvm-project/issues/93793
Fixes https://github.com/llvm/llvm-project/issues/48746
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Format/TokenAnnotator.cpp | 30 | ||||
-rw-r--r-- | clang/unittests/Format/TokenAnnotatorTest.cpp | 17 |
2 files changed, 36 insertions, 11 deletions
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 55c5ece..89e1341 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -127,7 +127,7 @@ public: SmallVector<ScopeType> &Scopes) : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false), IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)), - Keywords(Keywords), Scopes(Scopes) { + Keywords(Keywords), Scopes(Scopes), TemplateDeclarationDepth(0) { assert(IsCpp == LangOpts.CXXOperatorNames); Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false)); resetTokenMetadata(); @@ -1266,16 +1266,22 @@ private: } bool parseTemplateDeclaration() { - if (CurrentToken && CurrentToken->is(tok::less)) { - CurrentToken->setType(TT_TemplateOpener); - next(); - if (!parseAngle()) - return false; - if (CurrentToken) - CurrentToken->Previous->ClosesTemplateDeclaration = true; - return true; - } - return false; + if (!CurrentToken || CurrentToken->isNot(tok::less)) + return false; + + CurrentToken->setType(TT_TemplateOpener); + next(); + + TemplateDeclarationDepth++; + const bool WellFormed = parseAngle(); + TemplateDeclarationDepth--; + if (!WellFormed) + return false; + + if (CurrentToken && TemplateDeclarationDepth == 0) + CurrentToken->Previous->ClosesTemplateDeclaration = true; + + return true; } bool consumeToken() { @@ -3091,6 +3097,8 @@ private: // same decision irrespective of the decisions for tokens leading up to it. // Store this information to prevent this from causing exponential runtime. llvm::SmallPtrSet<FormatToken *, 16> NonTemplateLess; + + int TemplateDeclarationDepth; }; static const int PrecedenceUnaryOperator = prec::PointerToMember + 1; diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 12c4b7f..d3b310f 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -584,6 +584,23 @@ TEST_F(TokenAnnotatorTest, UnderstandsNonTemplateAngleBrackets) { EXPECT_TOKEN(Tokens[20], tok::greater, TT_BinaryOperator); } +TEST_F(TokenAnnotatorTest, UnderstandsTemplateTemplateParameters) { + auto Tokens = annotate("template <template <typename...> typename X,\n" + " template <typename...> class Y,\n" + " typename... T>\n" + "class A {};"); + ASSERT_EQ(Tokens.size(), 28u) << Tokens; + EXPECT_TOKEN(Tokens[1], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[3], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::greater, TT_TemplateCloser); + EXPECT_FALSE(Tokens[6]->ClosesTemplateDeclaration); + EXPECT_TOKEN(Tokens[11], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[14], tok::greater, TT_TemplateCloser); + EXPECT_FALSE(Tokens[14]->ClosesTemplateDeclaration); + EXPECT_TOKEN(Tokens[21], tok::greater, TT_TemplateCloser); + EXPECT_TRUE(Tokens[21]->ClosesTemplateDeclaration); +} + TEST_F(TokenAnnotatorTest, UnderstandsWhitespaceSensitiveMacros) { FormatStyle Style = getLLVMStyle(); Style.WhitespaceSensitiveMacros.push_back("FOO"); |