diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1fe3b61a5a81f2..9be5c09a32dd3f 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -127,7 +127,7 @@ class AnnotatingParser { SmallVector &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 @@ class AnnotatingParser { } 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() { @@ -3073,6 +3079,8 @@ class AnnotatingParser { // same decision irrespective of the decisions for tokens leading up to it. // Store this information to prevent this from causing exponential runtime. llvm::SmallPtrSet 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 8cc5c239d30a1c..504e5b66dae534 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