diff options
author | NAKAMURA Takumi <geek4civic@gmail.com> | 2025-01-09 18:31:57 +0900 |
---|---|---|
committer | NAKAMURA Takumi <geek4civic@gmail.com> | 2025-01-09 18:33:27 +0900 |
commit | df025ebf872052c0761d44a3ef9b65e9675af8a8 (patch) | |
tree | 9b4e94583e2536546d6606270bcdf846c95e1ba2 /clang/lib/Format | |
parent | 4428c9d0b1344179f85a72e183a44796976521e3 (diff) | |
parent | bdcf47e4bcb92889665825654bb80a8bbe30379e (diff) | |
download | llvm-users/chapuni/cov/single/loop.zip llvm-users/chapuni/cov/single/loop.tar.gz llvm-users/chapuni/cov/single/loop.tar.bz2 |
Merge branch 'users/chapuni/cov/single/base' into users/chapuni/cov/single/loopusers/chapuni/cov/single/loop
Conflicts:
clang/lib/CodeGen/CoverageMappingGen.cpp
Diffstat (limited to 'clang/lib/Format')
-rw-r--r-- | clang/lib/Format/AffectedRangeManager.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Format/AffectedRangeManager.h | 4 | ||||
-rw-r--r-- | clang/lib/Format/Format.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Format/FormatToken.h | 3 | ||||
-rw-r--r-- | clang/lib/Format/FormatTokenLexer.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Format/FormatTokenLexer.h | 3 | ||||
-rw-r--r-- | clang/lib/Format/MatchFilePath.cpp | 38 | ||||
-rw-r--r-- | clang/lib/Format/TokenAnnotator.cpp | 63 | ||||
-rw-r--r-- | clang/lib/Format/TokenAnnotator.h | 8 | ||||
-rw-r--r-- | clang/lib/Format/UnwrappedLineFormatter.cpp | 168 | ||||
-rw-r--r-- | clang/lib/Format/UnwrappedLineParser.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Format/UnwrappedLineParser.h | 2 |
12 files changed, 274 insertions, 88 deletions
diff --git a/clang/lib/Format/AffectedRangeManager.cpp b/clang/lib/Format/AffectedRangeManager.cpp index bf124d7..67108f3 100644 --- a/clang/lib/Format/AffectedRangeManager.cpp +++ b/clang/lib/Format/AffectedRangeManager.cpp @@ -21,8 +21,8 @@ namespace format { bool AffectedRangeManager::computeAffectedLines( SmallVectorImpl<AnnotatedLine *> &Lines) { - SmallVectorImpl<AnnotatedLine *>::iterator I = Lines.begin(); - SmallVectorImpl<AnnotatedLine *>::iterator E = Lines.end(); + ArrayRef<AnnotatedLine *>::iterator I = Lines.begin(); + ArrayRef<AnnotatedLine *>::iterator E = Lines.end(); bool SomeLineAffected = false; const AnnotatedLine *PreviousLine = nullptr; while (I != E) { @@ -34,7 +34,7 @@ bool AffectedRangeManager::computeAffectedLines( // if any token within the directive is affected. if (Line->InPPDirective) { FormatToken *Last = Line->Last; - SmallVectorImpl<AnnotatedLine *>::iterator PPEnd = I + 1; + const auto *PPEnd = I + 1; while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) { Last = (*PPEnd)->Last; ++PPEnd; @@ -89,8 +89,8 @@ bool AffectedRangeManager::affectsLeadingEmptyLines(const FormatToken &Tok) { } void AffectedRangeManager::markAllAsAffected( - SmallVectorImpl<AnnotatedLine *>::iterator I, - SmallVectorImpl<AnnotatedLine *>::iterator E) { + ArrayRef<AnnotatedLine *>::iterator I, + ArrayRef<AnnotatedLine *>::iterator E) { while (I != E) { (*I)->Affected = true; markAllAsAffected((*I)->Children.begin(), (*I)->Children.end()); diff --git a/clang/lib/Format/AffectedRangeManager.h b/clang/lib/Format/AffectedRangeManager.h index add16bd..eef056f 100644 --- a/clang/lib/Format/AffectedRangeManager.h +++ b/clang/lib/Format/AffectedRangeManager.h @@ -47,8 +47,8 @@ private: bool affectsLeadingEmptyLines(const FormatToken &Tok); // Marks all lines between I and E as well as all their children as affected. - void markAllAsAffected(SmallVectorImpl<AnnotatedLine *>::iterator I, - SmallVectorImpl<AnnotatedLine *>::iterator E); + void markAllAsAffected(ArrayRef<AnnotatedLine *>::iterator I, + ArrayRef<AnnotatedLine *>::iterator E); // Determines whether 'Line' is affected by the SourceRanges given as input. // Returns \c true if line or one if its children is affected. diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 95129a8..fc60c5e 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -839,6 +839,18 @@ template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> { } }; +template <> +struct ScalarEnumerationTraits< + FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle> { + static void + enumeration(IO &IO, + FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::WNBWELS_Never); + IO.enumCase(Value, "Always", FormatStyle::WNBWELS_Always); + IO.enumCase(Value, "Leave", FormatStyle::WNBWELS_Leave); + } +}; + template <> struct MappingTraits<FormatStyle> { static void mapping(IO &IO, FormatStyle &Style) { // When reading, read the language first, we need it for getPredefinedStyle. @@ -975,6 +987,8 @@ template <> struct MappingTraits<FormatStyle> { Style.AllowShortLambdasOnASingleLine); IO.mapOptional("AllowShortLoopsOnASingleLine", Style.AllowShortLoopsOnASingleLine); + IO.mapOptional("AllowShortNamespacesOnASingleLine", + Style.AllowShortNamespacesOnASingleLine); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); IO.mapOptional("AlwaysBreakBeforeMultilineStrings", @@ -1164,10 +1178,13 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("TypeNames", Style.TypeNames); IO.mapOptional("TypenameMacros", Style.TypenameMacros); IO.mapOptional("UseTab", Style.UseTab); + IO.mapOptional("VariableTemplates", Style.VariableTemplates); IO.mapOptional("VerilogBreakBetweenInstancePorts", Style.VerilogBreakBetweenInstancePorts); IO.mapOptional("WhitespaceSensitiveMacros", Style.WhitespaceSensitiveMacros); + IO.mapOptional("WrapNamespaceBodyWithEmptyLines", + Style.WrapNamespaceBodyWithEmptyLines); // If AlwaysBreakAfterDefinitionReturnType was specified but // BreakAfterReturnType was not, initialize the latter from the former for @@ -1480,6 +1497,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; LLVMStyle.AllowShortLoopsOnASingleLine = false; + LLVMStyle.AllowShortNamespacesOnASingleLine = false; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; LLVMStyle.AttributeMacros.push_back("__capability"); @@ -1635,6 +1653,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME"); LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE"); LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE"); + LLVMStyle.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave; LLVMStyle.PenaltyBreakAssignment = prec::Assignment; LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; @@ -3066,8 +3085,8 @@ static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, // its current line. // If `Cursor` is not on any #include, `Index` will be UINT_MAX. static std::pair<unsigned, unsigned> -FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, - const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { +FindCursorIndex(const ArrayRef<IncludeDirective> &Includes, + const ArrayRef<unsigned> &Indices, unsigned Cursor) { unsigned CursorIndex = UINT_MAX; unsigned OffsetToEOL = 0; for (int i = 0, e = Includes.size(); i != e; ++i) { @@ -3116,7 +3135,7 @@ std::string replaceCRLF(const std::string &Code) { // provided and put on a deleted #include, it will be moved to the remaining // #include in the duplicate #includes. static void sortCppIncludes(const FormatStyle &Style, - const SmallVectorImpl<IncludeDirective> &Includes, + const ArrayRef<IncludeDirective> &Includes, ArrayRef<tooling::Range> Ranges, StringRef FileName, StringRef Code, tooling::Replacements &Replaces, unsigned *Cursor) { @@ -3359,7 +3378,7 @@ static unsigned findJavaImportGroup(const FormatStyle &Style, // import group, a newline is inserted, and within each import group, a // lexicographic sort based on ASCII value is performed. static void sortJavaImports(const FormatStyle &Style, - const SmallVectorImpl<JavaImportDirective> &Imports, + const ArrayRef<JavaImportDirective> &Imports, ArrayRef<tooling::Range> Ranges, StringRef FileName, StringRef Code, tooling::Replacements &Replaces) { unsigned ImportsBeginOffset = Imports.front().Offset; diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index f6bb860..d97b652 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -25,6 +25,7 @@ namespace clang { namespace format { #define LIST_TOKEN_TYPES \ + TYPE(AfterPPDirective) \ TYPE(ArrayInitializerLSquare) \ TYPE(ArraySubscriptLSquare) \ TYPE(AttributeColon) \ @@ -44,6 +45,7 @@ namespace format { TYPE(CastRParen) \ TYPE(ClassLBrace) \ TYPE(ClassRBrace) \ + TYPE(CompoundRequirementLBrace) \ /* ternary ?: expression */ \ TYPE(ConditionalExpr) \ /* the condition in an if statement */ \ @@ -186,6 +188,7 @@ namespace format { TYPE(UnionLBrace) \ TYPE(UnionRBrace) \ TYPE(UntouchableMacroFunc) \ + TYPE(VariableTemplate) \ /* Like in 'assign x = 0, y = 1;' . */ \ TYPE(VerilogAssignComma) \ /* like in begin : block */ \ diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index 7a264bd..a1d7eea 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -76,6 +76,8 @@ FormatTokenLexer::FormatTokenLexer( TemplateNames.insert(&IdentTable.get(TemplateName)); for (const auto &TypeName : Style.TypeNames) TypeNames.insert(&IdentTable.get(TypeName)); + for (const auto &VariableTemplate : Style.VariableTemplates) + VariableTemplates.insert(&IdentTable.get(VariableTemplate)); } ArrayRef<FormatToken *> FormatTokenLexer::lex() { @@ -562,8 +564,7 @@ bool FormatTokenLexer::tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, if (Tokens.size() < Kinds.size()) return false; - SmallVectorImpl<FormatToken *>::const_iterator First = - Tokens.end() - Kinds.size(); + const auto *First = Tokens.end() - Kinds.size(); for (unsigned i = 0; i < Kinds.size(); ++i) if (First[i]->isNot(Kinds[i])) return false; @@ -575,7 +576,7 @@ bool FormatTokenLexer::tryMergeTokens(size_t Count, TokenType NewType) { if (Tokens.size() < Count) return false; - SmallVectorImpl<FormatToken *>::const_iterator First = Tokens.end() - Count; + const auto *First = Tokens.end() - Count; unsigned AddLength = 0; for (size_t i = 1; i < Count; ++i) { // If there is whitespace separating the token and the previous one, @@ -1382,6 +1383,8 @@ FormatToken *FormatTokenLexer::getNextToken() { FormatTok->setFinalizedType(TT_TemplateName); else if (TypeNames.contains(Identifier)) FormatTok->setFinalizedType(TT_TypeName); + else if (VariableTemplates.contains(Identifier)) + FormatTok->setFinalizedType(TT_VariableTemplate); } } diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h index 71389d2..61474a3 100644 --- a/clang/lib/Format/FormatTokenLexer.h +++ b/clang/lib/Format/FormatTokenLexer.h @@ -129,7 +129,8 @@ private: llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros; - llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames; + llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames, + VariableTemplates; bool FormattingDisabled; diff --git a/clang/lib/Format/MatchFilePath.cpp b/clang/lib/Format/MatchFilePath.cpp index 062b334d..1f1e4bf 100644 --- a/clang/lib/Format/MatchFilePath.cpp +++ b/clang/lib/Format/MatchFilePath.cpp @@ -25,9 +25,11 @@ bool matchFilePath(StringRef Pattern, StringRef FilePath) { assert(!Pattern.empty()); assert(!FilePath.empty()); + const auto FilePathBack = FilePath.back(); + // No match if `Pattern` ends with a non-meta character not equal to the last // character of `FilePath`. - if (const auto C = Pattern.back(); !strchr("?*]", C) && C != FilePath.back()) + if (const auto C = Pattern.back(); !strchr("?*]", C) && C != FilePathBack) return false; constexpr auto Separator = '/'; @@ -49,25 +51,37 @@ bool matchFilePath(StringRef Pattern, StringRef FilePath) { return false; break; case '*': { - while (++I < EOP && Pattern[I] == '*') { // Skip consecutive stars. + bool Globstar = I == 0 || Pattern[I - 1] == Separator; + int StarCount = 1; + for (; ++I < EOP && Pattern[I] == '*'; ++StarCount) { + // Skip consecutive stars. } + if (StarCount != 2) + Globstar = false; const auto K = FilePath.find(Separator, J); // Index of next `Separator`. const bool NoMoreSeparatorsInFilePath = K == StringRef::npos; if (I == EOP) // `Pattern` ends with a star. - return NoMoreSeparatorsInFilePath; - // `Pattern` ends with a lone backslash. - if (Pattern[I] == '\\' && ++I == EOP) - return false; + return Globstar || NoMoreSeparatorsInFilePath; + if (Pattern[I] != Separator) { + // `Pattern` ends with a lone backslash. + if (Pattern[I] == '\\' && ++I == EOP) + return false; + Globstar = false; + } // The star is followed by a (possibly escaped) `Separator`. if (Pattern[I] == Separator) { - if (NoMoreSeparatorsInFilePath) - return false; - J = K; // Skip to next `Separator` in `FilePath`. - break; + if (!Globstar) { + if (NoMoreSeparatorsInFilePath) + return false; + J = K; // Skip to next `Separator` in `FilePath`. + break; + } + if (++I == EOP) + return FilePathBack == Separator; } // Recurse. - for (auto Pat = Pattern.substr(I); J < End && FilePath[J] != Separator; - ++J) { + for (auto Pat = Pattern.substr(I); + J < End && (Globstar || FilePath[J] != Separator); ++J) { if (matchFilePath(Pat, FilePath.substr(J))) return true; } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index f2cfa7f..bf5ee28 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -137,12 +137,12 @@ public: private: ScopeType getScopeType(const FormatToken &Token) const { switch (Token.getType()) { - case TT_LambdaLBrace: - return ST_ChildBlock; case TT_ClassLBrace: case TT_StructLBrace: case TT_UnionLBrace: return ST_Class; + case TT_CompoundRequirementLBrace: + return ST_CompoundRequirement; default: return ST_Other; } @@ -1580,7 +1580,10 @@ private: return false; break; case tok::l_brace: - if (Style.Language == FormatStyle::LK_TextProto) { + if (IsCpp) { + if (Tok->is(TT_RequiresExpressionLBrace)) + Line.Type = LT_RequiresExpression; + } else if (Style.Language == FormatStyle::LK_TextProto) { FormatToken *Previous = Tok->getPreviousNonComment(); if (Previous && Previous->isNot(TT_DictLiteral)) Previous->setType(TT_SelectorName); @@ -2022,8 +2025,11 @@ public: if (!consumeToken()) return LT_Invalid; } - if (Line.Type == LT_AccessModifier) - return LT_AccessModifier; + if (const auto Type = Line.Type; Type == LT_AccessModifier || + Type == LT_RequiresExpression || + Type == LT_SimpleRequirement) { + return Type; + } if (KeywordVirtualFound) return LT_VirtualFunctionDecl; if (ImportStatement) @@ -2076,7 +2082,7 @@ private: TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause, TT_RequiresClauseInARequiresExpression, TT_RequiresExpression, TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace, - TT_BracedListLBrace)) { + TT_CompoundRequirementLBrace, TT_BracedListLBrace)) { CurrentToken->setType(TT_Unknown); } CurrentToken->Role.reset(); @@ -2792,6 +2798,16 @@ private: return true; } + auto IsNonVariableTemplate = [](const FormatToken &Tok) { + if (Tok.isNot(TT_TemplateCloser)) + return false; + const auto *Less = Tok.MatchingParen; + if (!Less) + return false; + const auto *BeforeLess = Less->getPreviousNonComment(); + return BeforeLess && BeforeLess->isNot(TT_VariableTemplate); + }; + // Heuristically try to determine whether the parentheses contain a type. auto IsQualifiedPointerOrReference = [](const FormatToken *T, const LangOptions &LangOpts) { @@ -2825,10 +2841,11 @@ private: } return T && T->is(TT_PointerOrReference); }; - bool ParensAreType = - BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || - BeforeRParen->isTypeName(LangOpts) || - IsQualifiedPointerOrReference(BeforeRParen, LangOpts); + + bool ParensAreType = IsNonVariableTemplate(*BeforeRParen) || + BeforeRParen->is(TT_TypeDeclarationParen) || + BeforeRParen->isTypeName(LangOpts) || + IsQualifiedPointerOrReference(BeforeRParen, LangOpts); bool ParensCouldEndDecl = AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); if (ParensAreType && !ParensCouldEndDecl) @@ -3089,6 +3106,11 @@ private: } } + if (Line.Type == LT_SimpleRequirement || + (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)) { + return TT_BinaryOperator; + } + return TT_PointerOrReference; } @@ -3371,13 +3393,13 @@ private: /// Parse unary operator expressions and surround them with fake /// parentheses if appropriate. void parseUnaryOperator() { - llvm::SmallVector<FormatToken *, 2> Tokens; + SmallVector<FormatToken *, 2> Tokens; while (Current && Current->is(TT_UnaryOperator)) { Tokens.push_back(Current); next(); } parse(PrecedenceArrowAndPeriod); - for (FormatToken *Token : llvm::reverse(Tokens)) { + for (FormatToken *Token : reverse(Tokens)) { // The actual precedence doesn't matter. addFakeParenthesis(Token, prec::Unknown); } @@ -3555,7 +3577,7 @@ private: void TokenAnnotator::setCommentLineLevels( SmallVectorImpl<AnnotatedLine *> &Lines) const { const AnnotatedLine *NextNonCommentLine = nullptr; - for (AnnotatedLine *Line : llvm::reverse(Lines)) { + for (AnnotatedLine *Line : reverse(Lines)) { assert(Line->First); // If the comment is currently aligned with the line immediately following @@ -3676,9 +3698,16 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) { Line.Type = Parser.parseLine(); if (!Line.Children.empty()) { - ScopeStack.push_back(ST_ChildBlock); - for (auto &Child : Line.Children) + ScopeStack.push_back(ST_Other); + const bool InRequiresExpression = Line.Type == LT_RequiresExpression; + for (auto &Child : Line.Children) { + if (InRequiresExpression && + !Child->First->isOneOf(tok::kw_typename, tok::kw_requires, + TT_CompoundRequirementLBrace)) { + Child->Type = LT_SimpleRequirement; + } annotate(*Child); + } // ScopeStack can become empty if Child has an unmatched `}`. if (!ScopeStack.empty()) ScopeStack.pop_back(); @@ -4930,6 +4959,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, Right.is(TT_ModulePartitionColon)) { return true; } + + if (Right.is(TT_AfterPPDirective)) + return true; + // No space between import foo:bar but keep a space between import :bar; if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon)) return false; diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 9117ca3..16e920e 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -33,14 +33,16 @@ enum LineType { LT_VirtualFunctionDecl, LT_ArrayOfStructInitializer, LT_CommentAbovePPDirective, + LT_RequiresExpression, + LT_SimpleRequirement, }; enum ScopeType { - // Contained in child block. - ST_ChildBlock, // Contained in class declaration/definition. ST_Class, - // Contained within other scope block (function, loop, if/else, etc). + // Contained in compound requirement. + ST_CompoundRequirement, + // Contained in other blocks (function, lambda, loop, if/else, child, etc). ST_Other, }; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 1804c14..ec65fea 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -183,9 +183,9 @@ private: unsigned Indent = 0; }; -const FormatToken *getMatchingNamespaceToken( - const AnnotatedLine *Line, - const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { +const FormatToken * +getMatchingNamespaceToken(const AnnotatedLine *Line, + const ArrayRef<AnnotatedLine *> &AnnotatedLines) { if (!Line->startsWith(tok::r_brace)) return nullptr; size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex; @@ -200,9 +200,9 @@ StringRef getNamespaceTokenText(const AnnotatedLine *Line) { return NamespaceToken ? NamespaceToken->TokenText : StringRef(); } -StringRef getMatchingNamespaceTokenText( - const AnnotatedLine *Line, - const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { +StringRef +getMatchingNamespaceTokenText(const AnnotatedLine *Line, + const ArrayRef<AnnotatedLine *> &AnnotatedLines) { const FormatToken *NamespaceToken = getMatchingNamespaceToken(Line, AnnotatedLines); return NamespaceToken ? NamespaceToken->TokenText : StringRef(); @@ -241,8 +241,8 @@ private: /// Calculates how many lines can be merged into 1 starting at \p I. unsigned tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker, - SmallVectorImpl<AnnotatedLine *>::const_iterator I, - SmallVectorImpl<AnnotatedLine *>::const_iterator E) { + ArrayRef<AnnotatedLine *>::const_iterator I, + ArrayRef<AnnotatedLine *>::const_iterator E) { const unsigned Indent = IndentTracker.getIndent(); // Can't join the last line with anything. @@ -361,9 +361,18 @@ private: const auto *FirstNonComment = TheLine->getFirstNonComment(); if (!FirstNonComment) return 0; + // FIXME: There are probably cases where we should use FirstNonComment // instead of TheLine->First. + if (Style.AllowShortNamespacesOnASingleLine && + TheLine->First->is(tok::kw_namespace) && + TheLine->Last->is(tok::l_brace)) { + const auto result = tryMergeNamespace(I, E, Limit); + if (result > 0) + return result; + } + if (Style.CompactNamespaces) { if (const auto *NSToken = TheLine->First->getNamespaceToken()) { int J = 1; @@ -373,7 +382,7 @@ private: ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex && I[J]->Last->TotalLength < Limit; ++J, --ClosingLineIndex) { - Limit -= I[J]->Last->TotalLength; + Limit -= I[J]->Last->TotalLength + 1; // Reduce indent level for bodies of namespaces which were compacted, // but only if their content was indented in the first place. @@ -420,6 +429,7 @@ private: TheLine->First != LastNonComment) { return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0; } + // Try to merge a control statement block with left brace unwrapped. if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last && FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for, @@ -525,7 +535,7 @@ private: // Try to merge records. if (TheLine->Last->is(TT_EnumLBrace)) { ShouldMerge = Style.AllowShortEnumsOnASingleLine; - } else if (TheLine->Last->is(TT_RequiresExpressionLBrace)) { + } else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) { ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine; } else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) { // NOTE: We use AfterClass (whereas AfterStruct exists) for both classes @@ -604,8 +614,8 @@ private: } unsigned - tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I, - SmallVectorImpl<AnnotatedLine *>::const_iterator E, + tryMergeSimplePPDirective(ArrayRef<AnnotatedLine *>::const_iterator I, + ArrayRef<AnnotatedLine *>::const_iterator E, unsigned Limit) { if (Limit == 0) return 0; @@ -616,9 +626,76 @@ private: return 1; } - unsigned tryMergeSimpleControlStatement( - SmallVectorImpl<AnnotatedLine *>::const_iterator I, - SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) { + unsigned tryMergeNamespace(ArrayRef<AnnotatedLine *>::const_iterator I, + ArrayRef<AnnotatedLine *>::const_iterator E, + unsigned Limit) { + if (Limit == 0) + return 0; + + assert(I[1]); + const auto &L1 = *I[1]; + if (L1.InPPDirective != (*I)->InPPDirective || + (L1.InPPDirective && L1.First->HasUnescapedNewline)) { + return 0; + } + + if (std::distance(I, E) <= 2) + return 0; + + assert(I[2]); + const auto &L2 = *I[2]; + if (L2.Type == LT_Invalid) + return 0; + + Limit = limitConsideringMacros(I + 1, E, Limit); + + if (!nextTwoLinesFitInto(I, Limit)) + return 0; + + // Check if it's a namespace inside a namespace, and call recursively if so. + // '3' is the sizes of the whitespace and closing brace for " _inner_ }". + if (L1.First->is(tok::kw_namespace)) { + if (L1.Last->is(tok::comment) || !Style.CompactNamespaces) + return 0; + + assert(Limit >= L1.Last->TotalLength + 3); + const auto InnerLimit = Limit - L1.Last->TotalLength - 3; + const auto MergedLines = tryMergeNamespace(I + 1, E, InnerLimit); + if (MergedLines == 0) + return 0; + const auto N = MergedLines + 2; + // Check if there is even a line after the inner result. + if (std::distance(I, E) <= N) + return 0; + // Check that the line after the inner result starts with a closing brace + // which we are permitted to merge into one line. + if (I[N]->First->is(tok::r_brace) && !I[N]->First->MustBreakBefore && + I[MergedLines + 1]->Last->isNot(tok::comment) && + nextNLinesFitInto(I, I + N + 1, Limit)) { + return N; + } + return 0; + } + + // There's no inner namespace, so we are considering to merge at most one + // line. + + // The line which is in the namespace should end with semicolon. + if (L1.Last->isNot(tok::semi)) + return 0; + + // Last, check that the third line starts with a closing brace. + if (L2.First->isNot(tok::r_brace) || L2.First->MustBreakBefore) + return 0; + + // If so, merge all three lines. + return 2; + } + + unsigned + tryMergeSimpleControlStatement(ArrayRef<AnnotatedLine *>::const_iterator I, + ArrayRef<AnnotatedLine *>::const_iterator E, + unsigned Limit) { if (Limit == 0) return 0; if (Style.BraceWrapping.AfterControlStatement == @@ -658,10 +735,9 @@ private: return 1; } - unsigned - tryMergeShortCaseLabels(SmallVectorImpl<AnnotatedLine *>::const_iterator I, - SmallVectorImpl<AnnotatedLine *>::const_iterator E, - unsigned Limit) { + unsigned tryMergeShortCaseLabels(ArrayRef<AnnotatedLine *>::const_iterator I, + ArrayRef<AnnotatedLine *>::const_iterator E, + unsigned Limit) { if (Limit == 0 || I + 1 == E || I[1]->First->isOneOf(tok::kw_case, tok::kw_default)) { return 0; @@ -692,7 +768,7 @@ private: if (Line->First->is(tok::comment)) { if (Level != Line->Level) return 0; - SmallVectorImpl<AnnotatedLine *>::const_iterator J = I + 2 + NumStmts; + const auto *J = I + 2 + NumStmts; for (; J != E; ++J) { Line = *J; if (Line->InPPDirective != InPPDirective) @@ -713,10 +789,9 @@ private: return NumStmts; } - unsigned - tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator I, - SmallVectorImpl<AnnotatedLine *>::const_iterator E, - unsigned Limit) { + unsigned tryMergeSimpleBlock(ArrayRef<AnnotatedLine *>::const_iterator I, + ArrayRef<AnnotatedLine *>::const_iterator E, + unsigned Limit) { // Don't merge with a preprocessor directive. if (I[1]->Type == LT_PreprocessorDirective) return 0; @@ -898,10 +973,9 @@ private: /// Returns the modified column limit for \p I if it is inside a macro and /// needs a trailing '\'. - unsigned - limitConsideringMacros(SmallVectorImpl<AnnotatedLine *>::const_iterator I, - SmallVectorImpl<AnnotatedLine *>::const_iterator E, - unsigned Limit) { + unsigned limitConsideringMacros(ArrayRef<AnnotatedLine *>::const_iterator I, + ArrayRef<AnnotatedLine *>::const_iterator E, + unsigned Limit) { if (I[0]->InPPDirective && I + 1 != E && !I[1]->First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) { return Limit < 2 ? 0 : Limit - 2; @@ -909,13 +983,28 @@ private: return Limit; } - bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I, + bool nextTwoLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I, unsigned Limit) { if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore) return false; return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit; } + bool nextNLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I, + ArrayRef<AnnotatedLine *>::const_iterator E, + unsigned Limit) { + unsigned JoinedLength = 0; + for (const auto *J = I + 1; J != E; ++J) { + if ((*J)->First->MustBreakBefore) + return false; + + JoinedLength += 1 + (*J)->Last->TotalLength; + if (JoinedLength > Limit) + return false; + } + return true; + } + bool containsMustBreak(const AnnotatedLine *Line) { assert(Line->First); // Ignore the first token, because in this situation, it applies more to the @@ -943,9 +1032,9 @@ private: const FormatStyle &Style; const AdditionalKeywords &Keywords; - const SmallVectorImpl<AnnotatedLine *>::const_iterator End; + const ArrayRef<AnnotatedLine *>::const_iterator End; - SmallVectorImpl<AnnotatedLine *>::const_iterator Next; + ArrayRef<AnnotatedLine *>::const_iterator Next; const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines; }; @@ -1493,6 +1582,23 @@ static auto computeNewlines(const AnnotatedLine &Line, Newlines = 1; } + if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) { + // Modify empty lines after TT_NamespaceLBrace. + if (PreviousLine && PreviousLine->endsWith(TT_NamespaceLBrace)) { + if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never) + Newlines = 1; + else if (!Line.startsWithNamespace()) + Newlines = std::max(Newlines, 2u); + } + // Modify empty lines before TT_NamespaceRBrace. + if (Line.startsWith(TT_NamespaceRBrace)) { + if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never) + Newlines = 1; + else if (!PreviousLine->startsWith(TT_NamespaceRBrace)) + Newlines = std::max(Newlines, 2u); + } + } + // Insert or remove empty line before access specifiers. if (PreviousLine && RootToken.isAccessSpecifier()) { switch (Style.EmptyLineBeforeAccessModifier) { diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 654148a..3177172 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -51,9 +51,7 @@ void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line, << "T=" << (unsigned)I->Tok->getType() << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText << "\"] "; - for (SmallVectorImpl<UnwrappedLine>::const_iterator - CI = I->Children.begin(), - CE = I->Children.end(); + for (const auto *CI = I->Children.begin(), *CE = I->Children.end(); CI != CE; ++CI) { OS << "\n"; printLine(OS, *CI, (Prefix + " ").str()); @@ -394,7 +392,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, break; case tok::l_brace: if (InRequiresExpression) { - FormatTok->setFinalizedType(TT_RequiresExpressionLBrace); + FormatTok->setFinalizedType(TT_CompoundRequirementLBrace); } else if (FormatTok->Previous && FormatTok->Previous->ClosesRequiresClause) { // We need the 'default' case here to correctly parse a function @@ -1032,6 +1030,12 @@ void UnwrappedLineParser::parsePPDirective() { case tok::pp_pragma: parsePPPragma(); break; + case tok::pp_error: + case tok::pp_warning: + nextToken(); + if (!eof() && Style.isCpp()) + FormatTok->setFinalizedType(TT_AfterPPDirective); + [[fallthrough]]; default: parsePPUnknown(); break; @@ -1211,9 +1215,8 @@ void UnwrappedLineParser::parsePPPragma() { } void UnwrappedLineParser::parsePPUnknown() { - do { + while (!eof()) nextToken(); - } while (!eof()); if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) Line->Level += PPBranchLevel + 1; addUnwrappedLine(); @@ -1702,7 +1705,8 @@ void UnwrappedLineParser::parseStructuralElement( } for (const bool InRequiresExpression = - OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); + OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace, + TT_CompoundRequirementLBrace); !eof();) { if (IsCpp && FormatTok->isCppAlternativeOperatorKeyword()) { if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true); @@ -2041,7 +2045,9 @@ void UnwrappedLineParser::parseStructuralElement( ? FormatTok->NewlinesBefore > 0 : CommentsBeforeNextToken.front()->NewlinesBefore > 0; - if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) && + if (FollowedByNewline && + (Text.size() >= 5 || + (FunctionLike && FormatTok->isNot(tok::l_paren))) && tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) { if (PreviousToken->isNot(TT_UntouchableMacroFunc)) PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro); @@ -4788,8 +4794,7 @@ void UnwrappedLineParser::nextToken(int LevelDifference) { } void UnwrappedLineParser::distributeComments( - const SmallVectorImpl<FormatToken *> &Comments, - const FormatToken *NextTok) { + const ArrayRef<FormatToken *> &Comments, const FormatToken *NextTok) { // Whether or not a line comment token continues a line is controlled by // the method continuesLineCommentSection, with the following caveat: // @@ -5011,7 +5016,7 @@ void UnwrappedLineParser::readToken(int LevelDifference) { namespace { template <typename Iterator> void pushTokens(Iterator Begin, Iterator End, - llvm::SmallVectorImpl<FormatToken *> &Into) { + SmallVectorImpl<FormatToken *> &Into) { for (auto I = Begin; I != End; ++I) { Into.push_back(I->Tok); for (const auto &Child : I->Children) diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index b7daf8d..8160d5e 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -228,7 +228,7 @@ private: // NextTok specifies the next token. A null pointer NextTok is supported, and // signifies either the absence of a next token, or that the next token // shouldn't be taken into account for the analysis. - void distributeComments(const SmallVectorImpl<FormatToken *> &Comments, + void distributeComments(const ArrayRef<FormatToken *> &Comments, const FormatToken *NextTok); // Adds the comment preceding the next token to unwrapped lines. |