From: Daniel Jasper Date: Wed, 16 Jan 2013 09:10:19 +0000 (+0000) Subject: Change the datastructure for UnwrappedLines. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cbb6c41f3cec4a940201a8e2e65743c9f26c3673;p=clang Change the datastructure for UnwrappedLines. It was quite convoluted leading to us accidentally introducing O(N^2) complexity while copying from UnwrappedLine to AnnotatedLine. We might still want to improve the datastructure in AnnotatedLine (most importantly not put them in a vector where they need to be copied on vector resizing but that will be done as a follow-up. This fixes most of the regression in llvm.org/PR14959. No formatting changes intended. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172602 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 939038e2a5..dbed75c3f1 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -92,9 +92,30 @@ public: class AnnotatedLine { public: - AnnotatedLine(const FormatToken &FormatTok, unsigned Level, - bool InPPDirective) - : First(FormatTok), Level(Level), InPPDirective(InPPDirective) {} + AnnotatedLine(const UnwrappedLine &Line) + : First(Line.Tokens.front()), Level(Line.Level), + InPPDirective(Line.InPPDirective) { + assert(!Line.Tokens.empty()); + AnnotatedToken *Current = &First; + for (std::list::const_iterator I = ++Line.Tokens.begin(), + E = Line.Tokens.end(); + I != E; ++I) { + Current->Children.push_back(*I); + Current->Children[0].Parent = Current; + Current = &Current->Children[0]; + } + Last = Current; + } + AnnotatedLine(const AnnotatedLine &Other) + : First(Other.First), Type(Other.Type), Level(Other.Level), + InPPDirective(Other.InPPDirective) { + Last = &First; + while (!Last->Children.empty()) { + Last->Children[0].Parent = Last; + Last = &Last->Children[0]; + } + } + AnnotatedToken First; AnnotatedToken *Last; @@ -945,16 +966,6 @@ public: bool ColonIsObjCMethodExpr; }; - void createAnnotatedTokens(AnnotatedToken &Current) { - if (Current.FormatTok.Children.empty()) { - Line.Last = &Current; - } else { - Current.Children.push_back(AnnotatedToken(Current.FormatTok.Children[0])); - Current.Children.back().Parent = &Current; - createAnnotatedTokens(Current.Children.back()); - } - } - void calculateExtraInformation(AnnotatedToken &Current) { Current.SpaceRequiredBefore = spaceRequiredBefore(Current); @@ -978,9 +989,6 @@ public: } void annotate() { - Line.Last = &Line.First; - createAnnotatedTokens(Line.First); - AnnotatingParser Parser(Line.First); Line.Type = Parser.parseLine(); if (Line.Type == LT_Invalid) @@ -1619,8 +1627,7 @@ private: } virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) { - AnnotatedLines.push_back( - AnnotatedLine(TheLine.RootToken, TheLine.Level, TheLine.InPPDirective)); + AnnotatedLines.push_back(AnnotatedLine(TheLine)); } /// \brief Add a new line and the required indent before the first Token diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index fe522ac9d8..9a29ff011a 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -81,25 +81,17 @@ class ScopedLineState { public: ScopedLineState(UnwrappedLineParser &Parser) : Parser(Parser) { PreBlockLine = Parser.Line.take(); - Parser.Line.reset(new UnwrappedLine(*PreBlockLine)); - assert(Parser.LastInCurrentLine == NULL || - Parser.LastInCurrentLine->Children.empty()); - PreBlockLastToken = Parser.LastInCurrentLine; - PreBlockRootTokenInitialized = Parser.RootTokenInitialized; - Parser.RootTokenInitialized = false; - Parser.LastInCurrentLine = NULL; + Parser.Line.reset(new UnwrappedLine()); + Parser.Line->Level = PreBlockLine->Level; + Parser.Line->InPPDirective = PreBlockLine->InPPDirective; } ~ScopedLineState() { - if (Parser.RootTokenInitialized) { + if (!Parser.Line->Tokens.empty()) { Parser.addUnwrappedLine(); } - assert(!Parser.RootTokenInitialized); + assert(Parser.Line->Tokens.empty()); Parser.Line.reset(PreBlockLine); - Parser.RootTokenInitialized = PreBlockRootTokenInitialized; - Parser.LastInCurrentLine = PreBlockLastToken; - assert(Parser.LastInCurrentLine == NULL || - Parser.LastInCurrentLine->Children.empty()); Parser.MustBreakBeforeNextToken = true; } @@ -107,15 +99,12 @@ private: UnwrappedLineParser &Parser; UnwrappedLine *PreBlockLine; - FormatToken* PreBlockLastToken; - bool PreBlockRootTokenInitialized; }; UnwrappedLineParser::UnwrappedLineParser( clang::DiagnosticsEngine &Diag, const FormatStyle &Style, FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback) - : Line(new UnwrappedLine), RootTokenInitialized(false), - LastInCurrentLine(NULL), MustBreakBeforeNextToken(false), Diag(Diag), + : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), Diag(Diag), Style(Style), Tokens(&Tokens), Callback(Callback) { } @@ -659,7 +648,7 @@ void UnwrappedLineParser::parseObjCProtocol() { } void UnwrappedLineParser::addUnwrappedLine() { - if (!RootTokenInitialized) + if (Line->Tokens.empty()) return; // Consume trailing comments. while (!eof() && FormatTok.NewlinesBefore == 0 && @@ -667,17 +656,17 @@ void UnwrappedLineParser::addUnwrappedLine() { nextToken(); } #ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT - FormatToken* NextToken = &Line->RootToken; llvm::errs() << "Line: "; - while (NextToken) { - llvm::errs() << NextToken->Tok.getName() << " "; - NextToken = NextToken->Children.empty() ? NULL : &NextToken->Children[0]; + for (std::list::iterator I = Line->Tokens.begin(), + E = Line->Tokens.end(); + I != E; ++I) { + llvm::errs() << I->Tok.getName() << " "; + } llvm::errs() << "\n"; #endif Callback.consumeUnwrappedLine(*Line); - RootTokenInitialized = false; - LastInCurrentLine = NULL; + Line->Tokens.clear(); } bool UnwrappedLineParser::eof() const { @@ -687,17 +676,9 @@ bool UnwrappedLineParser::eof() const { void UnwrappedLineParser::nextToken() { if (eof()) return; - if (RootTokenInitialized) { - assert(LastInCurrentLine->Children.empty()); - LastInCurrentLine->Children.push_back(FormatTok); - LastInCurrentLine = &LastInCurrentLine->Children.back(); - } else { - Line->RootToken = FormatTok; - RootTokenInitialized = true; - LastInCurrentLine = &Line->RootToken; - } + Line->Tokens.push_back(FormatTok); if (MustBreakBeforeNextToken) { - LastInCurrentLine->MustBreakBefore = true; + Line->Tokens.back().MustBreakBefore = true; MustBreakBeforeNextToken = false; } readToken(); diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h index 08faff15af..21a973d9dd 100644 --- a/lib/Format/UnwrappedLineParser.h +++ b/lib/Format/UnwrappedLineParser.h @@ -24,7 +24,7 @@ #include "clang/Format/Format.h" #include "clang/Lex/Lexer.h" -#include +#include namespace clang { @@ -76,11 +76,6 @@ struct FormatToken { /// This happens for example when a preprocessor directive ended directly /// before the token. bool MustBreakBefore; - - // FIXME: We currently assume that there is exactly one token in this vector - // except for the very last token that does not have any children. - /// \brief All tokens that logically follow this token. - std::vector Children; }; /// \brief An unwrapped line is a sequence of \c Token, that we would like to @@ -93,8 +88,8 @@ struct UnwrappedLine { UnwrappedLine() : Level(0), InPPDirective(false) { } - /// \brief The \c Token comprising this \c UnwrappedLine. - FormatToken RootToken; + /// \brief The \c Tokens comprising this \c UnwrappedLine. + std::list Tokens; /// \brief The indent level of the \c UnwrappedLine. unsigned Level; @@ -160,8 +155,6 @@ private: // subtracted from beyond 0. Introduce a method to subtract from Line.Level // and use that everywhere in the Parser. OwningPtr Line; - bool RootTokenInitialized; - FormatToken *LastInCurrentLine; FormatToken FormatTok; bool MustBreakBeforeNextToken;