From: Daniel Jasper Date: Wed, 6 May 2015 08:38:24 +0000 (+0000) Subject: clang-format: Prevent exponential runtime in token annotator. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=842cc813b8b5a23fe7367522de991ce6e3fec96b;p=clang clang-format: Prevent exponential runtime in token annotator. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@236577 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 45193572ca..39ac66b27f 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -15,6 +15,7 @@ #include "TokenAnnotator.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "format-token-annotator" @@ -495,13 +496,15 @@ private: return false; break; case tok::less: - if ((!Tok->Previous || + if (!NonTemplateLess.count(Tok) && + (!Tok->Previous || (!Tok->Previous->Tok.isLiteral() && !(Tok->Previous->is(tok::r_paren) && Contexts.size() > 1))) && parseAngle()) { Tok->Type = TT_TemplateOpener; } else { Tok->Type = TT_BinaryOperator; + NonTemplateLess.insert(Tok); CurrentToken = Tok; next(); } @@ -648,6 +651,7 @@ private: public: LineType parseLine() { + NonTemplateLess.clear(); if (CurrentToken->is(tok::hash)) return parsePreprocessorDirective(); @@ -1160,6 +1164,12 @@ private: FormatToken *CurrentToken; bool AutoFound; const AdditionalKeywords &Keywords; + + // Set of "<" tokens that do not open a template parameter list. If parseAngle + // determines that a specific token can't be a template opener, it will make + // 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; }; static const int PrecedenceUnaryOperator = prec::PointerToMember + 1; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index e5fe7b5091..762f92c042 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -5155,6 +5155,7 @@ TEST_F(FormatTest, UnderstandsTemplateParameters) { getLLVMStyleWithColumns(60)); verifyFormat("static_assert(is_convertible::value, \"AAA\");"); verifyFormat("Constructor(A... a) : a_(X{std::forward(a)}...) {}"); + verifyFormat("< < < < < < < < < < < < < < < < < < < < < < < < < < < < < <"); } TEST_F(FormatTest, UnderstandsBinaryOperators) {