aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilia Kond <emilia@rymiel.space>2024-06-22 12:51:36 +0300
committerGitHub <noreply@github.com>2024-06-22 12:51:36 +0300
commit4a7bf42a9b83144db8a11ac06cce4da21166e6a2 (patch)
tree865e06461041e05c2dd93d3dfe8da288b788ffa2
parent8e9c6bfb5075a498344521d5911b6bc9ab9c901f (diff)
downloadllvm-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
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp30
-rw-r--r--clang/unittests/Format/TokenAnnotatorTest.cpp17
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");