[clang] Dev trunk (PR #90590)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 30 03:52:19 PDT 2024
https://github.com/yash-kumar8 created https://github.com/llvm/llvm-project/pull/90590
Fix endline comment alignment, inline constructor definition alignment, variable name alignment with bit field
>From 6bc8456c9da364023905417c9fb35f9ad8067fa7 Mon Sep 17 00:00:00 2001
From: Vivek Pandey <vivek.pandey at tallysolutions.com>
Date: Tue, 27 Feb 2024 11:04:53 +0530
Subject: [PATCH 1/4] Merged changes to 19.0.0
---
clang/include/clang/Format/Format.h | 3 +
clang/lib/Format/ContinuationIndenter.cpp | 28 +-
clang/lib/Format/Format.cpp | 4 +
clang/lib/Format/FormatToken.cpp | 95 +-
clang/lib/Format/FormatToken.h | 853 +++++++++++++-
clang/lib/Format/FormatTokenLexer.cpp | 2 +
clang/lib/Format/TokenAnnotator.cpp | 598 +++++++++-
clang/lib/Format/TokenAnnotator.h | 102 +-
clang/lib/Format/UnwrappedLineFormatter.cpp | 134 ++-
clang/lib/Format/UnwrappedLineParser.cpp | 17 +
clang/lib/Format/WhitespaceManager.cpp | 1172 ++++++++++++++++++-
clang/lib/Format/WhitespaceManager.h | 62 +
clang/tools/clang-format/ClangFormat.cpp | 179 +++
13 files changed, 3227 insertions(+), 22 deletions(-)
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index e9b2160a7b9243..9c725320740982 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2249,6 +2249,9 @@ struct FormatStyle {
/// \version 3.7
unsigned ColumnLimit;
+ /// TALLY: The extended column limit
+ unsigned ColumnLimitExtended = 9999;
+
/// A regular expression that describes comments with special meaning,
/// which should not be split into lines or otherwise changed.
/// \code
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 159d130cb67332..9aa7afcec7fe75 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -627,6 +627,30 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
if (State.NoContinuation)
return true;
+ // TALLY : By default the newlines are honored. For few cases
+ // like start of function definition and conditional
+ // and loop expressions should have a rigid frame.
+ FormatToken *tokenlast;
+ FormatToken *tokenfirst;
+
+ if (State.Line)
+ tokenlast = State.Line->Last;
+ tokenfirst = State.Line->First;
+
+ if (tokenfirst && tokenfirst->isOneOf(tok::kw_else, tok::kw_while, tok::kw_do, tok::kw_if, tok::kw_for))
+ return !(State.NextToken->LparenCount == State.NextToken->RparenCount);
+
+ if (tokenlast && tokenlast->isTrailingComment())
+ tokenlast = tokenlast->getPreviousNonComment();
+
+ if (tokenfirst && tokenfirst->is(tok::r_brace) &&
+ tokenlast && tokenlast->isOneOf(tok::l_brace, tok::semi)) {
+
+ if (tokenfirst->getNextNonComment () &&
+ tokenfirst->getNextNonComment ()->isOneOf (tok::kw_else, tok::kw_while))
+ return !(State.NextToken->LparenCount == State.NextToken->RparenCount);
+ }
+
return false;
}
@@ -1392,6 +1416,8 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return CurrentState.ColonPos - NextNonComment->ColumnWidth;
return CurrentState.Indent;
}
+ //if (NextNonComment->isOneOf(tok::colon, TT_CtorInitializerColon) && Current.is(tok::r_paren)) // TALLY
+ // return CurrentState.Indent;
if (NextNonComment->is(tok::colon) && NextNonComment->is(TT_ObjCMethodExpr))
return CurrentState.ColonPos;
if (NextNonComment->is(TT_ArraySubscriptLSquare)) {
@@ -1453,7 +1479,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
NextNonComment->SpacesRequiredBefore;
}
if (CurrentState.Indent == State.FirstIndent && PreviousNonComment &&
- !PreviousNonComment->isOneOf(tok::r_brace, TT_CtorInitializerComma)) {
+ !PreviousNonComment->isOneOf(tok::r_brace, TT_CtorInitializerComma, tok::kw_constexpr)) { // TALLY: , tok::kw_constexpr
// Ensure that we fall back to the continuation indent width instead of
// just flushing continuations left.
return CurrentState.Indent + Style.ContinuationIndentWidth;
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 56cd9495920c7b..0e77b0a620df6e 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -2402,6 +2402,10 @@ class Formatter : public TokenAnalyzer {
tooling::Replacements Result;
deriveLocalStyle(AnnotatedLines);
AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
+ // TALLY: Add Tally-specific information to all annotated lines
+ for (AnnotatedLine *Line : AnnotatedLines)
+ Annotator.calculateTallyInformation(*Line);
+
for (AnnotatedLine *Line : AnnotatedLines)
Annotator.calculateFormattingInformation(*Line);
Annotator.setCommentLineLevels(AnnotatedLines);
diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp
index b791c5a26bbe3a..f63be2aad054b4 100644
--- a/clang/lib/Format/FormatToken.cpp
+++ b/clang/lib/Format/FormatToken.cpp
@@ -11,8 +11,10 @@
/// roles.
///
//===----------------------------------------------------------------------===//
-
+// clang-format off
#include "FormatToken.h"
+///TALLY : Need for one function.
+#include "TokenAnnotator.h"
#include "ContinuationIndenter.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Debug.h"
@@ -71,6 +73,97 @@ bool FormatToken::isSimpleTypeSpecifier() const {
}
}
+/// TALLY: To check if the preceding set of tokens are Template type. If need to optimize, then
+/// can dumb this function with compromise of inserting a new line.
+bool FormatToken::isAfterNoDiscardOrNoReturnOrTemplate(unsigned & newlinescount) const {
+
+ const FormatToken * logicalfirst = nullptr;
+
+ /// If the line is of type [[...]] template <...> ...
+
+ if (this->is(tok::greater)) {
+
+ /// Basically skip the attribute part.
+ if (this->MyLine->First->is(tok::l_square)) {
+ logicalfirst = this->MyLine->First;
+
+ while (logicalfirst) {
+ if (logicalfirst->is(tok::kw_template))
+ break;
+ logicalfirst = logicalfirst->getNextNonComment();
+ }
+ }
+ /// Else if the line is of type template <...> ...
+ else if (this->MyLine->First->is(tok::kw_template))
+ logicalfirst = this->MyLine->First;
+
+ if (logicalfirst) {
+ if (this->Next == logicalfirst->walkTemplateBlockInClassDecl () && this->Next->is(tok::kw_friend) == false)
+ newlinescount = 1;
+
+ return logicalfirst->is(tok::kw_template);
+ }
+ }
+
+ /// Cant start from first since the line can be of type template <...> [[...]] ...
+ if ( this->is(tok::r_square) &&
+ (this->Previous && this->Previous->is (tok::r_square)) &&
+ ((this->Previous->Previous && this->Previous->Previous->TokenText.startswith ("nodiscard")) ||
+ (this->Previous->Previous && this->Previous->Previous->TokenText.startswith ("noreturn"))) &&
+ (this->Previous->Previous->Previous && this->Previous->Previous->Previous->is (tok::l_square)) &&
+ (this->Previous->Previous->Previous->Previous && this->Previous->Previous->Previous->Previous->is (tok::l_square))
+ ) {
+
+ newlinescount = 1;
+ return true;
+ }
+
+ return false;
+}
+
+//TALLY: Helper function to check if the lbrace is part of a constexpr
+bool FormatToken::isLBraceOfConstexprOrVarDelcOrDef() const {
+
+
+ if (is(tok::l_brace)) {
+ FormatToken * prev = getPreviousNonComment();
+ FormatToken * scopevar = nullptr;
+
+ while (prev) {
+ if (prev->is(tok::kw_constexpr))
+ return true;
+
+ if (prev->isOneOf (tok::kw_class, tok::kw_struct, tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_else, tok::kw_union))
+ return false;
+
+ if (prev->MyLine && prev->MyLine->First && prev->MyLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_else, tok::kw_for))
+ return false;
+
+ if (prev->is(tok::coloncolon))
+ scopevar = prev;
+
+ prev = prev->getPreviousNonComment();
+ }
+
+ if (scopevar) {
+ FormatToken * prevtoscope = scopevar->getPreviousNonComment();
+ if (prevtoscope)
+ if (prevtoscope->isDatatype())
+ return true;
+ }
+
+ prev = getPreviousNonComment();
+
+ if (prev) {
+ prev = prev->getPreviousNonComment();
+ if(prev && prev->isDatatype())
+ return true;
+ }
+
+ }
+ return false;
+}
+
bool FormatToken::isTypeOrIdentifier() const {
return isSimpleTypeSpecifier() || Tok.isOneOf(tok::kw_auto, tok::identifier);
}
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 0c1dce7a294082..3b6ae1949252ce 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -11,7 +11,7 @@
/// around Token with additional information related to formatting.
///
//===----------------------------------------------------------------------===//
-
+// clang-format off
#ifndef LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H
#define LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H
@@ -594,6 +594,793 @@ struct FormatToken {
/// cases in which we treat parents as block-openers for now.
bool MacroParent = false;
+ /// TALLY: Whether the token is part of a line which contains a semi-colon
+ bool HasSemiColonInLine = false;
+
+ /// TALLY: Token size for columnarization
+ size_t PrevTokenSizeForColumnarization = 0;
+
+ /// TALLY: If this token is part of a PP conditional inclusion
+ bool IsPPConditionalInclusionScope = false;
+
+ /// TALLY: If this token is part of a struct scope
+ bool IsStructScope = false;
+
+ /// TALLY: If this token is part of a union scope
+ bool IsUnionScope = false;
+
+ /// TALLY: If this token is part of a class scope
+ bool IsClassScope = false;
+
+ /// TALLY: If this token is part of a enum scope
+ bool IsEnumScope = false;
+
+ /// TALLY: If part of function definition line.
+ bool IsFunctionDefinitionLine = false;
+
+ /// TALLY: If in function definition scope.
+ bool IsInFunctionDefinitionScope = false;
+
+ /// TALLY: Name of the struct (if any) this token is scoped under
+ StringRef StructScopeName = "<StructScopeName_None>";
+
+ /// TALLY: Name of the class (if any) this token is scoped under
+ StringRef ClassScopeName = "<ClassScopeName_None>";
+
+ /// TALLY: L-Brace count
+ unsigned LbraceCount = 0;
+
+ /// TALLY: R-Brace count
+ unsigned RbraceCount = 0;
+
+ /// TALLY: L-Paren count
+ unsigned LparenCount = 0;
+
+ /// TALLY: R-Paren count
+ unsigned RparenCount = 0;
+
+ /// TALLY: L-Paren count
+ unsigned LArrowCount = 0;
+
+ /// TALLY: R-Paren count
+ unsigned RArrowCount = 0;
+
+ /// TALLY: A weight to determine whether line break in the original must be enforced
+ unsigned OriginalLineBreakWeight = 0;
+
+ /// TALLY: The owning line
+ mutable AnnotatedLine* MyLine = nullptr;
+
+ /// TALLY: If this token is a datatype
+ bool IsDatatype = false;
+
+ /// TALLY: If this token in an interim token between a datatype and variable name
+ bool IsInterimBeforeName = false;
+
+ /// TALLY: If this token in a RHS token after an equals, unary/binary operator or member access
+ bool IsRhsToken = false;
+
+ /// TALLY: If this token in a variable name with datatype
+ bool IsVariableNameWithDatatype = false;
+
+ /// TALLY: If this token in a variable name without datatype
+ bool IsVariableNameWithoutDatatype = false;
+
+ /// TALLY: If this token in a function name
+ bool IsFunctionName = false;
+
+ /// TALLY: If this token in part of content inside arrow braces of expression of type template<...>
+ bool IsInTemplateLine = false;
+
+ /// TALLY: If the code is in clang off region then no formatting applied
+ static bool sCodeInFormatOffRegion;
+ bool CodeInFormatOffRegion;
+
+ // TALLY: Previous non-comment token is
+ bool prevNonCommIs(tok::TokenKind Kind) const {
+ FormatToken* prevNonComm = getPreviousNonComment();
+ return (prevNonComm && prevNonComm->is(Kind));
+ }
+
+ // TALLY: Helper function
+ bool isPPKeywordAndPrevHash() const {
+ const FormatToken* MyPrev = getPreviousNonComment();
+ if (MyPrev && MyPrev->is(tok::hash)) {
+ return isOneOf(
+ tok::pp_if, tok::pp_ifdef, tok::pp_ifndef,
+ tok::pp_elif, tok::pp_else, tok::pp_endif,
+ tok::pp_defined, tok::pp_include, tok::pp___include_macros,
+ tok::pp_define, tok::pp_undef, tok::pp_error,
+ tok::pp_pragma
+ );
+ }
+ else {
+ return false;
+ }
+ }
+
+ // TALLY: Helper function
+ bool isPPDefineKeywordAndPrevHash() const {
+ const FormatToken* MyPrev = getPreviousNonComment();
+ if (MyPrev && MyPrev->is(tok::hash)) {
+ return is(tok::pp_define);
+ }
+ else {
+ return false;
+ }
+ }
+
+ // TALLY: Helper function
+ bool isPPConditionalInclusionStart() const {
+ //return false;
+ // True for '#' preceding and there-on
+ const FormatToken* MyNext = getNextNonComment();
+ return MyNext && MyNext->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef);
+ }
+
+ // TALLY: Helper function
+ bool isPPConditionalInclusionEnd() const {
+ return is(tok::pp_endif);
+ }
+
+ // TALLY: Helper function
+ bool isTallyMemMgrMacro() const {
+ return
+ TokenText.startswith("NO_POOL") ||
+ TokenText.startswith("USE_MALLOC_POOL") ||
+ TokenText.startswith("USE_CALLOC_POOL");
+ }
+
+ // TALLY: Helper function
+ bool isTallyTrace() const {
+ return TokenText.startswith("TRACEFUNC");
+ }
+
+ // TALLY: Helper function
+ bool isFunctionName() const {
+ bool startOfName = false;
+ if (is(TT_StartOfName)) {
+ startOfName = true;
+ if (TokenText.contains("WINAPI")) {
+ startOfName = strcmp(TokenText.begin(), "WINAPI") == 0;
+ }
+ }
+ bool rc = (startOfName || is(TT_FunctionDeclarationName) || is(tok::kw_operator)
+ || (Previous && Previous->is(tok::kw_operator)));
+ return rc;
+ }
+
+ // TALLY: Helper function
+ bool isPointerOrRef() const {
+ return is(TT_PointerOrReference);
+ }
+
+ // TALLY: Helper function
+ bool isLeftParen() const {
+ return is(tok::l_paren) || (Previous && Previous->is(tok::kw_operator)); // && (isOperatorFunction() || is(tok::l_paren)))
+ }
+
+ // TALLY: Helper function
+ // Type specifiers
+ // TODO: Add support for C++ attributes like '[[nodiscard]]'
+ bool isDatatypeInner() const {
+ return (is(tok::identifier) || isSimpleTypeSpecifier() || is(tok::kw_auto)) &&
+ !(TokenText.startswith("CALLOC") ||
+ TokenText.startswith("MALLOC") ||
+ TokenText.startswith("WINAPI") ||
+ TokenText.startswith("nodiscard") ||
+ TokenText.startswith("noreturn") ||
+ TokenText.startswith("maybe_unused"));
+ }
+
+ // TALLY: Helper function
+ // TODO: 'consteval', 'constinit'
+ bool isDeclarationSpecifier() const {
+ return (isOneOf(
+ tok::kw_static, tok::kw_virtual, tok::kw_inline,
+ tok::kw_friend, tok::kw_volatile, tok::kw_const,
+ tok::kw_constexpr, tok::kw_explicit, tok::kw_register,
+ tok::kw_thread_local, tok::kw_extern, tok::kw_mutable,
+ tok::kw_alignas
+ )) ? true : false;
+ }
+
+ // TALLY: Helper function
+ bool isDeclSpecStaticOrVirtual() const {
+ return (isOneOf(tok::kw_static, tok::kw_virtual)) ? true : false;
+ }
+
+ //TALLY: To check if the preceding set of tokens are Template type.
+ bool isDeclSpecInlineOrExtern() const {
+ return (isOneOf(tok::kw_inline, tok::kw_extern)) ? true : false;
+ }
+
+ //TALLY: to check if the block is a template specifier or not.
+ const FormatToken * walkTemplateBlockInClassDecl() const {
+ int bracecount = 0;
+ const FormatToken *next = this->getNextNonComment();
+
+ if (this->is(tok::kw_template) && next && next->is(tok::less)) {
+ do {
+ if (next && next->is(tok::less))
+ ++bracecount;
+
+ if (next && next->is(tok::greater))
+ --bracecount;
+
+ next = next->getNextNonComment();
+ } while (bracecount && next);
+
+ if (bracecount == 0)
+ return next;
+ }
+
+ return nullptr;
+ }
+
+ //TALLY: To check if the preceding set of tokens are Template type.
+ bool isAfterNoDiscardOrNoReturnOrTemplate (unsigned & newlineCount) const;
+
+ //TALLY: To check if the friend declaration is for a templatized type..
+ bool isTemplatizedFriendSpecifier() const {
+ const FormatToken * next = walkTemplateBlockInClassDecl ();
+
+ return (next && next->is(tok::kw_friend));
+ }
+
+ //TALLY : To check if the current block start from 'this' is maybe_unused.
+ bool isMaybeUnused() const {
+ if (this->is(tok::l_square)) {
+
+ const FormatToken *next = this->getNextNonComment();
+
+ if (next && next->is(tok::l_square)) {
+
+ next = next->getNextNonComment();
+ if (next && (next->TokenText.startswith ("maybe_unused"))) {
+
+ next = next->getNextNonComment();
+ if (next && next->is(tok::r_square)) {
+
+ next = next->getNextNonComment();
+
+ if (next && next->is(tok::r_square)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ //TALLY: To check if the current set of subsequent tokens are Template type.
+ bool isNoDiscardOrNoReturnOrTemplate() const {
+ if (walkTemplateBlockInClassDecl () != nullptr) {
+
+ return true;
+ }
+
+ if (this->is(tok::l_square)) {
+
+ const FormatToken *next = this->getNextNonComment();
+
+ if (next && next->is(tok::l_square)) {
+
+ next = next->getNextNonComment();
+ if (next && (next->TokenText.startswith ("nodiscard") || next->TokenText.startswith ("noreturn"))) {
+
+ next = next->getNextNonComment();
+ if (next && next->is(tok::r_square)) {
+
+ next = next->getNextNonComment();
+ return next && next->is(tok::r_square);
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // TALLY: Helper function
+ bool isDatatype() const {
+ if (!isDeclarationSpecifier()) {
+ return isDatatypeInner();
+ }
+ else {
+ // Declaration specifiers should precede datatype, but occasionally could be after datatype
+ FormatToken* MyPrev = getPreviousNonComment();
+ return (MyPrev) ? MyPrev->isDatatypeInner() : false;
+ }
+ }
+
+ // TALLY: Helper function
+ bool isPointerOrRefOrDatatypeOrKeyword() const {
+ return (isPointerOrRef() || isDatatype() || TokenText.startswith("WINAPI"));
+ }
+
+ // TALLY: Helper function
+ bool isFunctionNameAndPrevIsPointerOrRefOrDatatype() const {
+ FormatToken * MyPrev = getPreviousNonComment();
+
+ if (MyPrev != nullptr && MyPrev->isPointerOrRefOrDatatypeOrKeyword())
+ return isFunctionAndNextLeftParen();
+ else if (MyPrev != nullptr) {
+ return (isFunctionAndNextLeftParen() &&
+ ((MyPrev->is(tok::kw_const) && MyPrev->Previous && MyPrev->Previous->isPointerOrRef()) ||
+ (MyPrev->is(tok::kw_operator))));
+ }
+
+ return false;
+ //return (isFunctionAndNextLeftParen() && MyPrev != nullptr && MyPrev->isPointerOrRefOrDatatypeOrKeyword());
+ }
+
+ // TALLY: Helper function
+ bool isClassOrStructNamed() const {
+ return
+ (IsClassScope && TokenText.startswith(ClassScopeName))
+ ||
+ (IsStructScope && TokenText.startswith(StructScopeName));
+ }
+
+ // TALLY: Helper function
+ bool isCtorOrDtor() const {
+ const FormatToken * MyPrev = getPreviousNonComment();
+ bool isdtor {};
+
+ if (MyPrev && !MyPrev->is(tok::kw_constexpr)) {
+ isdtor = MyPrev->is(tok::tilde);
+
+ if (!isdtor)
+ return false;
+ }
+
+ if (IsClassScope) {
+ return (ClassScopeName.equals (TokenText));
+ }
+
+ if (isdtor) {
+ bool isTemplateClassIndicator = false;
+
+ do {
+ MyPrev = MyPrev->getPreviousNonComment();
+
+ if (MyPrev) {
+ if (MyPrev->isOneOf(tok::coloncolon, tok::coloncolon))
+ continue;
+ else if (MyPrev->is(tok::greater)) {
+ isTemplateClassIndicator = true;
+ continue;
+ }
+ else if (MyPrev->is(tok::less)) {
+ if (!isTemplateClassIndicator)
+ return false;
+
+ MyPrev = MyPrev->getPreviousNonComment();
+
+ if (MyPrev && MyPrev->is(tok::identifier)) {
+ StringRef clsnm(TokenText);
+
+ return (clsnm.equals(TokenText));
+ }
+ }
+ else if (MyPrev->is(tok::identifier)) {
+ StringRef clsnm(TokenText);
+
+ if (clsnm.equals(TokenText))
+ return true;
+
+ if (!isTemplateClassIndicator)
+ return false;
+ }
+ }
+ } while (MyPrev);
+
+ return false;
+ }
+
+ // Check if this is the constructor definition
+ const FormatToken * Nxt = getNextNonComment();
+ while (Nxt) {
+ if (Nxt->is(tok::coloncolon) && Nxt->Next && Nxt->Next->Next && Nxt->Next->Next->is(tok::l_paren)) {
+ if (Nxt->Next == nullptr)
+ return false;
+
+ StringRef nxtToNextTkn(Nxt->Next->TokenText);
+ bool isEql = nxtToNextTkn.equals(TokenText);
+
+ return isEql;
+ }
+ Nxt = Nxt->Next;
+ }
+
+ //if (getNextNonComment() && getNextNonComment()->getNextNonComment()) {
+ // StringRef nxtToNextTkn(getNextNonComment()->getNextNonComment()->TokenText);
+ // bool isEql = nxtToNextTkn.equals(TokenText);
+
+ // return isEql;
+ //}
+
+ return false;
+ }
+
+ // TALLY: Helper function
+ bool isConstructor() const {
+ const FormatToken* MyPrev = getPreviousNonComment();
+
+ if (MyPrev && !MyPrev->isOneOf (tok::kw_constexpr, tok::greater)) {
+ return false;
+ }
+
+ const FormatToken * MyNext = getNextNonComment ();
+ static const StringRef funbrace ("(");
+
+ if (IsClassScope && MyNext && MyNext->TokenText.equals(funbrace)) {
+ return (ClassScopeName.equals (TokenText));
+ }
+
+ return false;
+ }
+
+ // TALLY: Helper function
+ bool isDestructor() const {
+ const FormatToken* MyNext = getNextNonComment();
+ if (is(tok::tilde) && MyNext) {
+ if (IsClassScope) {
+ return (MyNext->ClassScopeName.equals (MyNext->TokenText));
+ }
+ }
+
+ return false;
+ }
+
+ // TALLY: Helper function
+ bool isFunctionOrCtorOrDtor() const {
+ bool rc =
+ isFunctionNameAndPrevIsPointerOrRefOrDatatype() ||
+ isConstructor() ||
+ isDestructor();
+ return rc;
+ }
+
+ // TALLY: Helper function
+ bool isFunctionOrCtorOrPrevIsDtor() const {
+ const FormatToken* MyPrev = getPreviousNonComment();
+ bool rc =
+ isFunctionNameAndPrevIsPointerOrRefOrDatatype() ||
+ isConstructor() ||
+ (MyPrev && MyPrev->isDestructor());
+ return rc;
+ }
+
+ // TALLY: Helper function
+ bool isPrevBeforeInterimsVarWithoutDatatype() const {
+ const FormatToken* MyPrev = getPreviousNonComment();
+ while (MyPrev && !MyPrev->IsVariableNameWithoutDatatype) {
+ MyPrev = MyPrev->getPreviousNonComment();
+ }
+ return (MyPrev && MyPrev->IsVariableNameWithoutDatatype);
+ }
+
+ // TALLY: Is the previous or previous-to-previous token a variable name without datatype
+ bool isPrevOrPrev2VarWithoutDatatype() const {
+ const FormatToken* MyPrev = getPreviousNonComment();
+ if (MyPrev == nullptr) {
+ return false;
+ }
+
+ const FormatToken* MyPrev2 = MyPrev->getPreviousNonComment();
+ if (MyPrev->IsVariableNameWithoutDatatype || MyPrev2 == nullptr) {
+ return true;
+ }
+
+ if (MyPrev2 && MyPrev2->IsVariableNameWithoutDatatype) {
+ return true;
+ }
+
+ return false;
+ }
+
+ // TALLY: Is this token a variable name without datatype.
+ /*
+ bool isVarNameWithoutDatatype() const {
+ bool prevOk = false;
+ bool nextOk = false;
+ if (is(tok::identifier)) {
+ const FormatToken* MyPrev = getPreviousNonComment();
+ if (MyPrev == nullptr) {
+ prevOk = true;
+ }
+ else {
+ // Star shall be isPointerOrRef() but could also be TT_UnaryOperator instead, so
+ // explicitly check for tok::star also
+ if (MyPrev->isPointerOrRef() || MyPrev->is(tok::star)) {
+ const FormatToken* MyPrev2 = MyPrev->getPreviousNonComment();
+ if (MyPrev2 == nullptr) {
+ prevOk = true;
+ }
+ else if (!MyPrev2->isDatatype()) {
+ prevOk = true;
+ }
+ }
+ else if (!MyPrev->isDatatype()) {
+ prevOk = true;
+ }
+ }
+ // Next may be tok::equal or next-to-next (eg. *pointer++ = something)
+ const FormatToken* MyNext = getNextNonComment();
+ if (MyNext) {
+ if (MyNext->is(tok::equal)) {
+ nextOk = true;
+ }
+ else {
+ const FormatToken* MyNext2 = MyNext->getNextNonComment();
+ if (MyNext2->is(tok::equal)) {
+ nextOk = true;
+ }
+ }
+ }
+ }
+ return prevOk && nextOk;
+ }
+ */
+
+ // TALLY: Helper function
+ bool isFunctionAndNextLeftParen() const {
+ const FormatToken* MyNext = getNextNonComment();
+ if (MyNext) {
+ return isFunctionName() && MyNext->isLeftParen();
+ }
+ return false;
+ }
+
+ // TALLY: Helper function
+ bool isFunctionNameAfterInterims() const {
+ if (IsFunctionName)
+ return true;
+
+ const FormatToken* MyNext = getNextNonComment();
+
+ while (MyNext && MyNext->IsInterimBeforeName) {
+ MyNext = MyNext->getNextNonComment();
+ }
+
+ if (MyNext && MyNext->IsFunctionName)
+ return true;
+
+ return false;
+ }
+
+ // TALLY: Helper function
+ bool isMemberVariableNameAfterInterims() const {
+ if (isMemberVarNameInDecl())
+ return true;
+
+ const FormatToken* MyNext = getNextNonComment();
+
+ while (MyNext && MyNext->IsInterimBeforeName) {
+ MyNext = MyNext->getNextNonComment();
+ }
+
+ if (MyNext && MyNext->isMemberVarNameInDecl())
+ return true;
+
+ return false;
+ }
+
+ // TALLY: Helper function
+ /*
+ bool isFunctionAndNextLeftParenAfterZeroOrMoreInterimTokensInLine() const {
+ if (isFunctionAndNextLeftParen())
+ return true;
+
+ const FormatToken* MyNext = getNextNonComment();
+
+ if (MyNext && MyNext->isFunctionAndNextLeftParen())
+ return true;
+
+ while (MyNext && !MyNext->isFunctionAndNextLeftParen()) {
+ if (MyNext->isOneOf(tok::star, tok::amp, tok::l_square, tok::r_square, tok::numeric_constant) || MyNext->isPointerOrRef()) {
+ MyNext = MyNext->getNextNonComment();
+ if (MyNext && MyNext->isFunctionAndNextLeftParen())
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ return false;
+ }
+ */
+
+ // TALLY: Helper function
+ bool isPointerOrRefAndNextIsFunctionAndNextNextLeftParen() const {
+ const FormatToken* MyNext = getNextNonComment();
+ if (MyNext) {
+ return isPointerOrRef() && MyNext->isFunctionAndNextLeftParen();
+ }
+ return false;
+ }
+
+ // TALLY: Helper function
+ /*
+ bool isMemberVarNameInDeclAfterZeroOrMoreInterimTokensInLine() const {
+ if (isMemberVarNameInDecl())
+ return true;
+
+ const FormatToken* MyNext = getNextNonComment();
+
+ if (MyNext && MyNext->isMemberVarNameInDecl())
+ return true;
+
+ if (is(tok::less)) {
+ while (MyNext && !MyNext->is(tok::greater)) {
+ MyNext = MyNext->getNextNonComment();
+ }
+ if (MyNext && MyNext->is(tok::greater)) {
+ MyNext = MyNext->getNextNonComment();
+ return MyNext->isMemberVarNameInDecl();
+ }
+ }
+ else {
+ while (MyNext && !MyNext->isMemberVarNameInDecl()) {
+ if (MyNext->isOneOf(tok::star, tok::amp, tok::l_square, tok::r_square, tok::numeric_constant) || MyNext->isPointerOrRef()) {
+ MyNext = MyNext->getNextNonComment();
+ if (MyNext && MyNext->isMemberVarNameInDecl())
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+
+ return false;
+ }
+ */
+
+ // TALLY: Is this token a class or struct member variable name
+ bool isMemberVarNameInDecl() const {
+ if (!HasSemiColonInLine || (!(IsClassScope || IsStructScope)) || LbraceCount == 0)
+ return false;
+
+ return IsVariableNameWithDatatype;
+ }
+
+ // TALLY: Is this token a non-member (local) variable name
+ bool isNonMemberVarNameInDecl() const {
+ if (!HasSemiColonInLine || IsClassScope || IsStructScope || LbraceCount == 0)
+ return false;
+
+ return IsVariableNameWithDatatype;
+ }
+
+ // TALLY: Is this token a variable name, with an earlier token being
+ // pointer or reference or data type, and following token being a
+ // semi-colon, equals, square left bracket, comma, parens, braces or colon.
+ bool isVarNameInDecl() const {
+ if (isMemberVarNameInDecl())
+ return false;
+
+ bool prevOk = false;
+ bool nextOk = false;
+ if (is(tok::identifier)) {
+ const FormatToken* MyPrev = getPreviousNonComment();
+ if (MyPrev) {
+ if (MyPrev->isDatatype()) {
+ prevOk = true;
+ }
+ else if (MyPrev && (MyPrev->isDatatype() || MyPrev->isPointerOrRef())) {
+ prevOk = true;
+ }
+ else if (MyPrev && (MyPrev->is(tok::coloncolon)) && MyPrev->Previous && MyPrev->Previous->is(tok::identifier)) {
+ prevOk = true;
+ }
+ else if (MyPrev->IsInterimBeforeName) {
+ while (MyPrev && MyPrev->IsInterimBeforeName)
+ MyPrev = MyPrev->getPreviousNonComment();
+
+ // Also support pointer-to-pointer i.e. two or more levels of indirection. Suffices to stop after two-level checking.
+ if (MyPrev && (MyPrev->isDatatype() || MyPrev->isPointerOrRef())) {
+ prevOk = true;
+ }
+ }
+ }
+ const FormatToken* MyNext = getNextNonComment();
+ if (MyNext) {
+ if (MyNext->isOneOf(tok::equal, tok::semi, tok::l_square, tok::comma, tok::r_paren)) {
+ nextOk = true;
+ }
+ else if (!IsClassScope && MyNext->is(tok::l_paren) && MyNext->MatchingParen) {
+ nextOk = true;
+ }
+ else if (MyNext->is(tok::l_brace) && MyNext->MatchingParen) {
+ nextOk = true;
+ }
+ else if (MyNext->is(tok::colon)) {
+ const FormatToken* MyNext2 = MyNext->getNextNonComment();
+ if (MyNext2 && MyNext2->is(tok::numeric_constant)) {
+ nextOk = true;
+ }
+ }
+ }
+ }
+ /*else if (is(tok::r_square)) {
+ const FormatToken* MyPrev = getPreviousNonComment();
+ while (MyPrev && !MyPrev->is(tok::l_square)) {
+ MyPrev = MyPrev->getPreviousNonComment();
+ }
+ if (MyPrev && MyPrev->is(tok::l_square)) {
+ MyPrev = MyPrev->getPreviousNonComment();
+ if (MyPrev) {
+ return MyPrev->isVarNameInDecl();
+ }
+ }
+ }*/
+
+ return prevOk && nextOk;
+ }
+
+ // TALLY: Is this token a scoped variable name eg. Something::SomethingElse a
+ bool isScopedVarNameInDecl() const {
+ if (isMemberVarNameInDecl())
+ return false;
+
+ bool prevOk = false;
+ bool nextOk = false;
+ if (is(tok::identifier)) {
+ const FormatToken* MyPrev = getPreviousNonComment();
+ if (MyPrev) {
+ if (MyPrev->isDatatype()) {
+ prevOk = true;
+ }
+ else if (MyPrev->isPointerOrRef()) {
+ const FormatToken* MyPrevPrev = MyPrev->getPreviousNonComment();
+ if (MyPrevPrev && MyPrevPrev->isDatatype()) {
+ prevOk = true;
+ }
+ }
+ }
+ const FormatToken* MyNext = getNextNonComment();
+ if (MyNext) {
+ if (MyNext->is(tok::coloncolon)) {
+ const FormatToken* MyNext2 = MyNext->getNextNonComment();
+ if (MyNext2) {
+ const FormatToken* MyNext3 = MyNext2->getNextNonComment();
+ if (MyNext3 && MyNext3->isOneOf(tok::equal, tok::semi, tok::l_square, tok::comma, tok::l_brace)) {
+ nextOk = true;
+ }
+ }
+ }
+ }
+ }
+ return prevOk && nextOk;
+ }
+
+ //TALLY: Helper function to check if the lbrace is part of a constexpr
+ bool isLBraceOfConstexprOrVarDelcOrDef() const;
+
+ /// TALLY: Helper function
+ bool isParenScoped() const {
+ return (LparenCount - RparenCount == 1);
+ }
+
+ /// TALLY: Helper function
+ bool isNotScoped() const {
+ return (LbraceCount == 0);
+ }
+
+ /// TALLY: Returns the next token ignoring comments.
+ FormatToken* getNextNonCommentNonConst() const {
+ FormatToken* Tok = Next;
+ while (Tok && Tok->is(tok::comment))
+ Tok = Tok->Next;
+ return Tok;
+ }
+
bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }
bool is(TokenType TT) const { return getType() == TT; }
bool is(const IdentifierInfo *II) const {
@@ -856,6 +1643,22 @@ struct FormatToken {
void copyFrom(const FormatToken &Tok) { *this = Tok; }
+ // TALLY
+ FormatToken * MarkOperatorOverloadAsFunction () {
+ FormatToken * nxttkn = Next;
+
+ while (nxttkn && nxttkn->isOperatorFunction () && !nxttkn->is(tok::l_paren)) {
+ nxttkn->IsFunctionName = true;
+ nxttkn->Tok.setKind(tok::identifier);
+ nxttkn = nxttkn->Next;
+ }
+
+ if (nxttkn->is(tok::l_paren) == true)
+ return nxttkn->Previous;
+
+ return nxttkn;
+ }
+
private:
// Only allow copying via the explicit copyFrom method.
FormatToken(const FormatToken &) = delete;
@@ -886,6 +1689,54 @@ struct FormatToken {
return Previous->endsSequenceInternal(K1, Tokens...);
return is(K1) && Previous && Previous->endsSequenceInternal(Tokens...);
}
+
+ // TALLY
+ bool isOperatorFunction () const
+ {
+ switch (Tok.getKind()) {
+ case tok::l_square:
+ //case tok::r_square:
+ case tok::l_paren:
+ //case tok::r_paren:
+ case tok::amp:
+ case tok::ampamp:
+ case tok::ampequal:
+ case tok::star:
+ case tok::starequal:
+ case tok::plus:
+ case tok::plusplus:
+ case tok::plusequal:
+ case tok::minus:
+ case tok::arrow:
+ case tok::minusequal:
+ case tok::minusminus:
+ case tok::tilde:
+ case tok::exclaim:
+ case tok::exclaimequal:
+ case tok::slash:
+ case tok::slashequal:
+ case tok::percent:
+ case tok::percentequal:
+ case tok::less:
+ case tok::lessless:
+ case tok::lessequal:
+ case tok::spaceship:
+ case tok::greater:
+ case tok::greatergreater:
+ case tok::greaterequal:
+ case tok::greatergreaterequal:
+ case tok::caret:
+ case tok::caretequal:
+ case tok::pipe:
+ case tok::pipepipe:
+ case tok::pipeequal:
+ case tok::equal:
+ case tok::equalequal:
+ return true;
+ default:
+ return false;
+ }
+ }
};
class ContinuationIndenter;
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 036f7e6a4efc1e..8cb00ca30bf71d 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -1178,6 +1178,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
break;
case '\f':
case '\v':
+ // TALLY: Null character
+ case '\0':
Column = 0;
break;
case ' ':
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index ac876bf4442e95..890545b258c1e3 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -11,7 +11,7 @@
/// \c AnnotatedTokens out of \c FormatTokens with required extra information.
///
//===----------------------------------------------------------------------===//
-
+// clang-format off
#include "TokenAnnotator.h"
#include "FormatToken.h"
#include "clang/Basic/SourceManager.h"
@@ -1348,7 +1348,9 @@ class AnnotatingParser {
Tok->setType(TT_RangeBasedForLoopColon);
} else if (Contexts.back().ContextType == Context::C11GenericSelection) {
Tok->setType(TT_GenericSelectionColon);
- } else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
+ } else if (CurrentToken && (CurrentToken->is(tok::numeric_constant)
+ /// TALLY : The BitFied can be an identifier aswell.
+ || CurrentToken->is(tok::identifier))) {
Tok->setType(TT_BitFieldColon);
} else if (Contexts.size() == 1 &&
!Line.First->isOneOf(tok::kw_enum, tok::kw_case,
@@ -1364,8 +1366,10 @@ class AnnotatingParser {
FormatToken *PrevPrev = Prev->getPreviousNonComment();
if (!PrevPrev)
break;
- if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept))
+ if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept)) {
Tok->setType(TT_CtorInitializerColon);
+ Tok->SpacesRequiredBefore = 1;
+ }
} else {
Tok->setType(TT_InheritanceColon);
}
@@ -3750,10 +3754,591 @@ bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {
return false;
}
+// TALLY: Walk the line
+void TokenAnnotator::walkLine1(AnnotatedLine& Line) {
+ OriginalLineBreakWeight = 0;
+
+ // TALLY: Walk the line in backward direction looking for semi-colon
+ bool hasSemiColon = false;
+ FormatToken* MyToken0 = Line.Last;
+ if (MyToken0) {
+ for (MyToken0 = Line.Last; MyToken0 != nullptr && !hasSemiColon; MyToken0 = MyToken0->Previous) {
+ if (MyToken0->is(tok::semi)) {
+ hasSemiColon = true;
+ }
+ }
+ }
+
+ // TALLY: Walk the line in forward direction
+ FormatToken* MyToken = Line.First;
+ if (MyToken) {
+ for (; MyToken != nullptr; MyToken = MyToken->Next) {
+ // Compute state
+
+ // Populate Set if the line define a MACRO
+ if (MyToken->is(tok::hash) && MyToken->Next) {
+ StringRef defstr(STRDEFINETEXT);
+
+ if (MyToken->Next->TokenText.equals(defstr) && MyToken->Next->Next) {
+ string val(MyToken->Next->Next->TokenText.data(), MyToken->Next->Next->TokenText.size());
+
+ DefinedMacros.insert(val);
+ }
+ }
+
+ if (MyToken->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union, tok::kw_enum)) {
+ if (MyToken->is(tok::kw_class)) {
+ if (MyToken->Previous && MyToken->Previous->is(tok::kw_friend) == true ||
+ (Line.endsWith(tok::semi) && !(Line.endsWith(tok::semi, tok::r_brace))) ||
+ LArrowCount > 0)
+ continue;
+
+ IsClassScope = true;
+
+ const FormatToken * Next = MyToken->getNextNonComment();
+ if (Next) {
+
+ if (Next->is(tok::kw_alignas) && Next->Next && Next->Next->is(tok::l_paren)
+ && Next->Next->Next && Next->Next->Next->Next && Next->Next->Next->Next->is(tok::r_paren)
+ && Next->Next->Next->Next->Next) {
+
+ Next = Next->Next->Next->Next->Next;
+ if (Next->Next && (Next->Next->isOneOf(tok::l_brace, tok::colon) ||
+ (Next->Next->is(tok::kw___is_final) && Next->Next->Next && Next->Next->Next->isOneOf(tok::l_brace, tok::colon))))
+ Next = Next;
+ }
+
+ ClassScopeName = Next->TokenText;
+ }
+ }
+ if (MyToken->is(tok::kw_struct)) {
+ IsStructScope = true;
+ const FormatToken* Next = MyToken->getNextNonComment();
+ if (Next) {
+ StructScopeName = Next->TokenText;
+ }
+ }
+ if (MyToken->is(tok::kw_union)) {
+ IsUnionScope = true;
+ }
+ if (MyToken->is(tok::kw_enum)) {
+ MyToken->IsEnumScope = true;
+ if (MyToken->Next->is(tok::kw_class))
+ MyToken = MyToken->Next;
+
+ IsEnumScope = true;
+ }
+ }
+ else if (MyToken->is(TT_TemplateOpener)) {
+ if (MyToken->Previous && MyToken->Previous->is(tok::kw_template) && IsInTemplateLine == false) {
+ LArrowCount = 1;
+ MyToken->Previous->IsInTemplateLine = true;
+ IsInTemplateLine = true;
+ }
+ else if (IsInTemplateLine)
+ ++LArrowCount;
+ }
+ else if (MyToken->is(TT_TemplateCloser) && LArrowCount > 0) {
+ ++RArrowCount;
+
+ if (LArrowCount == RArrowCount) {
+ LArrowCount = RArrowCount = 0;
+ MyToken->IsInTemplateLine = true;
+ IsInTemplateLine = false;
+ if (MyToken->getNextNonComment() && IsFunctionDefinitionLine && LparenCount == 0)
+ MyToken->getNextNonCommentNonConst()->NewlinesBefore = 1;
+ }
+ }
+ else if (MyToken->is(tok::l_brace)) {
+ LbraceCount++;
+ if (LparenCount == RparenCount && IsFunctionDefinitionLine)
+ IsFunctionDefinitionLine = false;
+ }
+ else if (MyToken->is(tok::r_brace)) {
+ RbraceCount++;
+
+ if (RbraceCount == LbraceCount) {
+ LbraceCount = 0;
+ RbraceCount = 0;
+
+ if (IsClassScope) {
+ IsClassScope = false;
+ }
+
+ if (IsStructScope) {
+ IsStructScope = false;
+ }
+
+ if (IsUnionScope) {
+ IsUnionScope = false;
+ }
+
+ if (IsEnumScope) {
+ MyToken->IsEnumScope = IsEnumScope;
+ if(MyToken->Next && MyToken->Next->is(tok::semi))
+ MyToken->Next->IsEnumScope = true;
+ IsEnumScope = false;
+ }
+
+ if (IsInFunctionDefinition) {
+ IsInFunctionDefinition = false;
+ }
+ }
+ }
+ else if (MyToken->is(tok::l_paren)) {
+ LparenCount++;
+
+ // Dont add weight for if/while statements.
+ if (MyToken->getPreviousNonComment() && MyToken->getPreviousNonComment()->isOneOf(tok::kw_if, tok::kw_while) == false)
+ OriginalLineBreakWeight += 2;
+
+ // Add additional weight for a function declaration
+ if (hasSemiColon) {
+ const FormatToken* MyPrev = MyToken->getPreviousNonComment();
+ if (MyPrev && MyPrev->isFunctionOrCtorOrPrevIsDtor()) {
+ OriginalLineBreakWeight += 5;
+ }
+ }
+
+ if (IsFunctionDefinitionLine) {
+ FormatToken* MyPrev = MyToken->Previous;
+
+ if (MyPrev) {
+ if (MyPrev->Previous && MyPrev->Previous->is(tok::coloncolon)) {
+ MyPrev = MyPrev->Previous->Previous;
+
+ if (MyPrev && MyPrev->is(tok::greater)) {
+
+ int arrowcount = 0;
+ do {
+ if (MyPrev->is(tok::greater))
+ ++arrowcount;
+ else if (MyPrev->is(tok::less))
+ --arrowcount;
+
+ MyPrev = MyPrev->Previous;
+ } while (arrowcount && MyPrev);
+ }
+ else if (MyPrev && MyPrev->is(tok::r_paren)) {
+
+ int bracketcount = 0;
+ do {
+ if (MyPrev->is(tok::r_paren))
+ ++bracketcount;
+
+ if (MyPrev->is(tok::l_paren))
+ --bracketcount;
+
+ MyPrev = MyPrev->Previous;
+ } while (bracketcount && MyPrev);
+ }
+ }
+
+ if (MyPrev) {
+ bool isconstructor = MyPrev->isCtorOrDtor();
+
+ if (!isconstructor) {
+ MyPrev->NewlinesBefore = 1;
+ }
+ else if (isconstructor && !IsClassScope && MyPrev->Previous && MyPrev->Previous->is(tok::kw_constexpr)) {
+ ++MyPrev->MustBreakBefore;
+ //++MyPrev->Newlines;
+ }
+ }
+ }
+ }
+ }
+ else if (MyToken->is(tok::r_paren)) {
+ RparenCount++;
+
+ if (RparenCount == LparenCount) {
+ LparenCount = 0;
+ RparenCount = 0;
+ }
+ }
+ else if (MyToken->isPPConditionalInclusionStart()) {
+ IsPPConditionalInclusionScope = true;
+ }
+ else if (MyToken->isPPConditionalInclusionEnd()) {
+ IsPPConditionalInclusionScope = false;
+ }
+ else if (MyToken->isOneOf(tok::kw_if, tok::kw_for, tok::kw_while)) {
+ OriginalLineBreakWeight += 5;
+ }
+ else if (MyToken->is(tok::arrow)) {
+ OriginalLineBreakWeight += 2;
+ }
+ else if (!Line.endsWith(tok::semi) && Line.MightBeFunctionDecl && MyToken->isDatatype() &&
+ IsClassScope == false && IsStructScope == false && IsEnumScope == false &&
+ RbraceCount == LbraceCount && LbraceCount == 0) {
+ IsInFunctionDefinition = true;
+ IsFunctionDefinitionLine = true;
+ }
+
+ // Copy state
+ MyToken->MyLine = &Line;
+ MyToken->HasSemiColonInLine = hasSemiColon;
+ MyToken->IsPPConditionalInclusionScope = IsPPConditionalInclusionScope;
+ MyToken->IsClassScope = IsClassScope;
+ MyToken->IsStructScope = IsStructScope;
+ MyToken->IsUnionScope = IsUnionScope;
+ MyToken->IsEnumScope = MyToken->IsEnumScope ? true : IsEnumScope;
+ MyToken->StructScopeName = StructScopeName;
+ MyToken->ClassScopeName = ClassScopeName;
+ MyToken->LbraceCount = LbraceCount;
+ MyToken->RbraceCount = RbraceCount;
+ MyToken->LparenCount = LparenCount;
+ MyToken->RparenCount = RparenCount;
+ MyToken->IsFunctionDefinitionLine = IsFunctionDefinitionLine;
+ MyToken->IsInFunctionDefinitionScope = IsInFunctionDefinition;
+ MyToken->IsInTemplateLine = MyToken->IsInTemplateLine ? true : IsInTemplateLine;
+ MyToken->LArrowCount = LArrowCount;
+ MyToken->RArrowCount = RArrowCount;
+
+ // Check if this token is a MACRO
+ if ((MyToken->Previous == nullptr && MyToken->is(tok::identifier) && MyToken->Next && MyToken->Next->is(tok::semi))
+ || (MyToken->Previous == nullptr && MyToken->is(tok::identifier) && MyToken->Next && MyToken->Next->is(tok::comment))
+ || (MyToken->Previous == nullptr && MyToken->is(tok::identifier) && MyToken->Next == nullptr)) {
+
+ string val(MyToken->TokenText.data(), MyToken->TokenText.size());
+
+ if (DefinedMacros.find(val) != DefinedMacros.end()) {
+ MyToken->Finalized = true;
+ }
+ if (MyToken->Next)
+ MyToken->HasSemiColonInLine = MyToken->Next->is(tok::semi);
+ else
+ MyToken->HasSemiColonInLine = false;
+ }
+
+ if (MyToken->Previous != nullptr && MyToken->Previous->Finalized && MyToken->is(tok::comment)) {
+ string val(MyToken->Previous->TokenText.data(), MyToken->Previous->TokenText.size());
+
+ if (DefinedMacros.find(val) != DefinedMacros.end()) {
+ MyToken->Finalized = true;
+ }
+ }
+ }
+ }
+
+ // TALLY: Walk the line in forward direction
+ FormatToken* MyToken2 = Line.First;
+ if (MyToken2) {
+ for (MyToken2 = Line.First; MyToken2 != nullptr; MyToken2 = MyToken2->Next) {
+ // Copy state (accumulated weight for all tokens in the line) to all tokens in the line
+ MyToken2->OriginalLineBreakWeight = OriginalLineBreakWeight;
+ }
+ }
+}
+
+// TALLY: Walk the line in forward direction
+void TokenAnnotator::walkLine2(AnnotatedLine& Line) {
+
+ int templatebracecount = 0;
+
+ // First loop for 'IsRhsToken'
+ FormatToken* MyToken = Line.First;
+ if (MyToken) {
+ for (MyToken = Line.First; MyToken != nullptr; MyToken = MyToken->Next) {
+ if (MyToken->isNotScoped() || MyToken->IsInTemplateLine)
+ continue;
+
+ bool nonAlignasLParen = MyToken->is(tok::l_paren) && MyToken->Previous && !MyToken->Previous->is(tok::kw_alignas);
+
+ if (MyToken->isOneOf(tok::equal, TT_BinaryOperator, TT_UnaryOperator) || MyToken->isMemberAccess() || nonAlignasLParen)
+ break;
+ }
+
+ // TALLY to distinguish '(' from 'operator=('
+ if (MyToken && (MyToken->isOneOf(tok::equal, TT_BinaryOperator, TT_UnaryOperator) || MyToken->isMemberAccess())
+ && (MyToken->Previous && !(MyToken->Previous->is(tok::kw_operator)))) {
+ FormatToken* Next = MyToken->getNextNonCommentNonConst();
+ while (Next) {
+ Next->IsRhsToken = true;
+ Next = Next->getNextNonCommentNonConst();
+ }
+ }
+ }
+
+ // Second loop for 'IsVariableNameWithDatatype', 'IsFunctionName', and 'IsDatatype'
+ FormatToken* DtToken = nullptr;
+ MyToken = Line.First;
+ if (MyToken) {
+ for (MyToken = Line.First; MyToken != nullptr; MyToken = MyToken->Next) {
+ if (MyToken->IsInterimBeforeName || MyToken->IsRhsToken || MyToken->isNotScoped() || MyToken->isParenScoped() || MyToken->IsInTemplateLine)
+ // Basically a template type, then move to next token.
+ continue;
+
+ // In Function Definition Block
+ if (MyToken->IsInFunctionDefinitionScope) {
+ //const FormatToken * Prev = MyToken->getPreviousNonComment();
+ const FormatToken * Next = MyToken;
+ bool isDT = true;
+
+ while (Next != nullptr && Next->isNot (tok::semi)) {
+ if (Next->isOneOf(tok::l_paren, tok::r_paren, tok::less, tok::lessless, tok::lesslessequal,
+ tok::greater, tok::greatergreater, tok::greatergreaterequal,
+ tok::period, tok::periodstar, tok::arrow, tok::arrowstar, tok::kw_goto,
+ tok::pipe, tok::pipeequal,tok::pipepipe, tok::caret, tok::caretequal,
+ tok::ampamp, tok::ampequal, tok::starequal, tok::plusequal, tok::plusplus,
+ tok::minusequal, tok::minusminus, tok::percentequal, tok::slashequal)) {
+ isDT = false;
+ Next = nullptr;
+ break;
+ }
+
+ if (Next->is(tok::equal)) {
+ // Check if this statement is a const variable declaration
+ const FormatToken * tmp = MyToken;
+ while (tmp && tmp->isNot(tok::equal)) {
+ if (tmp->isOneOf(tok::kw_const, tok::kw_constexpr)) {
+ // it is a declaration
+ isDT = true;
+ break;
+ }
+ isDT = false;
+ tmp = tmp->Next;
+ }
+ Next = nullptr; // we need no more iteration on token in this statement
+ break;
+ }
+ Next = Next->Next;
+ }
+
+ if (isDT) {
+ Next = MyToken->isNot(tok::l_brace) ? MyToken : MyToken->getNextNonComment();
+ while (Next != nullptr && Next->isNot (tok::semi)) {
+ MyToken->IsVariableNameWithDatatype = true;
+ MyToken->IsDatatype = true;
+ Next = Next->Next;
+ }
+ }
+ if (Next == nullptr)
+ break;
+
+ MyToken = (FormatToken *)Next;
+ continue;
+ }
+
+ // Datatype
+ if (MyToken->isDatatypeInner() && (MyToken->Previous == nullptr || MyToken->Previous->is(tok::kw_return) == false) && MyToken->IsEnumScope == false) {
+ if (DtToken == nullptr)
+ DtToken = MyToken;
+
+ // Interim
+ FormatToken* Next = MyToken;
+ do {
+ Next = Next->getNextNonCommentNonConst();
+
+ if (!Next) {
+ break;
+ }
+
+ if (Next->is(tok::less))
+ ++templatebracecount;
+
+ if(templatebracecount)
+ Next->IsInterimBeforeName = true;
+
+ if (Next->is(tok::greater))
+ --templatebracecount;
+
+ } while (templatebracecount);
+
+ templatebracecount = 0;
+
+ if (Next && Next->is(tok::coloncolon)) {
+ FormatToken* NextNext = Next->getNextNonCommentNonConst();
+
+ if (NextNext && NextNext->TokenText.equals("Enum")) {
+ Next->IsInterimBeforeName = true;
+ Next = NextNext;
+ Next->IsInterimBeforeName = true;
+ }
+ }
+
+ // Interim
+ while (Next &&
+ (Next->isOneOf(tok::star, tok::amp) ||
+ Next->isPointerOrRef())) {
+ Next->IsInterimBeforeName = true;
+ Next = Next->getNextNonCommentNonConst();
+ }
+ }
+
+ if (DtToken != nullptr && MyToken != DtToken) {
+ const FormatToken* Prev = MyToken->getPreviousNonComment();
+ const FormatToken* Next = MyToken->getNextNonComment();
+
+ // Function name
+ if ((MyToken->isFunctionName() && Next && Next->is(tok::l_paren) && MyToken->Previous && MyToken->Previous->isDatatype() == false) ||
+ (MyToken->isFunctionName() && Next && Next->is(tok::l_paren) && (MyToken->IsClassScope || MyToken->IsStructScope)) ||
+ MyToken->isFunctionName() && MyToken->is(tok::kw_operator) && (MyToken->IsClassScope || MyToken->IsStructScope)) {
+ MyToken->IsFunctionName = true;
+
+ if (MyToken->is(tok::kw_operator))
+ MyToken = MyToken->MarkOperatorOverloadAsFunction();
+
+ DtToken->IsDatatype = true;
+ }
+ // Variable name
+ else if (MyToken->is(tok::identifier) && Prev && !Prev->isMemberAccess()) {
+ bool nextOk = false;
+ if (Next) {
+ // && !isValueAssignment(Prev)
+ if (Next->isOneOf(tok::semi, tok::comma, tok::equal)) {
+ nextOk = true;
+ }
+ else if (Next->is(tok::l_brace) && Next->MatchingParen) {
+ nextOk = true;
+ }
+ else if (Next->is(tok::l_paren) &&
+ Prev->isOneOf(tok::coloncolon, tok::l_square) == false /*&& Next->IsClassScope == false*/)
+ /*
+ * && isFunctionLocalVariableDeclaration (Prev, Next)
+ */
+ nextOk = true;
+ else if (Next->is(tok::colon)) {
+ const FormatToken* MyNext2 = Next->getNextNonComment();
+ if (MyNext2 && (MyNext2->is(tok::numeric_constant) || MyNext2->is(tok::identifier) )) {
+ nextOk = true;
+ }
+ }
+ else if (Next->is(tok::l_square)) {
+ const FormatToken* Next2 = Next->getNextNonComment();
+ // Array size may be tok::numeric_constant or tok::identifier or expression
+ // containing tok::plus, tok::minus, tok::star etc. so we conservatively look
+ // for matching tok::r_square only.
+ while (Next2 && !Next2->is(tok::r_square)) {
+ Next2 = Next2->getNextNonComment();
+ }
+ if (Next2 && Next2->is(tok::r_square)) {
+ const FormatToken* nextnext = Next2->getNextNonComment();
+ if (nextnext == nullptr || nextnext->is(tok::l_paren) == false)
+ nextOk = true;
+ }
+ }
+ // TODO: Add support for scoped variable name eg. Something::SomethingElse
+ }
+
+ if (nextOk) {
+ MyToken->IsVariableNameWithDatatype = true;
+ DtToken->IsDatatype = true;
+ }
+ }
+ }
+ }
+ }
+
+ // Third loop for 'IsVariableNameWithoutDatatype'
+ MyToken = Line.First;
+ if (MyToken) {
+ for (MyToken = Line.First; MyToken != nullptr; MyToken = MyToken->Next) {
+ if (MyToken->IsInterimBeforeName || MyToken->IsRhsToken || MyToken->isNotScoped() || MyToken->isParenScoped())
+ continue;
+
+ // Identifier
+ if (!MyToken->IsDatatype && MyToken->is(tok::identifier)) {
+
+ // Interim
+ FormatToken* Prev = MyToken->getPreviousNonComment();
+ while (Prev && (Prev->isOneOf(tok::star, tok::amp) || Prev->isPointerOrRef())) {
+ Prev->IsInterimBeforeName = true;
+ Prev = Prev->getPreviousNonComment();
+ }
+
+ if (Prev == nullptr) {
+ MyToken->IsVariableNameWithoutDatatype = true;
+ }
+ }
+ }
+ }
+}
+
+/// TALLY: Calculate Tally-specific information for all tokens in all annotated lines
+// before calculateFormattingInformation()
+void TokenAnnotator::calculateTallyInformation(AnnotatedLine& Line) {
+ for (SmallVectorImpl<AnnotatedLine*>::iterator I = Line.Children.begin(),
+ E = Line.Children.end();
+ I != E; ++I) {
+ calculateTallyInformation(**I);
+ }
+
+ walkLine1(Line);
+ walkLine2(Line);
+}
+
+// TALLY: Check if this line is part of variable declaration in a function definition
+// TODO: this may need more conditions
+bool TokenAnnotator::isFunctionLocalVariableDeclaration(const FormatToken * pTkn, const FormatToken * pNxt)
+{
+ while (pTkn != nullptr && pTkn->IsInFunctionDefinitionScope) {
+
+ if (pTkn->is(tok::equal) && !isValueAssignment (pTkn))
+ return true;
+
+ pTkn = pTkn->Previous;
+ }
+
+ while (pNxt != nullptr && pNxt->IsInFunctionDefinitionScope && pNxt->isNot(tok::semi)) {
+
+ if (pNxt->is(tok::equal))
+ return true;
+
+ pNxt = pNxt->Next;
+ }
+
+ return false;
+}
+
+// TALLY: Distinguish that it is not a variable declaration
+bool TokenAnnotator::isValueAssignment(const FormatToken * pTkn)
+{
+ while (pTkn != nullptr && pTkn->IsInFunctionDefinitionScope) {
+
+ if (pTkn->isOneOf(tok::arrow, tok::period, tok::r_paren))
+ return true;
+
+ pTkn = pTkn->Previous;
+ }
+
+ return false;
+}
+
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
for (AnnotatedLine *ChildLine : Line.Children)
calculateFormattingInformation(*ChildLine);
+ // TALLY: Walk the line in forward direction
+ FormatToken* MyToken = Line.First;
+ bool IsDoubleIndentNeeded = false;
+ bool IsReturnLine = MyToken->is(tok::kw_return);
+
+ if (MyToken && !IsReturnLine) {
+ for (MyToken = Line.First; MyToken != nullptr && IsDoubleIndentNeeded == false; MyToken = MyToken->Next) {
+ if (MyToken->IsVariableNameWithDatatype || MyToken->isTallyTrace()) {
+ IsDoubleIndentNeeded = true;
+ break;
+ }
+ }
+ }
+
+ /// TALLY: We have a variable name in declaration. Filter out cases in control statements and scoped in struct or union.
+ if (IsDoubleIndentNeeded) {
+ // Walk back to last non-comment token
+ FormatToken* SemiToken = Line.Last;
+ while (SemiToken && SemiToken->is(tok::comment)) {
+ SemiToken = SemiToken->Previous;
+ }
+ bool IsLastSemi = SemiToken && SemiToken->is(tok::semi);
+
+ bool IsStructOrUnion = (MyToken->IsStructScope || MyToken->IsUnionScope);// && (!MyToken->IsClassScope || !MyToken->IsStructScope));
+ if (IsLastSemi && !(IsStructOrUnion || MyToken->isParenScoped() || MyToken->isNotScoped())) {
+ Line.IsDoubleIndented = true;
+ ++Line.Level;
+ }
+ }
+
Line.First->TotalLength =
Line.First->IsMultiline ? Style.ColumnLimit
: Line.FirstStartColumn + Line.First->ColumnWidth;
@@ -4488,7 +5073,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
// operator C<T>::D<U>*()
// dependent on PointerAlignment style.
if (Previous) {
- if (Previous->endsSequence(tok::kw_operator))
+ if (Previous->endsSequence(tok::kw_operator) ||
+ Previous->endsSequence(tok::kw_const, tok::kw_operator) ||
+ Previous->endsSequence(tok::kw_volatile, tok::kw_operator))
return Style.PointerAlignment != FormatStyle::PAS_Left;
if (Previous->is(tok::kw_const) || Previous->is(tok::kw_volatile)) {
return (Style.PointerAlignment != FormatStyle::PAS_Left) ||
@@ -5499,6 +6086,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
break;
}
}
+ // TALLY: Always have a break after tok::r_brace and before tok::kw_break
+ if (Left.is(tok::r_brace) && Right.is(tok::kw_break))
+ return true;
if (Style.PackConstructorInitializers == FormatStyle::PCIS_Never) {
if (Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon &&
(Left.is(TT_CtorInitializerComma) ||
diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h
index 05a6daa87d8034..02d885878be236 100644
--- a/clang/lib/Format/TokenAnnotator.h
+++ b/clang/lib/Format/TokenAnnotator.h
@@ -11,12 +11,16 @@
/// \c AnnotatedTokens out of \c FormatTokens with required extra information.
///
//===----------------------------------------------------------------------===//
-
+// clang-format off
#ifndef LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
#define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
#include "UnwrappedLineParser.h"
#include "clang/Format/Format.h"
+#include <string>
+#include <set>
+
+using namespace std;
namespace clang {
namespace format {
@@ -57,7 +61,7 @@ class AnnotatedLine {
IsMultiVariableDeclStmt(false), Affected(false),
LeadingEmptyLinesAffected(false), ChildrenAffected(false),
ReturnTypeWrapped(false), IsContinuation(Line.IsContinuation),
- FirstStartColumn(Line.FirstStartColumn) {
+ FirstStartColumn(Line.FirstStartColumn), /* TALLY */ IsDoubleIndented(false) {
assert(!Line.Tokens.empty());
// Calculate Next and Previous for all tokens. Note that we must overwrite
@@ -151,6 +155,16 @@ class AnnotatedLine {
startsWith(tok::kw_export, tok::kw_namespace);
}
+ /// TALLY : To state if there is a string literal in the line expression.
+ bool hasStringLiteral() const {
+ for (const FormatToken* curr = First; curr; curr = curr->getNextNonComment()) {
+ if (curr->isStringLiteral())
+ return true;
+ }
+
+ return false;
+ }
+
FormatToken *getFirstNonComment() const {
assert(First);
return First->is(tok::comment) ? First->getNextNonComment() : First;
@@ -200,6 +214,12 @@ class AnnotatedLine {
bool IsContinuation;
unsigned FirstStartColumn;
+ /// TALLY: \c True if this line is additional/double indented
+ bool IsDoubleIndented;
+
+ /// TALLY: Line state for columnarization
+ unsigned LastSpecifierPadding = 0;
+ unsigned LastSpecifierTabs = 0;
private:
// Disallow copying.
@@ -214,6 +234,13 @@ class TokenAnnotator {
TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
: Style(Style), Keywords(Keywords) {}
+ /// TALLY: clean the set that is created.
+ ~TokenAnnotator() {
+
+ if (DefinedMacros.size() > 0)
+ DefinedMacros.clear();
+ }
+
/// Adapts the indent levels of comment lines to the indent of the
/// subsequent line.
// FIXME: Can/should this be done in the UnwrappedLineParser?
@@ -222,6 +249,61 @@ class TokenAnnotator {
void annotate(AnnotatedLine &Line);
void calculateFormattingInformation(AnnotatedLine &Line) const;
+ /// TALLY: Add Tally-specific information to all annotated lines
+ void calculateTallyInformation(AnnotatedLine &Line);
+
+ /// TALLY: If a given token is part of a PP conditional inclusion
+ bool IsPPConditionalInclusionScope = false;
+
+ /// TALLY: If a given token is part of a struct scope
+ bool IsStructScope = false;
+
+ /// TALLY: If a given token is part of a union scope
+ bool IsUnionScope = false;
+
+ /// TALLY: If a given token is part of a class scope
+ bool IsClassScope = false;
+
+ /// TALLY: If a given token is part of a enum scope
+ bool IsEnumScope = false;
+
+ /// TALLY: If in function definition.
+ bool IsInFunctionDefinition = false;
+
+ /// TALLY : If in function definition Line. and not body.
+ bool IsFunctionDefinitionLine = false;
+
+ /// TALLY : If in template Line Basically in arrow braces inside expression of type. template <>.
+ bool IsInTemplateLine = false;
+
+ /// TALLY: Name of the struct (if any) a given token is scoped under
+ StringRef StructScopeName = "<StructScopeName_None>";
+
+ /// TALLY: Name of the class (if any) a given token is scoped under
+ StringRef ClassScopeName = "<ClassScopeName_None>";
+
+ /// TALLY: L-Brace count
+ unsigned LbraceCount = 0;
+
+ /// TALLY: R-Brace count
+ unsigned RbraceCount = 0;
+
+ /// TALLY: L-Paren count
+ unsigned LparenCount = 0;
+
+ /// TALLY: R-Paren count
+ unsigned RparenCount = 0;
+
+ /// TALLY: template opener count.
+ unsigned LArrowCount = 0;
+
+ /// TALLY: template closer count.
+ unsigned RArrowCount = 0;
+
+ /// TALLY: A weight to determine whether line break in the original must be enforced
+ unsigned OriginalLineBreakWeight = 0;
+
+
private:
/// Calculate the penalty for splitting before \c Tok.
unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
@@ -258,11 +340,27 @@ class TokenAnnotator {
FormatStyle::PointerAlignmentStyle getTokenPointerOrReferenceAlignment(
const FormatToken &PointerOrReference) const;
+ // TALLY
+ void walkLine1(AnnotatedLine &Line);
+
+ // TALLY
+ void walkLine2(AnnotatedLine &Line);
+
+ // TALLY
+ bool isFunctionLocalVariableDeclaration(const FormatToken * pTkn, const FormatToken * pNxt);
+
+ // TALLY
+ bool isValueAssignment(const FormatToken * pTkn);
+
const FormatStyle &Style;
const AdditionalKeywords &Keywords;
SmallVector<ScopeType> Scopes;
+ // TALLY: mark MACRO, is populated only when it is defined in same file it is used.
+ static constexpr char STRDEFINETEXT[] {'d','e','f','i','n','e','\0'};
+
+ set<string> DefinedMacros;
};
} // end namespace format
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index adeb072434873f..cf856beb085c42 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -264,8 +264,10 @@ class LineJoiner {
if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)
return 0;
+ // TALLY: ColumnLimitInEffect
+ unsigned ColumnLimitInEffect = TheLine->InPPDirective ? Style.ColumnLimitExtended : Style.ColumnLimit;
unsigned Limit =
- Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent;
+ Style.ColumnLimit == 0 ? UINT_MAX : ColumnLimitInEffect - Indent;
// If we already exceed the column limit, we set 'Limit' to 0. The different
// tryMerge..() functions can then decide whether to still do merging.
Limit = TheLine->Last->TotalLength > Limit
@@ -275,8 +277,29 @@ class LineJoiner {
if (TheLine->Last->is(TT_FunctionLBrace) &&
TheLine->First == TheLine->Last &&
!Style.BraceWrapping.SplitEmptyFunction &&
- NextLine.First->is(tok::r_brace)) {
+ NextLine.First->is(tok::r_brace))
return tryMergeSimpleBlock(I, E, Limit);
+
+ // TALLY: Try merge Tally Memory Manager macro with left-brace
+ const AnnotatedLine *tNextLine = I[1];
+ if (TheLine && TheLine->Last && TheLine->Last->is(tok::l_brace) &&
+ tNextLine && tNextLine->First && tNextLine->First->isTallyMemMgrMacro())
+ return tryMergeSimpleBlock(I, E, UINT_MAX);
+
+ // TALLY: Try merge empty constructor / destructor block
+ // Actual merge happens in tryMergeSimpleBlock() in the lines
+ // after this comment '// We merge empty blocks even if the line exceeds the column limit.'
+ if (TheLine && TheLine->Last && TheLine->Last->is(tok::r_paren) &&
+ tNextLine && tNextLine->First && tNextLine->First->is(tok::l_brace)) {
+ // Get the l_paren from r_paren
+ FormatToken* MatchingParenToken = TheLine->Last->MatchingParen;
+ if (MatchingParenToken != nullptr) {
+ const FormatToken* MyPrev = MatchingParenToken->getPreviousNonComment();
+ const FormatToken* MyPrev2 = MyPrev ? MyPrev->getPreviousNonComment() : nullptr;
+ if ((MyPrev && MyPrev->isConstructor()) || (MyPrev2 && MyPrev2->isDestructor())) {
+ return tryMergeSimpleBlock(I, E, UINT_MAX);
+ }
+ }
}
const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] : nullptr;
@@ -814,7 +837,7 @@ class LineJoiner {
if (ShouldMerge()) {
// We merge empty blocks even if the line exceeds the column limit.
Tok->SpacesRequiredBefore =
- (Style.SpaceInEmptyBlock || Line.Last->is(tok::comment)) ? 1 : 0;
+ (Tok->isTallyMemMgrMacro() || Style.SpaceInEmptyBlock || Line.Last->is(tok::comment)) ? 1 : 0;
Tok->CanBreakBefore = true;
return 1;
} else if (Limit != 0 && !Line.startsWithNamespace() &&
@@ -1349,6 +1372,14 @@ unsigned UnwrappedLineFormatter::format(
Joiner.getNextMergedLine(DryRun, IndentTracker);
Line; PrevPrevLine = PreviousLine, PreviousLine = Line, Line = NextLine,
FirstLine = false) {
+ /// TALLY : Ignore the lines that we dont want to format. Currently template based friend class.
+ /// Line containing string literal. Hence for these, we do not need to employ clang-format off
+ if (Line && Line->First &&
+ ((Line->startsWith(tok::hash) || Line->InPPDirective) ||
+ Line->First->TokenText.equals("TW_CHECK_UDT_SIZE"))) {
+ markFinalized(Line->First);
+ }
+
assert(Line->First);
const AnnotatedLine &TheLine = *Line;
unsigned Indent = IndentTracker.getIndent();
@@ -1383,6 +1414,9 @@ unsigned UnwrappedLineFormatter::format(
}
NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
+ // TALLY: Always apply NoColumnLimitLineFormatter. Don't apply
+ // NoLineBreakFormatter and OptimizingLineFormatter.
+ bool IsFunctionDefinitionLine = TheLine.MightBeFunctionDecl && !TheLine.Last->isOneOf(tok::semi, tok::comment);
unsigned ColumnLimit = getColumnLimit(TheLine.InPPDirective, NextLine);
bool FitsIntoOneLine =
!TheLine.ContainsMacroCall &&
@@ -1391,6 +1425,11 @@ unsigned UnwrappedLineFormatter::format(
(!Style.isJavaScript() || !Style.JavaScriptWrapImports)) ||
(Style.isCSharp() &&
TheLine.InPPDirective)); // don't split #regions in C#
+
+ //if (IsFunctionDefinitionLine) {
+ // Penalty += NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this)
+ // .formatLine(TheLine, NextStartColumn + Indent, FirstLine ? FirstStartColumn : 0, DryRun);
+ //} else
if (Style.ColumnLimit == 0) {
NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this)
.formatLine(TheLine, NextStartColumn + Indent,
@@ -1467,7 +1506,7 @@ static auto computeNewlines(const AnnotatedLine &Line,
// Remove empty lines at the start of nested blocks (lambdas/arrow functions)
if (!PreviousLine && Line.Level > 0)
Newlines = std::min(Newlines, 1u);
- if (Newlines == 0 && !RootToken.IsFirst)
+ if (Newlines == 0 && !RootToken.IsFirst && !RootToken.LparenCount) // TALLY: && !RootToken.LparenCount
Newlines = 1;
if (RootToken.IsFirst && !RootToken.HasUnescapedNewline)
Newlines = 0;
@@ -1486,8 +1525,8 @@ static auto computeNewlines(const AnnotatedLine &Line,
if (PreviousLine && RootToken.isAccessSpecifier()) {
switch (Style.EmptyLineBeforeAccessModifier) {
case FormatStyle::ELBAMS_Never:
- if (Newlines > 1)
- Newlines = 1;
+ if (Newlines > 2) // TALLY previous Newlines > 1
+ Newlines = 2; // TALLY previous Newlines = 1
break;
case FormatStyle::ELBAMS_Leave:
Newlines = std::max(RootToken.NewlinesBefore, 1u);
@@ -1496,12 +1535,44 @@ static auto computeNewlines(const AnnotatedLine &Line,
if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) && Newlines <= 1)
Newlines = 2;
if (PreviousLine->First->isAccessSpecifier())
- Newlines = 1; // Previous is an access modifier remove all new lines.
+ Newlines = 2; // Previous is an access modifier remove all new lines.
break;
case FormatStyle::ELBAMS_Always: {
const FormatToken *previousToken;
- if (PreviousLine->Last->is(tok::comment))
+ if (PreviousLine->Last->is(tok::comment)) {
previousToken = PreviousLine->Last->getPreviousNonComment();
+
+ // TALLY: Ensure an empty line before and after a comment section
+ // (excluding trailing line comments)
+ bool commentThenNoncomment =
+ PreviousLine && PreviousLine->First->is(tok::comment) &&
+ !PreviousLine->InPPDirective && !RootToken.is(tok::comment);
+ bool noncommentThenComment =
+ PreviousLine && !PreviousLine->First->is(tok::comment) &&
+ !PreviousLine->InPPDirective && RootToken.is(tok::comment);
+ if (commentThenNoncomment || noncommentThenComment)
+ Newlines = 2;
+
+ // TALLY: Remove empty lines before "};" in class, struct, union or enum declarations
+ // This block needs to be after 'Ensure an empty line before and after a comment section'
+ FormatToken *LastToken = Line.Last;
+ if (LastToken && LastToken->is(tok::comment))
+ LastToken = LastToken->getPreviousNonComment();
+ if (PreviousLine && PreviousLine->First && RootToken.is(tok::r_brace) &&
+ LastToken && LastToken->is(tok::semi)) {
+ bool applies = false;
+ if (PreviousLine->First->IsClassScope && !RootToken.IsClassScope)
+ applies = true;
+ if (PreviousLine->First->IsStructScope && !RootToken.IsStructScope)
+ applies = true;
+ if (PreviousLine->First->IsUnionScope && !RootToken.IsUnionScope)
+ applies = true;
+ if (PreviousLine->First->IsEnumScope && !RootToken.IsEnumScope)
+ applies = true;
+ if (applies)
+ Newlines = 1;
+ }
+ }
else
previousToken = PreviousLine->Last;
if ((!previousToken || previousToken->isNot(tok::l_brace)) &&
@@ -1512,8 +1583,14 @@ static auto computeNewlines(const AnnotatedLine &Line,
}
}
+ // TALLY: Insert or remove empty line after access specifiers.
+ if (PreviousLine && PreviousLine->First->isAccessSpecifier()) {
+ Newlines = 2;
+ }
+
+ //TALLY: we may not want these block
// Insert or remove empty line after access specifiers.
- if (PreviousLine && PreviousLine->First->isAccessSpecifier() &&
+ /*if (PreviousLine && PreviousLine->First->isAccessSpecifier() &&
(!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline)) {
// EmptyLineBeforeAccessModifier is handling the case when two access
// modifiers follow each other.
@@ -1533,6 +1610,45 @@ static auto computeNewlines(const AnnotatedLine &Line,
break;
}
}
+ }*/
+
+ if (PreviousLine && PreviousLine->First->isTallyTrace())
+ Newlines = 2;
+ // TALLY: Add extra new line at the beginning of an if-, do-, for-,
+ // while-blocks
+ if (PreviousLine &&
+ PreviousLine->First->isOneOf(tok::kw_if, tok::kw_do, tok::kw_for,
+ tok::kw_while) &&
+ PreviousLine->Last->is(tok::l_brace) && RootToken.NewlinesBefore == 1) {
+ ++Newlines;
+ }
+
+ // TALLY: Add extra new line at the beginning of an else-block or else-if block
+ bool isElseBlock = false;
+ if (PreviousLine && PreviousLine->Last->is(tok::l_brace)) {
+ if (PreviousLine->First->is(tok::kw_else) && PreviousLine->First->Next->is(tok::l_brace)) {
+ isElseBlock = true;
+ } else if (PreviousLine->First->is(tok::r_brace)) {
+ const FormatToken *MyNext = PreviousLine->First->getNextNonComment();
+ if (MyNext->is(tok::kw_else))
+ isElseBlock = true;
+ }
+ }
+
+ if (isElseBlock && RootToken.NewlinesBefore == 1)
+ ++Newlines;
+
+ // TALLY: Add extra new line at the end of a double-indented block
+ if (PreviousLine && PreviousLine->IsDoubleIndented &&
+ !Line.IsDoubleIndented && RootToken.isNot(tok::comment) &&
+ RootToken.NewlinesBefore == 1) {
+
+ if (!((PreviousLine->First->IsClassScope ||
+ PreviousLine->First->IsStructScope) &&
+ (Line.First->IsClassScope == false ||
+ Line.First->IsStructScope == false))) {
+ ++Newlines;
+ }
}
return Newlines;
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 8f6453a25d9d41..5524ff6da6ecb9 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2486,6 +2486,19 @@ bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {
nextToken();
break;
case tok::comma:
+ // TALLY: Force enum members on new line each
+ if (IsEnum && FormatTok->Previous) {
+ if (!FormatTok->Previous->is(tok::numeric_constant)) {
+ // Simple case
+ FormatTok->Previous->MustBreakBefore = true;
+ }
+ else {
+ // Relatively complex case: Numeric constant before comma
+ if (FormatTok->Previous->Previous && FormatTok->Previous->Previous->is(tok::equal) && FormatTok->Previous->Previous->Previous) {
+ FormatTok->Previous->Previous->Previous->MustBreakBefore = true;
+ }
+ }
+ }
nextToken();
if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
addUnwrappedLine();
@@ -2834,6 +2847,10 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
if (Style.RemoveBracesLLVM) {
NestedTooDeep.back() = false;
Kind = IfStmtKind::IfElse;
+ }
+ if (FormatTok->NewlinesBefore >= 1) {
+ FormatTok->NewlinesBefore = 0;
+ FormatTok->HasUnescapedNewline = false;
}
nextToken();
handleAttributes();
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index f9eed7f516bbeb..cfac0ad0da935a 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -10,7 +10,7 @@
/// This file implements WhitespaceManager class.
///
//===----------------------------------------------------------------------===//
-
+// clang-format off
#include "WhitespaceManager.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
@@ -106,11 +106,25 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
llvm::sort(Changes, Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
+ columnarizeKeywords(); // TALLY
+ columnarizeDeclarationSpecifierTokens(); // TALLY
+ columnarizeDatatypeTokens(); // TALLY
+ columnarizeNoDiscardOrNoReturnOrTemplate (); // TALLY
+ columnarizeIdentifierTokens(); // TALLY
+ columnarizeLParenTokensAndSplitArgs(); // TALLY
+ alignConsecutiveAssignmentsOnScopedVarName(); // TALLY
+ alignConsecutiveAssignmentsOnVarNameAcrossSections(); // TALLY
+ alignConsecutiveAssignmentsOnVarNameWithinSection(); // TALLY
+ alignConsecutiveVarBitFields(); // TALLY. We do NOT use alignConsecutiveBitFields().
+ alignConsecutiveAssignmentsOnEqualsAcrossSections(); // TALLY
+ alignConsecutiveAssignmentsOnEqualsWithinSection(); // TALLY
+ alignConsecutiveLBraceOfVarDeclOrDef(); // TALLY
+ alignConsecutiveAssignementsOnUsing (); // TALLY
alignConsecutiveMacros();
alignConsecutiveShortCaseStatements();
- alignConsecutiveDeclarations();
+ //alignConsecutiveDeclarations();
alignConsecutiveBitFields();
- alignConsecutiveAssignments();
+ //alignConsecutiveAssignments();
alignChainedConditionals();
alignTrailingComments();
alignEscapedNewlines();
@@ -120,7 +134,22 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
return Replaces;
}
+// TALLY
+bool WhitespaceManager::IsConditionBlock(const FormatToken *tkn)
+{
+ while (tkn) {
+ if (tkn->Tok.isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_for))
+ return true;
+
+ tkn = tkn->Previous;
+ }
+
+ return false;
+}
+
void WhitespaceManager::calculateLineBreakInformation() {
+ int prevTknStartOfColumnNWidth = 0;
+
Changes[0].PreviousEndOfTokenColumn = 0;
Change *LastOutsideTokenChange = &Changes[0];
for (unsigned i = 1, e = Changes.size(); i != e; ++i) {
@@ -244,6 +273,46 @@ void WhitespaceManager::calculateLineBreakInformation() {
} else {
LastBlockComment = nullptr;
}
+
+ if (Change.Tok->isOneOf(tok::r_paren, tok::kw_noexcept) &&
+ Change.Tok->Next && Change.Tok->Next->is(tok::colon)) {
+ Change.Tok->Next->SpacesRequiredBefore = 1;
+ Change.Tok->Next->MustBreakBefore = false;
+ Change.NewlinesBefore = 0;
+ prevTknStartOfColumnNWidth = Change.StartOfTokenColumn + Change.Tok->ColumnWidth;
+ }
+ else if (Change.Tok->is(tok::colon) && Change.Tok->Previous &&
+ Change.Tok->Previous->isOneOf(tok::r_paren, tok::kw_noexcept) &&
+ Change.Tok->Next && Change.Tok->Next->is(tok::identifier)) {
+ Change.Tok->Next->SpacesRequiredBefore = 1;
+ Change.Tok->Next->MustBreakBefore = false;
+ Change.Spaces = 1;
+ Change.NewlinesBefore = 0;
+ ++prevTknStartOfColumnNWidth;
+ if (Change.StartOfTokenColumn > prevTknStartOfColumnNWidth)
+ Change.StartOfTokenColumn = prevTknStartOfColumnNWidth;
+
+ ++prevTknStartOfColumnNWidth;
+ }
+ else if (Change.Tok->is(tok::identifier) &&
+ Change.Tok->Previous && Change.Tok->Previous->is(tok::colon) &&
+ Change.Tok->Previous->Previous && Change.Tok->Previous->Previous->isOneOf(tok::r_paren, tok::kw_noexcept)) {
+ Change.Spaces = 1;
+ Change.NewlinesBefore = 0;
+ ++prevTknStartOfColumnNWidth;
+ if (Change.StartOfTokenColumn > prevTknStartOfColumnNWidth)
+ Change.StartOfTokenColumn = prevTknStartOfColumnNWidth;
+ }
+/*
+ if (Change.Spaces > 4 && Change.Tok->LbraceCount == 1 &&
+ Change.Tok->IsInFunctionDefinitionScope && !Change.Tok->isTallyTrace() &&
+ !Change.Tok->IsDatatype) {
+ Change.Spaces = 4;
+ Change.StartOfTokenColumn = 4;
+ if (Change.NewlinesBefore > 2)
+ Change.NewlinesBefore = 2;
+ }
+ */
}
// Compute conditional nesting level
@@ -683,6 +752,1069 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
return i;
}
+// TALLY: Align a single sequence of tokens, see AlignTokens below.
+template <typename F>
+static void
+AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F&& Matches,
+ SmallVector<WhitespaceManager::Change, 16>& Changes,
+ /* TALLY */ bool IgnoreScope, /* TALLY */ bool IgnoreCommas) {
+
+ bool FoundMatchOnLine = false;
+ int Shift = 0;
+
+ // ScopeStack keeps track of the current scope depth. It contains indices of
+ // the first token on each scope.
+ // We only run the "Matches" function on tokens from the outer-most scope.
+ // However, we do need to pay special attention to one class of tokens
+ // that are not in the outer-most scope, and that is function parameters
+ // which are split across multiple lines, as illustrated by this example:
+ // double a(int x);
+ // int b(int y,
+ // double z);
+ // In the above example, we need to take special care to ensure that
+ // 'double z' is indented along with it's owning function 'b'.
+ SmallVector<unsigned, 16> ScopeStack;
+
+ for (unsigned i = Start; i != End; ++i) {
+ if (!IgnoreScope && ScopeStack.size() != 0 &&
+ Changes[i].indentAndNestingLevel() <
+ Changes[ScopeStack.back()].indentAndNestingLevel())
+ ScopeStack.pop_back();
+
+ // Compare current token to previous non-comment token to ensure whether
+ // it is in a deeper scope or not.
+ unsigned PreviousNonComment = i - 1;
+ while (PreviousNonComment > Start &&
+ Changes[PreviousNonComment].Tok->is(tok::comment))
+ PreviousNonComment--;
+ if (!IgnoreScope && i != Start && Changes[i].indentAndNestingLevel() >
+ Changes[PreviousNonComment].indentAndNestingLevel())
+ ScopeStack.push_back(i);
+
+ bool InsideNestedScope = ScopeStack.size() != 0;
+
+ if (Changes[i].NewlinesBefore > 0 &&
+ (!InsideNestedScope || IgnoreScope)) {
+ Shift = 0;
+ FoundMatchOnLine = false;
+ }
+
+ if (!FoundMatchOnLine && (IgnoreScope || !InsideNestedScope) &&
+ Matches(Changes[i])) {
+ if (!(Changes[i].Tok->IsFunctionDefinitionLine && Changes[i].Tok->is(tok::identifier) && (i > 0)
+ && Changes[i-1].Tok->isOneOf(tok::coloncolon, tok::l_square, tok::less,tok::r_brace,tok::kw_noexcept))
+ && Changes[i].Tok->LparenCount == 0
+ && !Changes[i-1].Tok->isOneOf(tok::r_brace, tok::kw_noexcept, tok::coloncolon)) {
+ FoundMatchOnLine = true;
+ Shift = Column - Changes[i].StartOfTokenColumn;
+ Changes[i].Spaces += Shift;
+ }
+ }
+
+
+ // This is for function parameters that are split across multiple lines,
+ // as mentioned in the ScopeStack comment.
+ if (InsideNestedScope && Changes[i].NewlinesBefore > 0) {
+ unsigned ScopeStart = ScopeStack.back();
+ if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName) ||
+ (ScopeStart > Start + 1 &&
+ Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)))
+ Changes[i].Spaces += Shift;
+ }
+
+ assert(Shift >= 0);
+ Changes[i].StartOfTokenColumn += Shift;
+ if (i + 1 != Changes.size())
+ Changes[i + 1].PreviousEndOfTokenColumn += Shift;
+ }
+}
+
+// TALLY: Walk through a subset of the changes, starting at StartAt, and find
+// sequences of matching tokens to align. To do so, keep track of the lines and
+// whether or not a matching token was found on a line. If a matching token is
+// found, extend the current sequence. If the current line cannot be part of a
+// sequence, e.g. because there is an empty line before it or it contains only
+// non-matching tokens, finalize the previous sequence.
+// The value returned is the token on which we stopped, either because we
+// exhausted all items inside Changes, or because we hit a scope level higher
+// than our initial scope.
+// This function is recursive. Each invocation processes only the scope level
+// equal to the initial level, which is the level of Changes[StartAt].
+// If we encounter a scope level greater than the initial level, then we call
+// ourselves recursively, thereby avoiding the pollution of the current state
+// with the alignment requirements of the nested sub-level. This recursive
+// behavior is necessary for aligning function prototypes that have one or more
+// arguments.
+// If this function encounters a scope level less than the initial level,
+// it returns the current position.
+// There is a non-obvious subtlety in the recursive behavior: Even though we
+// defer processing of nested levels to recursive invocations of this
+// function, when it comes time to align a sequence of tokens, we run the
+// alignment on the entire sequence, including the nested levels.
+// When doing so, most of the nested tokens are skipped, because their
+// alignment was already handled by the recursive invocations of this function.
+// However, the special exception is that we do NOT skip function parameters
+// that are split across multiple lines. See the test case in FormatTest.cpp
+// that mentions "split function parameter alignment" for an example of this.
+template <typename F>
+static unsigned AlignTokens(const FormatStyle& Style, F&& Matches,
+ SmallVector<WhitespaceManager::Change, 16>& Changes,
+ /* TALLY */ bool IgnoreScope,
+ /* TALLY */ bool IgnoreCommas,
+ unsigned StartAt,
+ /* TALLY */ unsigned MaxNewlinesBeforeSectionBreak,
+ /* TALLY */ bool NonMatchingLineBreaksSection,
+ /* TALLY */ bool AllowBeyondColumnLimitForAlignment,
+ /* TALLY */ unsigned MaxLeadingSpacesForAlignment,
+ /* TALLY */ bool ForceAlignToFourSpaces
+) {
+ // TALLY
+ unsigned ColumnLimitInEffect = AllowBeyondColumnLimitForAlignment ? Style.ColumnLimitExtended : Style.ColumnLimit;
+
+ unsigned MinColumn = 0;
+ unsigned MaxColumn = UINT_MAX;
+
+ // Line number of the start and the end of the current token sequence.
+ unsigned StartOfSequence = 0;
+ unsigned EndOfSequence = 0;
+
+ // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
+ // abort when we hit any token in a higher scope than the starting one.
+ auto IndentAndNestingLevel = StartAt < Changes.size()
+ ? Changes[StartAt].indentAndNestingLevel()
+ : std::tuple<unsigned, unsigned, unsigned>(0, 0, 0);
+
+ // Keep track of the number of commas before the matching tokens, we will only
+ // align a sequence of matching tokens if they are preceded by the same number
+ // of commas.
+ unsigned CommasBeforeLastMatch = 0;
+ unsigned CommasBeforeMatch = 0;
+
+ // Whether a matching token has been found on the current line.
+ bool FoundMatchOnLine = false;
+
+ // Aligns a sequence of matching tokens, on the MinColumn column.
+ //
+ // Sequences start from the first matching token to align, and end at the
+ // first token of the first line that doesn't need to be aligned.
+ //
+ // We need to adjust the StartOfTokenColumn of each Change that is on a line
+ // containing any matching token to be aligned and located after such token.
+ auto AlignCurrentSequence = [&] {
+ if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
+ AlignTokenSequence(StartOfSequence, EndOfSequence, MinColumn, Matches,
+ Changes, IgnoreScope, IgnoreCommas);
+ MinColumn = 0;
+ MaxColumn = UINT_MAX;
+ StartOfSequence = 0;
+ EndOfSequence = 0;
+ };
+
+ unsigned i = StartAt;
+ for (unsigned e = Changes.size(); i != e; ++i) {
+ if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
+ break;
+
+ if (Changes[i].NewlinesBefore != 0) {
+ CommasBeforeMatch = 0;
+ EndOfSequence = i;
+ // If there is a blank line, or if the last line didn't contain any
+ // matching token, the sequence ends here.
+ if (Changes[i].NewlinesBefore > MaxNewlinesBeforeSectionBreak || (NonMatchingLineBreaksSection && !FoundMatchOnLine))
+ AlignCurrentSequence();
+
+ FoundMatchOnLine = false;
+ }
+
+ if (Changes[i].Tok->is(tok::comma)) {
+ ++CommasBeforeMatch;
+ }
+ else if (!IgnoreScope && (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel)) {
+ // Call AlignTokens recursively, skipping over this scope block.
+ unsigned StoppedAt =
+ AlignTokens(Style, Matches, Changes, IgnoreScope, IgnoreCommas, i,
+ MaxNewlinesBeforeSectionBreak, NonMatchingLineBreaksSection,
+ AllowBeyondColumnLimitForAlignment, MaxLeadingSpacesForAlignment, ForceAlignToFourSpaces);
+ i = StoppedAt - 1;
+ continue;
+ }
+
+ if (!Matches(Changes[i]))
+ continue;
+
+ // If there is more than one matching token per line, or if the number of
+ // preceding commas, do not match anymore, end the sequence.
+ if (FoundMatchOnLine ||
+ (!IgnoreCommas && (CommasBeforeMatch != CommasBeforeLastMatch)))
+ AlignCurrentSequence();
+
+ CommasBeforeLastMatch = CommasBeforeMatch;
+ FoundMatchOnLine = true;
+
+ if (StartOfSequence == 0)
+ StartOfSequence = i;
+
+ unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
+ int LineLengthAfter = -Changes[i].Spaces;
+ for (unsigned j = i; j != e && Changes[j].NewlinesBefore == 0; ++j)
+ LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength;
+ unsigned ChangeMaxColumn = ColumnLimitInEffect - LineLengthAfter;
+
+ int leadingSpacesReqd = ChangeMinColumn - MinColumn;
+ if (leadingSpacesReqd < 0) {
+ leadingSpacesReqd *= -1;
+ }
+ // If we are restricted by the maximum leading spaces limit or maximum column width, end the sequence.
+ if (
+ (unsigned)leadingSpacesReqd > MaxLeadingSpacesForAlignment ||
+ ChangeMinColumn > MaxColumn ||
+ ChangeMaxColumn < MinColumn ||
+ (!IgnoreCommas && (CommasBeforeLastMatch != CommasBeforeMatch))
+ ) {
+ AlignCurrentSequence();
+ StartOfSequence = i;
+ }
+
+ MinColumn = std::max(MinColumn, ChangeMinColumn);
+ MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
+
+ // TALLY: Force align to four spaces
+ if (ForceAlignToFourSpaces) {
+ if (MinColumn % 4 != 0) {
+ unsigned int pad = 4 - (MinColumn % 4);
+ MinColumn += pad;
+ MaxColumn += pad;
+ }
+ }
+ }
+
+ EndOfSequence = i;
+ AlignCurrentSequence();
+ return i;
+}
+
+// TALLY: Align assignments on scoped variable name (WITHIN SECTION)
+void WhitespaceManager::alignConsecutiveAssignmentsOnScopedVarName() {
+ if (!Style.AlignConsecutiveAssignments.Enabled)
+ return;
+
+ AlignTokens(Style,
+ [&](const Change& C) {
+
+ bool retval =
+ (C.Tok->isScopedVarNameInDecl() &&
+ C.Tok->HasSemiColonInLine);
+
+ return retval;
+ },
+ Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
+ /*MaxNewlinesBeforeSectionBreak=*/2, /*NonMatchingLineBreaksSection=*/true,
+ /*AllowBeyondColumnLimitForAlignment=*/true, /*MaxLeadingSpacesForAlignment=*/UINT_MAX,
+ /*ForceAlignToFourSpaces*/false);
+}
+
+// TALLY : Align the consecutive constexprs
+void WhitespaceManager::alignConsecutiveLBraceOfVarDeclOrDef() {
+ if (!Style.AlignConsecutiveAssignments.Enabled)
+ return;
+
+ AlignTokens(Style,
+ [&](const Change& C) {
+ return C.Tok->isLBraceOfConstexprOrVarDelcOrDef() &&
+ C.Tok->HasSemiColonInLine; // Ensure is terminated by a semi colon.
+ },
+ Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
+ /*MaxNewlinesBeforeSectionBreak=*/2, /*NonMatchingLineBreaksSection=*/true,
+ /*AllowBeyondColumnLimitForAlignment=*/true, /*MaxLeadingSpacesForAlignment=*/UINT_MAX,
+ /*ForceAlignToFourSpaces*/true);
+}
+
+void WhitespaceManager::alignConsecutiveAssignementsOnUsing () {
+ if (!Style.AlignConsecutiveAssignments.Enabled)
+ return;
+
+ AlignTokens(Style,
+ [&](const Change& C) {
+ bool retval = (C.Tok->MyLine && C.Tok->MyLine->First &&
+ C.Tok->MyLine->First->is(tok::kw_using) &&
+ C.Tok->HasSemiColonInLine &&
+ C.Tok->Previous && C.Tok->Previous->Previous && C.Tok->Previous->Previous == C.Tok->MyLine->First &&
+ C.Tok->is(tok::equal));
+
+ return retval;
+ },
+ Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
+ /*MaxNewlinesBeforeSectionBreak=*/2, /*NonMatchingLineBreaksSection=*/true,
+ /*AllowBeyondColumnLimitForAlignment=*/true, /*MaxLeadingSpacesForAlignment=*/UINT_MAX,
+ /*ForceAlignToFourSpaces*/true);
+}
+
+// TALLY: Align assignments on variable name (ACROSS SECTIONS)
+// Mutually exclusive with alignConsecutiveAssignmentsOnVarNameWithinSection()
+void WhitespaceManager::alignConsecutiveAssignmentsOnVarNameAcrossSections() {
+ if (!Style.AlignConsecutiveAssignments.Enabled)
+ return;
+
+ AlignTokens(Style,
+ [&](const Change& C) {
+
+ return
+ C.Tok->isVarNameInDecl() &&
+ C.Tok->HasSemiColonInLine &&
+ C.Tok->LbraceCount > 0 &&
+ C.Tok->IsClassScope;
+ },
+ Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
+ /*MaxNewlinesBeforeSectionBreak=*/2, /*NonMatchingLineBreaksSection=*/false,
+ /*AllowBeyondColumnLimitForAlignment=*/true, /*MaxLeadingSpacesForAlignment=*/UINT_MAX,
+ /*ForceAlignToFourSpaces*/false);
+}
+
+// TALLY: Align assignments on variable name (WITHIN SECTION)
+// Mutually exclusive with alignConsecutiveAssignmentsOnVarNameAcrossSections()
+void WhitespaceManager::alignConsecutiveAssignmentsOnVarNameWithinSection() {
+ if (!Style.AlignConsecutiveAssignments.Enabled)
+ return;
+
+ AlignTokens(Style,
+ [&](const Change& C) {
+
+ bool retval =
+ C.Tok->isVarNameInDecl() &&
+ C.Tok->HasSemiColonInLine &&
+ !C.Tok->IsClassScope;
+
+ return retval;
+ },
+ Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
+ /*MaxNewlinesBeforeSectionBreak=*/2, /*NonMatchingLineBreaksSection=*/false,
+ /*AllowBeyondColumnLimitForAlignment=*/true, /*MaxLeadingSpacesForAlignment=*/UINT_MAX,
+ /*ForceAlignToFourSpaces*/true);
+}
+
+// TALLY: Align on bit field colon in a variable declaration (ACROSS SECTIONS)
+void WhitespaceManager::alignConsecutiveVarBitFields() {
+
+ AlignTokens(Style,
+ [&](const Change& C) {
+
+ // Do not align on ':' that is first on a line.
+ if (C.NewlinesBefore > 0)
+ return false;
+
+ // Do not align on ':' that is last on a line.
+ if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
+ return false;
+
+ return C.Tok->is(TT_BitFieldColon);
+ /*
+ return
+ C.Tok->is(tok::colon) &&
+ C.Tok->HasSemiColonInLine &&
+ C.Tok->getPreviousNonComment() != nullptr &&
+ C.Tok->getPreviousNonComment()->isVarNameInDecl();
+ */
+ },
+ Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
+ /*MaxNewlinesBeforeSectionBreak=*/2, /*NonMatchingLineBreaksSection=*/false,
+ /*AllowBeyondColumnLimitForAlignment=*/true, /*MaxLeadingSpacesForAlignment=*/UINT_MAX,
+ /*ForceAlignToFourSpaces*/false);
+}
+
+/// TALLY: Align consecutive assignments over all \c Changes (ACROSS SECTIONS)
+// Mutually exclusive with alignConsecutiveAssignmentsWithinSection()
+void WhitespaceManager::alignConsecutiveAssignmentsOnEqualsAcrossSections() {
+ if (!Style.AlignConsecutiveAssignments.Enabled)
+ return;
+
+ AlignTokens(Style,
+ [&](const Change& C) {
+ // Do not align on equal signs that are first on a line.
+ if (C.NewlinesBefore > 0)
+ return false;
+
+ // Do not align on equal signs that are last on a line.
+ if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
+ return false;
+
+ return
+ C.Tok->is(tok::equal) &&
+ C.Tok->HasSemiColonInLine &&
+ C.Tok->getPreviousNonComment() != nullptr &&
+ C.Tok->getPreviousNonComment()->isVarNameInDecl();
+ },
+ Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
+ /*MaxNewlinesBeforeSectionBreak=*/2, /*NonMatchingLineBreaksSection=*/false,
+ /*AllowBeyondColumnLimitForAlignment=*/true, /*MaxLeadingSpacesForAlignment=*/16,
+ /*ForceAlignToFourSpaces*/false);
+}
+
+/// TALLY: Align consecutive assignments over all \c Changes (WITHIN SECTION)
+// Mutually exclusive with alignConsecutiveAssignmentsDeclAcrossSections()
+void WhitespaceManager::alignConsecutiveAssignmentsOnEqualsWithinSection() {
+ if (!Style.AlignConsecutiveAssignments.Enabled)
+ return;
+
+ AlignTokens(Style,
+ [&](const Change& C) {
+ // Do not align on equal signs that are first on a line.
+ if (C.NewlinesBefore > 0)
+ return false;
+
+ // Do not align on equal signs that are last on a line.
+ if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
+ return false;
+
+ return
+ C.Tok->is(tok::equal) &&
+ C.Tok->HasSemiColonInLine &&
+ C.Tok->isPrevBeforeInterimsVarWithoutDatatype();
+ },
+ Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
+ /*MaxNewlinesBeforeSectionBreak=*/1, /*NonMatchingLineBreaksSection=*/true,
+ /*AllowBeyondColumnLimitForAlignment=*/true, /*MaxLeadingSpacesForAlignment=*/12,
+ /*ForceAlignToFourSpaces*/false);
+}
+
+/// TALLY: Columnarize specific tokens over all \c Changes.
+void WhitespaceManager::columnarizePPKeywords() {
+ // First loop
+ for (int i = 0; i < Changes.size(); ++i) {
+ const FormatToken* MyTok = Changes[i].Tok;
+
+ if (MyTok->isPPKeywordAndPrevHash()) {
+ size_t tokSize = ((StringRef)MyTok->TokenText).size() + 1;
+ MaxPPKeywordLen = MaxPPKeywordLen < tokSize ? tokSize : MaxPPKeywordLen;
+ }
+ }
+
+ unsigned toPad = MaxPPKeywordLen + 1;
+ unsigned pad = 1;
+
+ while (toPad % Style.TabWidth != 0) {
+ toPad++;
+ pad++;
+ }
+
+ // Second loop
+ for (int i = 0; i < Changes.size(); ++i) {
+
+ const FormatToken* MyTok = Changes[i].Tok;
+ const FormatToken* PrevTok = MyTok->getPreviousNonComment();
+
+ if (PrevTok && PrevTok->isPPKeywordAndPrevHash()) {
+
+ size_t tokSize = ((StringRef)PrevTok->TokenText).size() + 1;
+ size_t lenDiff = MaxPPKeywordLen - tokSize;
+
+ Changes[i].Spaces = pad + lenDiff;
+ }
+ }
+}
+
+/// TALLY: Columnarize specific tokens over all \c Changes.
+void WhitespaceManager::columnarizePPDefineKeyword() {
+ // First loop
+ for (int i = 0; i < Changes.size(); ++i) {
+ const FormatToken* MyTok = Changes[i].Tok;
+
+ if (MyTok->isPPDefineKeywordAndPrevHash()) {
+ const FormatToken* NextTok = MyTok->getNextNonComment();
+ if (NextTok) {
+ size_t tokSize = ((StringRef)NextTok->TokenText).size();
+ MaxPPDefineLHSLen = MaxPPDefineLHSLen < tokSize ? tokSize : MaxPPDefineLHSLen;
+ }
+ }
+ }
+
+ unsigned toPad = MaxPPDefineLHSLen + 1;
+ unsigned pad = 1;
+
+ while (toPad % Style.TabWidth != 0) {
+ toPad++;
+ pad++;
+ }
+
+ // Second loop
+ for (int i = 0; i < Changes.size(); ++i) {
+
+ const FormatToken* PrevTok = Changes[i].Tok->getPreviousNonComment();
+
+ if (PrevTok) {
+ const FormatToken* PrevPrevTok = PrevTok->getPreviousNonComment();
+
+ if (PrevPrevTok && PrevPrevTok->isPPDefineKeywordAndPrevHash()) {
+ // PrevTok is LHS
+ size_t tokSize = ((StringRef)PrevTok->TokenText).size();
+ size_t lenDiff = MaxPPDefineLHSLen - tokSize;
+ // Spaces before RHS
+ Changes[i].Spaces = pad + lenDiff;
+ }
+ }
+ }
+}
+
+// TALLY: Columnarize keywords tokens over all \c Changes.
+void WhitespaceManager::columnarizeKeywords()
+{
+ int spacebefswitch {};
+
+ if (!Style.AlignConsecutiveDeclarations.Enabled)
+ return;
+
+ for (int i = 0; i < Changes.size(); ++i) {
+
+ const FormatToken* MyTok = Changes[i].Tok;
+
+ if (MyTok->IsInFunctionDefinitionScope) {
+
+ if (MyTok->is(tok::kw_switch)) {
+
+ spacebefswitch = Changes[i].Spaces;
+ continue;
+ }
+
+ if (MyTok->is(tok::kw_case)) {
+
+ Changes[i].Spaces = spacebefswitch + 4;
+ Changes[i].StartOfTokenColumn = spacebefswitch + 4;
+ continue;
+ }
+ }
+ }
+}
+
+/// TALLY: Columnarize specific tokens over all \c Changes.
+// TODO: Check 'template' use-cases and adapt
+// TODO: Works only if declaration specifiers and datatypes do not have inline comments between the tokens.
+// TODO: Assumes tab size is 4. Need to fix to accept variable tab sizes.
+void WhitespaceManager::columnarizeDeclarationSpecifierTokens() {
+ unsigned dummy;
+
+ if (!Style.AlignConsecutiveDeclarations.Enabled)
+ return;
+
+ for (int i = 0; i < Changes.size(); ++i) {
+
+ const FormatToken* MyTok = Changes[i].Tok;
+
+ // 'const' is also applicable to params in addition to being a decl specifier, so filter out on LparenCount
+ if ((!(MyTok->IsClassScope || MyTok->IsStructScope)) || MyTok->LbraceCount == 0 || MyTok->LparenCount > 0)
+ continue;
+
+ const FormatToken* PrevTok = MyTok->getPreviousNonComment();
+ if (PrevTok && PrevTok->isAfterNoDiscardOrNoReturnOrTemplate(Changes[i].NewlinesBefore)) {
+ PrevTok = nullptr;
+ }
+
+ // 'const' is also applicable after parens, so filter out such tokens
+ if (MyTok->is(tok::kw_const) && PrevTok && PrevTok->is(tok::r_paren))
+ continue;
+
+ // Filter out the template token since they lie in a separate line itself.
+ if (MyTok->isAfterNoDiscardOrNoReturnOrTemplate(dummy))
+ continue;
+
+ AnnotatedLine* MyLine = MyTok->MyLine;
+
+ // As spaces before 'static' or 'virtual' has been set to zero, if static or virtual
+ // is not the first specifier in the list, then it will concatenate with the preceding
+ // specifier.
+ if ((MyTok->isDeclSpecStaticOrVirtual() && PrevTok == nullptr) || (MyTok->isDeclSpecInlineOrExtern() && MyTok->getNextNonComment()->isDeclSpecStaticOrVirtual())) {
+ Changes[i].StartOfTokenColumn = 0;
+ Changes[i].Spaces = 0;
+ MyLine->LastSpecifierPadding = MyTok->is(tok::kw_static) ? 2 : 1; // len(static)=6, len(virtual)=7
+ MyLine->LastSpecifierTabs += 2;
+ MaxSpecifierTabs = MaxSpecifierTabs < MyLine->LastSpecifierTabs ? MyLine->LastSpecifierTabs : MaxSpecifierTabs;
+ }
+ else if (MyTok->isDeclarationSpecifier()) {
+
+ if (PrevTok && PrevTok->isDeclSpecStaticOrVirtual()) {
+ Changes[i].Spaces = MyLine->LastSpecifierPadding;
+ }
+ else {
+ if (MyLine->LastSpecifierTabs == 0) {
+ MyLine->LastSpecifierTabs = 2;
+ if (MyTok->is(tok::kw_friend))
+ Changes[i].Spaces = MyTok->NewlinesBefore != 0 ? MyLine->LastSpecifierTabs * Style.TabWidth : 1;
+ }
+ else {
+ Changes[i].Spaces = MyLine->LastSpecifierPadding;
+ }
+ }
+
+ Changes[i].StartOfTokenColumn = MyLine->LastSpecifierTabs * Style.TabWidth;
+
+ // len=5
+ if (MyTok->is(tok::kw_const)) {
+ MyLine->LastSpecifierPadding = 3;
+ if (PrevTok && PrevTok->isPointerOrRef()) {
+ MyLine->LastSpecifierPadding += 1;
+ Changes[i].Spaces = MyLine->LastSpecifierPadding;
+ }
+
+ if (!PrevTok && (MyLine->MightBeFunctionDecl || MyTok->IsStructScope)) {
+ Changes[i].Spaces += MyLine->LastSpecifierPadding + 1;
+ Changes[i].StartOfTokenColumn += 4;
+ }
+ MyLine->LastSpecifierTabs += 2;
+ }
+ // len=6
+ else if (MyTok->isOneOf(tok::kw_inline, tok::kw_friend, tok::kw_extern)) {
+ MyLine->LastSpecifierPadding = 2;
+ MyLine->LastSpecifierTabs += 2;
+ }
+ // len=7
+ else if (MyTok->is(tok::kw_mutable)) {
+ MyLine->LastSpecifierPadding = 1;
+ MyLine->LastSpecifierTabs += 2;
+ }
+ // len=8
+ else if (MyTok->isOneOf(tok::kw_volatile, tok::kw_explicit, tok::kw_register)) {
+ MyLine->LastSpecifierPadding = 4;
+ MyLine->LastSpecifierTabs += 3;
+ }
+ // len=9
+ else if (MyTok->is(tok::kw_constexpr)) {
+ MyLine->LastSpecifierPadding = 3;
+ if (!PrevTok && (MyLine->MightBeFunctionDecl || MyTok->IsStructScope)) {
+ Changes[i].Spaces += MyLine->LastSpecifierPadding + 1;
+ Changes[i].StartOfTokenColumn += 4;
+ }
+ MyLine->LastSpecifierTabs += 3;
+ }
+ // len=12
+ else if (MyTok->is(tok::kw_thread_local)) {
+ MyLine->LastSpecifierPadding = 4;
+ MyLine->LastSpecifierTabs += 4;
+ }
+ // variable length
+ else if (MyTok->is(tok::kw_alignas)) {
+ const FormatToken* NextTok = MyTok->getNextNonComment();
+ size_t interimSize = 0;
+ while (NextTok && !NextTok->is(tok::r_paren))
+ {
+ interimSize += NextTok->SpacesRequiredBefore;
+ interimSize += ((StringRef)NextTok->TokenText).size();
+ NextTok = NextTok->getNextNonComment();
+ }
+ if (NextTok && NextTok->is(tok::r_paren)) {
+ interimSize += NextTok->SpacesRequiredBefore;
+ interimSize++;
+ int toPad = 7 + interimSize;
+ while (toPad % Style.TabWidth != 0)
+ toPad++;
+ MyLine->LastSpecifierPadding = toPad - (7 + interimSize);
+ MyLine->LastSpecifierTabs += (toPad / 4);
+ }
+ }
+ MaxSpecifierTabs = MaxSpecifierTabs < MyLine->LastSpecifierTabs ? MyLine->LastSpecifierTabs : MaxSpecifierTabs;
+ }
+ }
+}
+
+/// TALLY: Columnarize specific tokens over all \c Changes.
+// TODO: Works only if declaration specifiers and datatypes do not have inline comments between the tokens.
+
+void WhitespaceManager::columnarizeDatatypeTokens() {
+ if (!Style.AlignConsecutiveDeclarations.Enabled)
+ return;
+
+ if (MaxSpecifierTabs < 4)
+ MaxSpecifierTabs = 4;
+
+ int bracecount = 0;
+
+ for (int i = 0; i < Changes.size(); ++i) {
+
+ const FormatToken *MyTok = Changes[i].Tok;
+
+ if (!(MyTok->IsClassScope || MyTok->IsStructScope) || MyTok->LbraceCount == 0 || MyTok->LparenCount > 0)
+ continue;
+
+ if (MyTok->is(tok::less) && MyTok->Previous->is(tok::kw_template)) {
+
+ ++bracecount;
+ continue;
+ }
+
+ if (bracecount) {
+
+ if (MyTok->is(tok::greater))
+ --bracecount;
+ continue;
+ }
+
+ if (MyTok->IsDatatype) {
+
+ AnnotatedLine *MyLine = MyTok->MyLine;
+
+ bool functionNameAfterInterims = MyTok->isFunctionNameAfterInterims();
+ bool memVarNameAfterInterims = MyTok->isMemberVariableNameAfterInterims();
+
+ bool ismaybeunused = (MyTok->Previous && MyTok->Previous->Previous && MyTok->Previous->Previous->isMaybeUnused() && MyLine->First == MyTok->Previous->Previous);
+
+ if (functionNameAfterInterims || memVarNameAfterInterims || ismaybeunused) {
+ int j = ismaybeunused ? i - 2 : i;
+
+ size_t tokSize = ((StringRef)MyTok->TokenText).size();
+
+ FormatToken *NextTok = MyTok->getNextNonCommentNonConst();
+
+ size_t interimSize = 0;
+
+ while (NextTok && NextTok->IsInterimBeforeName) {
+
+ interimSize += NextTok->SpacesRequiredBefore;
+ interimSize += ((StringRef)NextTok->TokenText).size();
+ NextTok = NextTok->getNextNonCommentNonConst();
+ }
+
+ if (ismaybeunused) {
+ NextTok = NextTok->getNextNonCommentNonConst ();
+ if (NextTok) {
+ NextTok = NextTok->getNextNonCommentNonConst();
+ NextTok->PrevTokenSizeForColumnarization = tokSize;
+ NextTok->IsDatatype = true;
+ }
+ }
+
+ tokSize = ismaybeunused ? 4 + tokSize : interimSize + tokSize;
+
+ if (NextTok) {
+
+ if ((functionNameAfterInterims && NextTok->isFunctionAndNextLeftParen()) ||
+ (memVarNameAfterInterims && NextTok->isMemberVarNameInDecl())) {
+
+ NextTok->PrevTokenSizeForColumnarization = tokSize;
+ }
+ }
+
+ MaxDatatypeLen = MaxDatatypeLen < tokSize ? tokSize : MaxDatatypeLen;
+
+ if (MyLine->LastSpecifierTabs == 0 || MyLine->First->isMaybeUnused()) {
+
+ Changes[j].Spaces = MaxSpecifierTabs * Style.TabWidth;
+ MyLine->LastSpecifierTabs = MaxSpecifierTabs;
+ }
+ else if (MyLine->LastSpecifierTabs < MaxSpecifierTabs) {
+
+ Changes[j].Spaces = ((MaxSpecifierTabs - MyLine->LastSpecifierTabs) * Style.TabWidth) + MyLine->LastSpecifierPadding;
+ MyLine->LastSpecifierTabs = MaxSpecifierTabs;
+ }
+ else if (MyLine->LastSpecifierTabs == MaxSpecifierTabs) {
+
+ Changes[j].Spaces = MyLine->LastSpecifierPadding;
+ }
+
+ Changes[j].StartOfTokenColumn = MaxSpecifierTabs * Style.TabWidth;
+ }
+ }
+ }
+}
+
+/// TALLY : For checking if the function decl in class body is a template/nodiscard/noreturn type.
+void WhitespaceManager::columnarizeNoDiscardOrNoReturnOrTemplate() {
+ int spacecount;
+ int bracecount;
+
+ if (!Style.AlignConsecutiveDeclarations.Enabled)
+ return;
+
+ if (MaxSpecifierTabs < 4)
+ MaxSpecifierTabs = 4;
+
+ for (int i = 0; i < Changes.size(); ++i) {
+
+ const FormatToken *MyTok = Changes[i].Tok;
+
+ // Space before [[maybe_unused]]
+ if (MyTok->is(tok::l_square) && MyTok->Next && MyTok->Next->is(tok::l_square)
+ && MyTok->LparenCount
+ && (!MyTok->Previous || (MyTok->Previous && MyTok->Previous->is(tok::comment)))) {
+ Changes[i].Spaces = 1;
+ } // arrangement like LocatorType & pLocation
+ else if (MyTok->is(tok::identifier) && MyTok->Previous
+ && MyTok->Previous->isOneOf(tok::amp, tok::ampamp, tok::star)
+ && MyTok->Previous->Previous && MyTok->Previous->Previous->is(tok::identifier)
+ && MyTok->LparenCount && !IsConditionBlock(MyTok->Previous->Previous)) {
+ Changes[i].Spaces = 1;
+ }
+
+ if ((!(MyTok->IsClassScope || MyTok->IsStructScope)) || MyTok->LbraceCount == 0 || MyTok->LparenCount > 0)
+ continue;
+
+ if (MyTok->isNoDiscardOrNoReturnOrTemplate()) {
+
+ if (MyTok->is(tok::l_square)) {
+
+ Changes[i].StartOfTokenColumn = MaxSpecifierTabs * Style.TabWidth;
+ Changes[i].Spaces = MaxSpecifierTabs * Style.TabWidth;
+
+ const FormatToken *next = MyTok->getNextNonComment();
+
+ if (next && next->is(tok::l_square)) {
+
+ ++i;
+ Changes[i].StartOfTokenColumn = MaxSpecifierTabs * Style.TabWidth;
+ Changes[i].Spaces = 0;
+
+ next = next->getNextNonComment();
+ if (next && (next->TokenText.startswith("nodiscard")
+ || next->TokenText.startswith("noreturn")
+ || next->TokenText.startswith("maybe_unused"))) {
+
+ ++i;
+ Changes[i].StartOfTokenColumn += MaxSpecifierTabs * Style.TabWidth;
+ Changes[i].Spaces = 0;
+
+ next = next->getNextNonComment();
+ if (next && next->is(tok::r_square)) {
+
+ ++i;
+ Changes[i].StartOfTokenColumn += MaxSpecifierTabs * Style.TabWidth;
+ Changes[i].Spaces = 0;
+
+ next = next->getNextNonComment();
+ if (next && next->is(tok::r_square)) {
+
+ ++i;
+ Changes[i].StartOfTokenColumn += MaxSpecifierTabs * Style.TabWidth;
+ Changes[i].Spaces = 0;
+ }
+ }
+ }
+ }
+ }
+
+ FormatToken * aftertemplate = (FormatToken * )MyTok->walkTemplateBlockInClassDecl();
+ bool isfrienddecl = aftertemplate ? aftertemplate->is(tok::kw_friend) : false;
+
+ if (MyTok->is(tok::kw_template) &&
+ MyTok->MyLine &&
+ (MyTok->MyLine->MightBeFunctionDecl || isfrienddecl) &&
+ MyTok->MyLine->endsWith(tok::semi) &&
+ MyTok->LbraceCount > 0 &&
+ MyTok->LparenCount == 0 &&
+ MyTok->LArrowCount == 0) {
+
+ spacecount = 0;
+ bracecount = 0;
+
+ Changes[i].StartOfTokenColumn = isfrienddecl ? 8 : MaxSpecifierTabs * Style.TabWidth;
+ Changes[i].Spaces = isfrienddecl ? 8 : MaxSpecifierTabs * Style.TabWidth;;
+
+ ++i;
+ const FormatToken *curr = MyTok->Next;
+
+ if (curr->is(tok::less)) {
+ spacecount = 0;
+ ++bracecount;
+ }
+
+ while (bracecount) {
+
+ curr = curr->getNextNonComment();
+ ++i;
+
+ if (!curr)
+ break;
+ else if (curr->is(tok::less)) {
+ spacecount = 0;
+ ++bracecount;
+ }
+ else if (curr->is(tok::greater)) {
+ spacecount = 0;
+ --bracecount;
+ }
+ else if (curr->is(tok::comma) || curr->is(tok::ellipsis)) {
+ spacecount = 0;
+ }
+ else if (curr->isOneOf (tok::kw_template, tok::kw_typename, tok::kw_class) ||
+ curr->isDatatype()) {
+ if (curr->Previous && curr->Previous->isOneOf(tok::ellipsis, tok::less, tok::coloncolon))
+ spacecount = 0;
+ else
+ spacecount = 1;
+ }
+ else if (curr->is(tok::identifier)) {
+ if (curr->Previous && curr->Previous->isOneOf(tok::less, tok::coloncolon)) // tok::ellipsis,
+ spacecount = 0;
+ else
+ spacecount = 1;
+ }
+
+ Changes[i].StartOfTokenColumn += MaxSpecifierTabs * Style.TabWidth;
+ Changes[i].Spaces = spacecount;
+ } while (bracecount != 0);
+ }
+ }
+ }
+}
+
+/// TALLY: Columnarize specific tokens over all \c Changes.
+void WhitespaceManager::columnarizeIdentifierTokens() {
+ if (!Style.AlignConsecutiveDeclarations.Enabled)
+ return;
+
+ unsigned toPad = MaxDatatypeLen + 1;
+ unsigned pad = 1;
+
+ while (toPad % Style.TabWidth != 0) {
+ toPad++;
+ pad++;
+ }
+
+ for (int i = 0; i < Changes.size(); ++i) {
+
+ const FormatToken* MyTok = Changes[i].Tok;
+
+ if ((!(MyTok->IsClassScope || MyTok->IsStructScope)) && (MyTok->LbraceCount == 0 || MyTok->LparenCount > 0))
+ continue;
+
+ // Dont align bitfield specifiers.
+ if (MyTok->Previous && MyTok->Previous->is(TT_BitFieldColon))
+ continue;
+
+ FormatToken* NextTok = MyTok->getNextNonCommentNonConst();
+ FormatToken* PrevTok = MyTok->getPreviousNonComment();
+
+ if (MyTok->isMemberVarNameInDecl()) {
+
+ size_t lenDiff = MaxDatatypeLen - MyTok->PrevTokenSizeForColumnarization;
+
+ if (MyTok->Previous && MyTok->Previous->is(tok::l_brace) && MyTok->Next && !MyTok->Next->is(tok::comment)) {
+ Changes[i].Spaces = 0;
+ }
+ else if (MyTok->Previous && MyTok->Previous->is(tok::coloncolon) && MyTok->is(tok::identifier)) {
+ Changes[i].Spaces = 0;
+ }
+ else {
+ Changes[i].Spaces = pad + lenDiff;
+ }
+
+ int j = i + 1;
+
+ while (j < Changes.size() && Changes[j].NewlinesBefore == 0) {
+ Changes [j].StartOfTokenColumn += lenDiff;
+ ++j;
+ }
+ }
+ else if (MyTok->isFunctionNameAndPrevIsPointerOrRefOrDatatype() && !MyTok->IsInFunctionDefinitionScope) {
+ size_t tokSize = adjectIdentifierLocation (pad, i, MyTok);
+
+ if (MyTok->is(tok::kw_operator)) {
+ NextTok = NextTok->Next;
+ ++i;
+ }
+
+ if (NextTok)
+ NextTok->PrevTokenSizeForColumnarization = tokSize;
+ }
+ //else if (MyTok->is(tok::kw_operator)) {
+ // size_t tokSize = adjectIdentifierLocation (pad, i, MyTok);
+ // NextTok = NextTok->Next;
+ // if (NextTok)
+ // NextTok->PrevTokenSizeForColumnarization = tokSize;
+ //}
+ else if (MyTok->isConstructor()) {
+ size_t tokSize = 0;
+
+ if (PrevTok && PrevTok->is(tok::kw_constexpr)) { // && (MyTok->IsClassScope || MyTok->IsStructScope)
+ tokSize = adjectIdentifierLocation (pad, i, MyTok, true);
+ }
+ //else if (PrevTok && PrevTok->is(tok::kw_constexpr)) {
+ // Changes[i].Spaces = 0;
+ //}
+ else {
+ Changes[i].Spaces = MaxSpecifierTabs * Style.TabWidth + MaxDatatypeLen + pad;
+ tokSize = ((StringRef)MyTok->TokenText).size();
+ MaxMemberNameLen = MaxMemberNameLen < tokSize ? tokSize : MaxMemberNameLen;
+ }
+
+ if (NextTok)
+ NextTok->PrevTokenSizeForColumnarization = tokSize;
+ }
+ else if (MyTok->isDestructor()) {
+ Changes[i].Spaces = MaxSpecifierTabs * Style.TabWidth + MaxDatatypeLen + pad;
+ if (Changes[i].Spaces > 1)
+ Changes[i].Spaces -= 1;
+
+ if (NextTok) {
+ // Size of 'next'
+ size_t tokSize = ((StringRef)NextTok->TokenText).size();
+ MaxMemberNameLen = MaxMemberNameLen < tokSize ? tokSize : MaxMemberNameLen;
+
+ FormatToken* NextNextTok = NextTok->getNextNonCommentNonConst();
+
+ if (NextNextTok)
+ NextNextTok->PrevTokenSizeForColumnarization = tokSize;
+ }
+ }
+ else if (MyTok->is(tok::l_brace) && MyTok->Previous
+ && MyTok->Previous->is(tok::identifier)
+ && MyTok->Previous->Previous
+ && MyTok->Previous->Previous->is(tok::star)) {
+ // populate MaxGlobalVarNameLen
+ if (MaxGlobalVarNameLen < MyTok->Previous->ColumnWidth)
+ MaxGlobalVarNameLen = MyTok->Previous->ColumnWidth;
+ }
+ }
+}
+
+/// TALLY: Columnarize specific tokens over all \c Changes.
+void WhitespaceManager::columnarizeLParenTokensAndSplitArgs() {
+ bool insideargs = false;
+ int newlineargssize = 0;
+
+ if (!Style.AlignConsecutiveDeclarations.Enabled)
+ return;
+
+ unsigned toPad = MaxMemberNameLen + 1;
+ unsigned pad = 1;
+
+ while (toPad % Style.TabWidth != 0) {
+ toPad++;
+ pad++;
+ }
+
+ for (int i = 0; i < Changes.size(); ++i) {
+
+ const FormatToken* MyTok = Changes[i].Tok;
+
+ if ((!(MyTok->IsClassScope || MyTok->IsStructScope)) && MyTok->LbraceCount == 0)
+ continue;
+
+ FormatToken* PrevTok = MyTok->getPreviousNonComment();
+
+ if (MyTok->is(tok::l_paren) && !MyTok->IsInFunctionDefinitionScope && PrevTok && PrevTok->isFunctionOrCtorOrPrevIsDtor()) {
+ size_t lenDiff = MaxMemberNameLen - MyTok->PrevTokenSizeForColumnarization;
+ Changes[i].Spaces = pad + lenDiff;
+ newlineargssize = toPad + MaxSpecifierTabs * Style.TabWidth + MaxDatatypeLen + pad + 2;
+ insideargs = true;
+ }
+ else if (MyTok->is(tok::l_brace) && PrevTok && PrevTok->is(tok::identifier)
+ && MyTok->Previous->Previous && MyTok->Previous->Previous->is(tok::star)) {
+ size_t lenDiff = MaxGlobalVarNameLen - PrevTok->ColumnWidth;
+ Changes[i].Spaces = 1 + lenDiff;
+ insideargs = false;
+ }
+ else if (MyTok->is(tok::l_brace) && PrevTok && PrevTok->is(tok::identifier)
+ && MyTok->Previous->Previous && MyTok->Previous->Previous->is(tok::kw_operator)) {
+ size_t lenDiff = MaxGlobalVarNameLen - PrevTok->ColumnWidth;
+ Changes[i].Spaces = pad + lenDiff;
+ insideargs = false;
+ }
+
+ if (insideargs && MyTok->is(tok::r_paren))
+ insideargs = false;
+
+ if (insideargs)
+ if (MyTok->NewlinesBefore > 0)
+ Changes[i].Spaces = newlineargssize;
+ }
+}
+
// Aligns a sequence of matching tokens, on the MinColumn column.
//
// Sequences start from the first matching token to align, and end at the
@@ -986,7 +2118,7 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
if (C.Tok->is(TT_FunctionTypeLParen))
return true;
}
- if (C.Tok->is(TT_FunctionDeclarationName))
+ if (C.Tok->isOneOf(TT_FunctionDeclarationName, tok::kw_operator))
return true;
if (C.Tok->isNot(TT_StartOfName))
return false;
@@ -1757,5 +2889,37 @@ unsigned WhitespaceManager::appendTabIndent(std::string &Text, unsigned Spaces,
return Spaces;
}
+//TALLY
+size_t WhitespaceManager::adjectIdentifierLocation (unsigned pad, unsigned idx, const FormatToken * tkn, bool isConstructor)
+{
+ static const StringRef lparanthese ("(");
+ size_t lenDiff = MaxDatatypeLen - tkn->PrevTokenSizeForColumnarization;
+ int j = idx + 1;
+
+ if (isConstructor)
+ Changes[idx].Spaces = MaxSpecifierTabs * Style.TabWidth + MaxDatatypeLen + pad - (Changes[idx - 1].Spaces + Changes[idx - 1].TokenLength);
+ else if (tkn->Previous && tkn->Previous->is(tok::kw_const) && tkn->Next && tkn->Next->TokenText.equals(lparanthese))
+ Changes[idx].Spaces += pad;// > lenDiff ? pad - lenDiff : lenDiff - pad;
+ else
+ Changes[idx].Spaces = pad + lenDiff;
+
+ size_t tokSize = ((StringRef)tkn->TokenText).size();
+
+ if (tkn->is(tok::kw_operator)) {
+ tokSize += tkn->Next->ColumnWidth;
+ Changes[idx + 1].Spaces = 0; // TODO : Vivek changed from -1 to 0
+ ++j;
+ }
+
+ MaxMemberNameLen = MaxMemberNameLen < tokSize ? tokSize : MaxMemberNameLen;
+
+ while (j < Changes.size() && Changes[j].NewlinesBefore == 0) {
+ Changes[j].StartOfTokenColumn += lenDiff;
+ ++j;
+ }
+
+ return tokSize;
+}
+
} // namespace format
} // namespace clang
diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h
index 8ac73305871ae7..9e6017c636c0cb 100644
--- a/clang/lib/Format/WhitespaceManager.h
+++ b/clang/lib/Format/WhitespaceManager.h
@@ -212,6 +212,9 @@ class WhitespaceManager {
}
};
+ /// TALLY: Is code in condition block.
+ bool IsConditionBlock(const FormatToken *tkn);
+
/// Calculate \c IsTrailingComment, \c TokenLength for the last tokens
/// or token parts in a line and \c PreviousEndOfTokenColumn and
/// \c EscapedNewlineColumn for the first tokens or token parts in a line.
@@ -220,12 +223,60 @@ class WhitespaceManager {
/// \brief Align consecutive C/C++ preprocessor macros over all \c Changes.
void alignConsecutiveMacros();
+ /// TALLY: Align consecutive assignments over all \c Changes.
+ void alignConsecutiveAssignmentsOnScopedVarName();
+
+ /// TALLY : Align 'using' based assignments;
+ void alignConsecutiveAssignementsOnUsing ();
+
+ /// TALLY: Align consecutive assignments over all \c Changes.
+ void alignConsecutiveAssignmentsOnVarNameAcrossSections();
+
+ /// TALLY: Align consecutive assignments over all \c Changes.
+ void alignConsecutiveAssignmentsOnVarNameWithinSection();
+
+ /// TALLY: Align consecutive assignments over all \c Changes.
+ void alignConsecutiveVarBitFields();
+
+ // TALLY: Mutually exclusive with alignConsecutiveAssignmentsOnEqualsWithinSection()
+ void alignConsecutiveAssignmentsOnEqualsAcrossSections();
+
+ // TALLY: Mutually exclusive with alignConsecutiveAssignmentsOnEqualsAcrossSections()
+ void alignConsecutiveAssignmentsOnEqualsWithinSection();
+
/// Align consecutive assignments over all \c Changes.
void alignConsecutiveAssignments();
/// Align consecutive bitfields over all \c Changes.
void alignConsecutiveBitFields();
+ // TALLY : Align consecutive constexprs.
+ void alignConsecutiveLBraceOfVarDeclOrDef();
+
+ /// TALLY: Columnarize specific tokens over all \c Changes.
+ void columnarizePPKeywords();
+
+ /// TALLY: Columnarize specific tokens over all \c Changes.
+ void columnarizePPDefineKeyword();
+
+ /// TALLY: Columnarize keywords all \c Changes.
+ void columnarizeKeywords();
+
+ /// TALLY: Columnarize specific tokens over all \c Changes.
+ void columnarizeDeclarationSpecifierTokens();
+
+ /// TALLY: Columnarize specific tokens over all \c Changes.
+ void columnarizeDatatypeTokens();
+
+ /// TALLY: Columnarize NoDiscard NoReturn, and template.
+ void columnarizeNoDiscardOrNoReturnOrTemplate();
+
+ /// TALLY: Columnarize specific tokens over all \c Changes.
+ void columnarizeIdentifierTokens();
+
+ /// TALLY: Columnarize specific tokens over all \c Changes.
+ void columnarizeLParenTokensAndSplitArgs();
+
/// Align consecutive declarations over all \c Changes.
void alignConsecutiveDeclarations();
@@ -355,6 +406,17 @@ class WhitespaceManager {
tooling::Replacements Replaces;
const FormatStyle &Style;
bool UseCRLF;
+
+ // TALLY
+ size_t adjectIdentifierLocation (unsigned pad, unsigned idx, const FormatToken * tkn, bool isConstructor = false);
+
+ // TALLY
+ size_t MaxPPKeywordLen = 0;
+ size_t MaxPPDefineLHSLen = 0;
+ size_t MaxSpecifierTabs = 0;
+ size_t MaxDatatypeLen = 0;
+ size_t MaxMemberNameLen = 0;
+ size_t MaxGlobalVarNameLen = 0;
};
} // namespace format
diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp
index e122cea50f7268..1e5655282deddb 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -26,6 +26,9 @@
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Process.h"
#include <fstream>
+/// TALLY
+#include <stack>
+#include <string>
using namespace llvm;
using clang::tooling::Replacements;
@@ -398,6 +401,175 @@ class ClangFormatDiagConsumer : public DiagnosticConsumer {
}
};
+enum class TemplateCheckError {
+
+ NotTemplate,
+ BracesMismatch,
+};
+
+/// TALLY, Scan to see if following test is a template declaration.
+static bool IsTemplateReference(const char * Data, int & idx, TemplateCheckError & ErrVal)
+{
+ using namespace std;
+ stack<char> tmplt_braces;
+ int pIdx = idx - 1;
+
+ tmplt_braces.push('<');
+ while (Data[idx] != '\0') {
+
+ if (Data[idx] == ';' || Data[idx] == '{' || Data[idx] == '[' || Data[idx] == '('
+ || Data[idx] == '}' || Data[idx] == ']' || Data[idx] == ')') {
+
+ if (tmplt_braces.size() == 1 && Data[idx] == ';') {
+
+ ++idx;
+ ErrVal = TemplateCheckError::NotTemplate;
+ return false;
+ }
+ else {
+
+ ++idx;
+ ErrVal = TemplateCheckError::BracesMismatch;
+ return false;
+ }
+ }
+ if (Data[idx] == '>') {
+
+ tmplt_braces.pop();
+
+ if (tmplt_braces.size() == 0) {
+
+ ++idx;
+ return true;
+ }
+ }
+ else if (Data[idx] == '<') {
+
+ if (pIdx == idx - 1) {
+ // it is "<<"
+ ++idx;
+ ErrVal = TemplateCheckError::NotTemplate;
+ return false;
+ }
+ tmplt_braces.push(Data[idx]);
+ }
+
+ ++idx;
+ }
+
+ ErrVal = TemplateCheckError::BracesMismatch;
+ return false;
+}
+
+/// TALLY, A lightweight scan to see if file has correct number of braces '{}, () []'.
+/// Need to add support for template related braces '<>'
+static bool MissingNotBraces(StringRef BufStr) {
+ using namespace std;
+
+ stack<char> braces;
+ const char * data = BufStr.data();
+
+ const char doustr {'"'};
+ const char single {'\''};
+ const char l_curly {'{'};
+ const char l_square {'['};
+ const char l_curve {'('};
+ const char r_curly {'}'};
+ const char r_square {']'};
+ const char r_curve {')'};
+ bool instr {false}; // in string
+ int dblstrcnt {}; //
+ int sglstrcnt {}; //
+ int idx {};
+
+ while (data[idx] != '\0') {
+
+ char ch = data[idx];
+
+ // ignore comment line
+ if (!instr && ch == '/') {
+ ch = data[++idx];
+ if (ch == '/') { // skip till we reach at "\n" or end of string '\0'
+ while (data[++idx] != '\n' && data[idx] != '\0')
+ ;
+
+ continue;
+ }
+ else if (ch == '*') { // the comment start with /* and so will end with */
+ ++idx;
+ while (data[idx] != '\0') { // this is a comment
+ if (data[idx] == '*' && data[idx + 1] == '/') {
+ ++idx;
+ break;
+ }
+ ++idx;
+ }
+ if (data[idx] == '\0')
+ break;
+
+ ++idx;
+ continue;
+ }
+ } // comment check section end
+
+ // ignore anything in single or double quotes
+ // if single-quote, double quote and braces are inside single or double quote then move forward
+ if ((ch == single && (data[idx + 2] == single))
+ || (ch == doustr && (data[idx + 2] == doustr))) {
+ idx += 3;
+ if (data[idx] == single || data[idx] == doustr)
+ ++idx;
+ continue;
+ } else if (ch == single && data[idx + 1] == '\\' && data[idx + 2] == doustr && data[idx + 3] == single) {
+ idx += 4;
+ continue;
+ }
+
+ // Ignore whatever is part of string
+ if (ch == doustr) {
+ char pch;
+
+ ++idx;
+ while (data[idx] != doustr) {
+ pch = data[idx];
+ ++idx;
+ if (pch == '\\' && data[idx] == doustr)
+ ++idx;
+
+ continue;
+ }
+ ++idx;
+ continue;
+ }
+
+ // template support to be added
+ if ((ch == l_curly || ch == l_square || ch == l_curve)) { // TODO: || ch == l_angle
+ braces.push(ch);
+ }
+ else if (ch == r_curly || ch == r_square || ch == r_curve) { // tempalte bracket to be handled.
+ if (braces.empty())
+ return false;
+
+ char val = braces.top();
+
+ if ((ch == r_curly) && (val == l_curly))
+ braces.pop();
+ else if ((ch == r_square) && (val == l_square))
+ braces.pop();
+ else if ((ch == r_curve) && (val == l_curve))
+ braces.pop();
+ else
+ return false;
+ }
+ ++idx;
+ }
+
+ if (!braces.empty())
+ return false;
+
+ return true;
+}
+
// Returns true on error.
static bool format(StringRef FileName) {
const bool IsSTDIN = FileName == "-";
@@ -431,6 +603,13 @@ static bool format(StringRef FileName) {
return true;
}
+ /// TALLY scan current file for mismatch braces, and return if found.
+ if (!MissingNotBraces(BufStr)) {
+
+ llvm::errs() << "error: file has mismatch braces\n";
+ return false;
+ }
+
std::vector<tooling::Range> Ranges;
if (fillRanges(Code.get(), Ranges))
return true;
>From cba3ccfef6f087fba7f427981386a4551b89c876 Mon Sep 17 00:00:00 2001
From: Vivek Pandey <vivek.pandey at tallysolutions.com>
Date: Mon, 4 Mar 2024 20:49:45 +0530
Subject: [PATCH 2/4] controlled return statement and struct variable
declaration
---
clang/lib/Format/TokenAnnotator.cpp | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 890545b258c1e3..5023152d49c19e 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -3815,7 +3815,22 @@ void TokenAnnotator::walkLine1(AnnotatedLine& Line) {
IsStructScope = true;
const FormatToken* Next = MyToken->getNextNonComment();
if (Next) {
- StructScopeName = Next->TokenText;
+ if (Next->is(tok::kw_alignas) && Next->Next && Next->Next->is(tok::l_paren)
+ && Next->Next->Next && Next->Next->Next->Next && Next->Next->Next->Next->is(tok::r_paren)
+ && Next->Next->Next->Next->Next) {
+
+ Next = Next->Next->Next->Next->Next;
+ if (Next->Next && (Next->Next->isOneOf(tok::l_brace, tok::colon) ||
+ (Next->Next->is(tok::kw___is_final) && Next->Next->Next && Next->Next->Next->isOneOf(tok::l_brace, tok::colon))))
+ Next = Next;
+ }
+
+ if (Next && Next->Next && Next->Next->is(tok::l_brace))
+ StructScopeName = Next->TokenText;
+ else if (Next && Next->is(tok::l_brace))
+ StructScopeName = StructScopeName; // struct without name.
+ else
+ IsStructScope = false; // It many be inside function definition.
}
}
if (MyToken->is(tok::kw_union)) {
@@ -4077,7 +4092,7 @@ void TokenAnnotator::walkLine2(AnnotatedLine& Line) {
while (Next != nullptr && Next->isNot (tok::semi)) {
if (Next->isOneOf(tok::l_paren, tok::r_paren, tok::less, tok::lessless, tok::lesslessequal,
- tok::greater, tok::greatergreater, tok::greatergreaterequal,
+ tok::greater, tok::greatergreater, tok::greatergreaterequal, tok::kw_return,
tok::period, tok::periodstar, tok::arrow, tok::arrowstar, tok::kw_goto,
tok::pipe, tok::pipeequal,tok::pipepipe, tok::caret, tok::caretequal,
tok::ampamp, tok::ampequal, tok::starequal, tok::plusequal, tok::plusplus,
>From e81b29bb8921e4f8bf45ec9ed1dbc418d90447a4 Mon Sep 17 00:00:00 2001
From: Vivek Pandey <vivek.pandey at tallysolutions.com>
Date: Sat, 9 Mar 2024 12:20:23 +0530
Subject: [PATCH 3/4] Handled formatting of line with continue, break and
template variable declaration
---
clang/lib/Format/TokenAnnotator.cpp | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 5023152d49c19e..b44de3b220e095 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -4091,12 +4091,35 @@ void TokenAnnotator::walkLine2(AnnotatedLine& Line) {
bool isDT = true;
while (Next != nullptr && Next->isNot (tok::semi)) {
+ if (Next->is(tok::less)) { // this might be template variable declaration
+ Next = Next->Next;
+ isDT = false;
+ while (Next != nullptr && Next->isNot (tok::semi)) {
+ if (Next->is(tok::greater)) {
+ // Possible a data type
+ isDT = true;
+ }
+ else if (Next->is(tok::r_paren) && isDT) {
+ // Handling case like tempalte function invocation, say SomeFun<RetType>();
+ isDT = false;
+ }
+ Next = Next->Next;
+ }
+ if (!isDT && (Next != nullptr && Next->is (tok::semi))) {
+ // not a data type
+ Next = nullptr;
+ break;
+ }
+ else
+ break;
+ }
if (Next->isOneOf(tok::l_paren, tok::r_paren, tok::less, tok::lessless, tok::lesslessequal,
tok::greater, tok::greatergreater, tok::greatergreaterequal, tok::kw_return,
tok::period, tok::periodstar, tok::arrow, tok::arrowstar, tok::kw_goto,
tok::pipe, tok::pipeequal,tok::pipepipe, tok::caret, tok::caretequal,
tok::ampamp, tok::ampequal, tok::starequal, tok::plusequal, tok::plusplus,
- tok::minusequal, tok::minusminus, tok::percentequal, tok::slashequal)) {
+ tok::minusequal, tok::minusminus, tok::percentequal, tok::slashequal,
+ tok::kw_continue, tok::kw_break)) {
isDT = false;
Next = nullptr;
break;
>From e00eee301c844d73a472a15492313ac86934306a Mon Sep 17 00:00:00 2001
From: Yash Kumar <yash.kumar at tallysolutions.com>
Date: Tue, 30 Apr 2024 16:02:59 +0530
Subject: [PATCH 4/4] Fix endline comment alignment, inline constructor
definition alignment, variable name alignment with bit field
---
clang/include/clang/Format/Format.h | 6 +-
clang/lib/Format/FormatToken.h | 15 +-
clang/lib/Format/WhitespaceManager.cpp | 89 ++++-
clang/unittests/CMakeLists.txt | 1 +
clang/unittests/TWClangFormat/CMakeLists.txt | 15 +
clang/unittests/TWClangFormat/DummyTest.cpp | 45 +++
.../unittests/TWClangFormat/FormatTestBase.h | 179 +++++++++
.../unittests/TWClangFormat/FormatTestUtils.h | 74 ++++
.../TWClangFormat/TWClangTests.vcxproj | 139 +++++++
.../TWClangTests.vcxproj.filters | 25 ++
.../TWClangFormat/TWClangTests.vcxproj.user | 4 +
clang/unittests/TWClangFormat/TestLexer.h | 122 ++++++
.../TWClangFormat/x64/Debug/TWClangTests.log | 357 ++++++++++++++++++
.../Debug/TWClangTests.tlog/CL.command.1.tlog | 1 +
.../TWClangTests.lastbuildstate | 2 +
.../Debug/TWClangTests.tlog/unsuccessfulbuild | 0
.../TWClangFormat/x64/Debug/vc143.idb | Bin 0 -> 19456 bytes
.../TWClangFormat/x64/Debug/vc143.pdb | Bin 0 -> 156672 bytes
18 files changed, 1058 insertions(+), 16 deletions(-)
create mode 100644 clang/unittests/TWClangFormat/CMakeLists.txt
create mode 100644 clang/unittests/TWClangFormat/DummyTest.cpp
create mode 100644 clang/unittests/TWClangFormat/FormatTestBase.h
create mode 100644 clang/unittests/TWClangFormat/FormatTestUtils.h
create mode 100644 clang/unittests/TWClangFormat/TWClangTests.vcxproj
create mode 100644 clang/unittests/TWClangFormat/TWClangTests.vcxproj.filters
create mode 100644 clang/unittests/TWClangFormat/TWClangTests.vcxproj.user
create mode 100644 clang/unittests/TWClangFormat/TestLexer.h
create mode 100644 clang/unittests/TWClangFormat/x64/Debug/TWClangTests.log
create mode 100644 clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/CL.command.1.tlog
create mode 100644 clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/TWClangTests.lastbuildstate
create mode 100644 clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/unsuccessfulbuild
create mode 100644 clang/unittests/TWClangFormat/x64/Debug/vc143.idb
create mode 100644 clang/unittests/TWClangFormat/x64/Debug/vc143.pdb
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 9c725320740982..8b4facf9503663 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -31,7 +31,7 @@ class FileSystem;
namespace clang {
namespace format {
-
+
enum class ParseError {
Success = 0,
Error,
@@ -5275,7 +5275,9 @@ inline StringRef getLanguageName(FormatStyle::LanguageKind Language) {
bool isClangFormatOn(StringRef Comment);
bool isClangFormatOff(StringRef Comment);
-
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
+ FormatStyle *Style, bool AllowUnknownOptions);
} // end namespace format
} // end namespace clang
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 3b6ae1949252ce..6af05765d0d561 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -1244,7 +1244,13 @@ struct FormatToken {
// TALLY: Is this token a class or struct member variable name
bool isMemberVarNameInDecl() const {
- if (!HasSemiColonInLine || (!(IsClassScope || IsStructScope)) || LbraceCount == 0)
+ //if (!HasSemiColonInLine || (!(IsClassScope || IsStructScope)) || LbraceCount == 0)
+ // return false;
+
+ if (!HasSemiColonInLine || LbraceCount == 0)
+ return false;
+
+ if (!((IsClassScope || IsStructScope) and LbraceCount-RbraceCount==1))
return false;
return IsVariableNameWithDatatype;
@@ -1269,6 +1275,7 @@ struct FormatToken {
bool nextOk = false;
if (is(tok::identifier)) {
const FormatToken* MyPrev = getPreviousNonComment();
+ const FormatToken* MyNext = getNextNonComment();
if (MyPrev) {
if (MyPrev->isDatatype()) {
prevOk = true;
@@ -1276,7 +1283,8 @@ struct FormatToken {
else if (MyPrev && (MyPrev->isDatatype() || MyPrev->isPointerOrRef())) {
prevOk = true;
}
- else if (MyPrev && (MyPrev->is(tok::coloncolon)) && MyPrev->Previous && MyPrev->Previous->is(tok::identifier)) {
+ // TODO: condition might not be needed
+ else if (MyPrev && (MyPrev->is(tok::coloncolon) && MyNext && !MyNext->is(tok::semi)) && MyPrev->Previous && MyPrev->Previous->is(tok::identifier)) {
prevOk = true;
}
else if (MyPrev->IsInterimBeforeName) {
@@ -1289,7 +1297,6 @@ struct FormatToken {
}
}
}
- const FormatToken* MyNext = getNextNonComment();
if (MyNext) {
if (MyNext->isOneOf(tok::equal, tok::semi, tok::l_square, tok::comma, tok::r_paren)) {
nextOk = true;
@@ -1302,7 +1309,7 @@ struct FormatToken {
}
else if (MyNext->is(tok::colon)) {
const FormatToken* MyNext2 = MyNext->getNextNonComment();
- if (MyNext2 && MyNext2->is(tok::numeric_constant)) {
+ if (MyNext2 && (MyNext2->is(tok::numeric_constant) || MyNext2->is(tok::identifier))) {
nextOk = true;
}
}
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index cfac0ad0da935a..72ae7b48ddd71c 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -110,7 +110,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
columnarizeDeclarationSpecifierTokens(); // TALLY
columnarizeDatatypeTokens(); // TALLY
columnarizeNoDiscardOrNoReturnOrTemplate (); // TALLY
- columnarizeIdentifierTokens(); // TALLY
+ columnarizeIdentifierTokens(); // TALLY {}
columnarizeLParenTokensAndSplitArgs(); // TALLY
alignConsecutiveAssignmentsOnScopedVarName(); // TALLY
alignConsecutiveAssignmentsOnVarNameAcrossSections(); // TALLY
@@ -1058,11 +1058,11 @@ void WhitespaceManager::alignConsecutiveAssignmentsOnVarNameAcrossSections() {
AlignTokens(Style,
[&](const Change& C) {
- return
- C.Tok->isVarNameInDecl() &&
+ bool retval = C.Tok->isVarNameInDecl() &&
C.Tok->HasSemiColonInLine &&
C.Tok->LbraceCount > 0 &&
C.Tok->IsClassScope;
+ return retval;
},
Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
/*MaxNewlinesBeforeSectionBreak=*/2, /*NonMatchingLineBreaksSection=*/false,
@@ -1084,6 +1084,8 @@ void WhitespaceManager::alignConsecutiveAssignmentsOnVarNameWithinSection() {
C.Tok->HasSemiColonInLine &&
!C.Tok->IsClassScope;
+ //bool retval =
+ // C.Tok->isVarNameInDecl() && C.Tok->HasSemiColonInLine;
return retval;
},
Changes, /*IgnoreScope=*/false, /*IgnoreCommas=*/false, /*StartAt=*/0,
@@ -1432,6 +1434,8 @@ void WhitespaceManager::columnarizeDatatypeTokens() {
if (!(MyTok->IsClassScope || MyTok->IsStructScope) || MyTok->LbraceCount == 0 || MyTok->LparenCount > 0)
continue;
+ if (MyTok->LbraceCount - MyTok->RbraceCount > 1) continue;
+
if (MyTok->is(tok::less) && MyTok->Previous->is(tok::kw_template)) {
++bracecount;
@@ -1672,6 +1676,8 @@ void WhitespaceManager::columnarizeIdentifierTokens() {
if ((!(MyTok->IsClassScope || MyTok->IsStructScope)) && (MyTok->LbraceCount == 0 || MyTok->LparenCount > 0))
continue;
+ if (MyTok->LbraceCount - MyTok->RbraceCount > 1) continue;
+
// Dont align bitfield specifiers.
if (MyTok->Previous && MyTok->Previous->is(TT_BitFieldColon))
continue;
@@ -1732,6 +1738,55 @@ void WhitespaceManager::columnarizeIdentifierTokens() {
MaxMemberNameLen = MaxMemberNameLen < tokSize ? tokSize : MaxMemberNameLen;
}
+ // check if constructor has definition in hpp
+ // align definition with constructor name/noexcept
+ for (int j = i; j < Changes.size(); j++) {
+ const FormatToken* cur_tok = Changes[j].Tok;
+
+ if (cur_tok->is(tok::semi)) {
+ // if semicolon found
+ // then it is only declaration
+
+ break;
+
+ } else if (cur_tok->is(tok::l_brace)) {
+ // if left brace found
+ // then indent all lines till definition ends;
+
+ int old_spaces = Changes[j].Spaces;
+ if (PrevTok && PrevTok->is(tok::kw_constexpr)) {
+ Changes[j].Spaces = Changes[i-1].Spaces;
+ } else {
+ Changes[j].Spaces = Changes[i].Spaces;
+ }
+
+ int space_increment = Changes[j].Spaces - old_spaces;
+ int lbrace_cout = 1;
+
+ for (int k = j+1; k < Changes.size();k++) {
+ if (Changes[k].NewlinesBefore != 0) {
+ Changes[k].Spaces += space_increment;
+
+ // correct StartOfTokenColumn of rest of tokens in the line
+ for (int y=k; y < Changes.size() && Changes[y].NewlinesBefore == 0; y++) {
+ Changes[y].StartOfTokenColumn += space_increment;
+ }
+ }
+ if (Changes[k].Tok->is(tok::l_brace)) {
+ lbrace_cout++;
+ }
+ if (Changes[k].Tok->is(tok::r_brace)) {
+ lbrace_cout--;
+ }
+ if (lbrace_cout==0) {
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+
if (NextTok)
NextTok->PrevTokenSizeForColumnarization = tokSize;
}
@@ -1786,26 +1841,37 @@ void WhitespaceManager::columnarizeLParenTokensAndSplitArgs() {
continue;
FormatToken* PrevTok = MyTok->getPreviousNonComment();
+ size_t lenDiff=0;
if (MyTok->is(tok::l_paren) && !MyTok->IsInFunctionDefinitionScope && PrevTok && PrevTok->isFunctionOrCtorOrPrevIsDtor()) {
- size_t lenDiff = MaxMemberNameLen - MyTok->PrevTokenSizeForColumnarization;
+ lenDiff = MaxMemberNameLen - MyTok->PrevTokenSizeForColumnarization;
Changes[i].Spaces = pad + lenDiff;
newlineargssize = toPad + MaxSpecifierTabs * Style.TabWidth + MaxDatatypeLen + pad + 2;
insideargs = true;
}
else if (MyTok->is(tok::l_brace) && PrevTok && PrevTok->is(tok::identifier)
&& MyTok->Previous->Previous && MyTok->Previous->Previous->is(tok::star)) {
- size_t lenDiff = MaxGlobalVarNameLen - PrevTok->ColumnWidth;
+ lenDiff = MaxGlobalVarNameLen - PrevTok->ColumnWidth;
Changes[i].Spaces = 1 + lenDiff;
insideargs = false;
}
else if (MyTok->is(tok::l_brace) && PrevTok && PrevTok->is(tok::identifier)
&& MyTok->Previous->Previous && MyTok->Previous->Previous->is(tok::kw_operator)) {
- size_t lenDiff = MaxGlobalVarNameLen - PrevTok->ColumnWidth;
+ lenDiff = MaxGlobalVarNameLen - PrevTok->ColumnWidth;
Changes[i].Spaces = pad + lenDiff;
insideargs = false;
}
+ if (lenDiff!=0) {
+
+ int j = i;
+
+ while (j < Changes.size() && Changes[j].NewlinesBefore == 0) {
+ Changes [j].StartOfTokenColumn += lenDiff;
+ ++j;
+ }
+ }
+
if (insideargs && MyTok->is(tok::r_paren))
insideargs = false;
@@ -2329,7 +2395,7 @@ void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
unsigned Column) {
for (unsigned i = Start; i != End; ++i) {
int Shift = 0;
- if (Changes[i].IsTrailingComment)
+ if (Changes[i].IsTrailingComment)
Shift = Column - Changes[i].StartOfTokenColumn;
if (Changes[i].StartOfBlockComment) {
Shift = Changes[i].IndentationOffset +
@@ -2913,9 +2979,12 @@ size_t WhitespaceManager::adjectIdentifierLocation (unsigned pad, unsigned idx,
MaxMemberNameLen = MaxMemberNameLen < tokSize ? tokSize : MaxMemberNameLen;
- while (j < Changes.size() && Changes[j].NewlinesBefore == 0) {
- Changes[j].StartOfTokenColumn += lenDiff;
- ++j;
+ if (lenDiff!=0) {
+ j = idx;
+ while (j < Changes.size() && Changes[j].NewlinesBefore == 0) {
+ Changes[j].StartOfTokenColumn += lenDiff;
+ ++j;
+ }
}
return tokSize;
diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt
index f4e4f585bdd800..b1e04b514232b0 100644
--- a/clang/unittests/CMakeLists.txt
+++ b/clang/unittests/CMakeLists.txt
@@ -36,6 +36,7 @@ add_subdirectory(CrossTU)
add_subdirectory(Tooling)
add_subdirectory(Introspection)
add_subdirectory(Format)
+add_subdirectory(TWClangFormat)
add_subdirectory(Frontend)
add_subdirectory(Rewrite)
add_subdirectory(Sema)
diff --git a/clang/unittests/TWClangFormat/CMakeLists.txt b/clang/unittests/TWClangFormat/CMakeLists.txt
new file mode 100644
index 00000000000000..1bd59eba6f377f
--- /dev/null
+++ b/clang/unittests/TWClangFormat/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_unittest(TWClangTests
+ DummyTest.cpp
+ )
+
+clang_target_link_libraries(TWClangTests
+ PRIVATE
+ clangBasic
+ clangFormat
+ clangRewrite
+ clangToolingCore
+ )
diff --git a/clang/unittests/TWClangFormat/DummyTest.cpp b/clang/unittests/TWClangFormat/DummyTest.cpp
new file mode 100644
index 00000000000000..abf9b7c8b60df0
--- /dev/null
+++ b/clang/unittests/TWClangFormat/DummyTest.cpp
@@ -0,0 +1,45 @@
+#include "FormatTestBase.h"
+
+
+#define DEBUG_TYPE "braces-remover-test"
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Format/Format.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Inclusions/HeaderIncludes.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace format {
+namespace test {
+namespace {
+
+ class DummyTest : public FormatTestBase {};
+
+ TEST_F(DummyTest, Dummy) {
+
+ FormatStyle Style = getTWStyle();
+
+ verifyFormat("void\r\n"
+ "f ()\r\n"
+ "{\r\n"
+ " int q;\r\n"
+ "\r\n"
+ " q = 9;\r\n"
+ "}",
+ "void\n"
+ "f ()\n"
+ "{\n"
+ " int q;\n"
+ "\n"
+ " q = 9;\n"
+ "}",
+ Style);
+ }
+
+} // namespace
+} // namespace test
+} // namespace format
+} // namespace clang
\ No newline at end of file
diff --git a/clang/unittests/TWClangFormat/FormatTestBase.h b/clang/unittests/TWClangFormat/FormatTestBase.h
new file mode 100644
index 00000000000000..7eb482c6403be4
--- /dev/null
+++ b/clang/unittests/TWClangFormat/FormatTestBase.h
@@ -0,0 +1,179 @@
+//===- unittest/Format/FormatTestBase.h - Formatting test base classs -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the base class for format tests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H
+#define LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H
+
+#include "FormatTestUtils.h"
+
+#include "clang/Format/Format.h"
+#include "llvm/Support/Debug.h"
+#include "gtest/gtest.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+
+namespace clang {
+namespace format {
+namespace test {
+
+#define DEBUG_TYPE "format-test-base"
+
+class FormatTestBase : public ::testing::Test {
+protected:
+ enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete, SC_DoNotCheck };
+
+ virtual FormatStyle getDefaultStyle() const { return getLLVMStyle(); }
+
+ virtual std::string messUp(llvm::StringRef Code) const {
+ return test::messUp(Code);
+ }
+
+ // Tally
+ FormatStyle getTWStyle() {
+ FormatStyle Style = getLLVMStyle();
+ bool AllowUnknownOptions = false;
+ llvm::vfs::FileSystem *FS = llvm::vfs::getRealFileSystem().get();
+
+ StringRef ConfigFile("D:\\work\\llvmwork\\_clang-format");
+ Style.InheritsParentConfig = false;
+ auto Status = FS->status(ConfigFile);
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions);
+ return Style;
+ }
+
+ std::string format(llvm::StringRef Code,
+ const std::optional<FormatStyle> &Style = {},
+ StatusCheck CheckComplete = SC_ExpectComplete,
+ const std::vector<tooling::Range> &Ranges = {}) {
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
+ auto NonEmptyRanges =
+ !Ranges.empty()
+ ? Ranges
+ : std::vector<tooling::Range>{1, tooling::Range(0, Code.size())};
+ auto UsedStyle = Style ? Style.value() : getDefaultStyle();
+ FormattingAttemptStatus Status;
+ tooling::Replacements Replaces =
+ reformat(UsedStyle, Code, NonEmptyRanges, "<stdin>", &Status);
+ if (CheckComplete != SC_DoNotCheck) {
+ bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
+ EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
+ << Code << "\n\n";
+ }
+ ReplacementCount = Replaces.size();
+ auto Result = applyAllReplacements(Code, Replaces);
+ EXPECT_TRUE(static_cast<bool>(Result));
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ return *Result;
+ }
+
+ FormatStyle getStyleWithColumns(FormatStyle Style, unsigned ColumnLimit) {
+ Style.ColumnLimit = ColumnLimit;
+ return Style;
+ }
+
+ FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) {
+ return getStyleWithColumns(getLLVMStyle(), ColumnLimit);
+ }
+
+ FormatStyle getGoogleStyleWithColumns(unsigned ColumnLimit) {
+ return getStyleWithColumns(getGoogleStyle(), ColumnLimit);
+ }
+
+ FormatStyle getTextProtoStyleWithColumns(unsigned ColumnLimit) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::FormatStyle::LK_TextProto);
+ Style.ColumnLimit = ColumnLimit;
+ return Style;
+ }
+
+ bool _verifyFormat(const char *File, int Line, llvm::StringRef Expected,
+ llvm::StringRef Code,
+ const std::optional<FormatStyle> &Style = {},
+ const std::vector<tooling::Range> &Ranges = {}) {
+ testing::ScopedTrace t(File, Line, ::testing::Message() << Code.str());
+ const auto ExpectedCode{Expected.str()};
+ auto FormattedCode{format(Code, Style, SC_ExpectComplete, Ranges)};
+ EXPECT_EQ(ExpectedCode, FormattedCode);
+ if (ExpectedCode != FormattedCode)
+ return false;
+ if (Expected != Code) {
+ FormattedCode = format(Expected, Style, SC_ExpectComplete, Ranges);
+ EXPECT_EQ(ExpectedCode, FormattedCode) << "Expected code is not stable";
+ if (ExpectedCode != FormattedCode)
+ return false;
+ }
+ auto UsedStyle = Style ? Style.value() : getDefaultStyle();
+ if (UsedStyle.Language == FormatStyle::LK_Cpp) {
+ // Objective-C++ is a superset of C++, so everything checked for C++
+ // needs to be checked for Objective-C++ as well.
+ FormatStyle ObjCStyle = UsedStyle;
+ ObjCStyle.Language = FormatStyle::LK_ObjC;
+ // FIXME: Additional messUp is superfluous.
+ FormattedCode = format(Code, ObjCStyle, SC_ExpectComplete, Ranges);
+ EXPECT_EQ(ExpectedCode, FormattedCode);
+ if (ExpectedCode != FormattedCode)
+ return false;
+ }
+ return true;
+ }
+
+ void _verifyFormat(const char *File, int Line, llvm::StringRef Code,
+ const std::optional<FormatStyle> &Style = {}) {
+ if (!_verifyFormat(File, Line, Code, Code, Style))
+ return;
+ if (const auto MessedUpCode{messUp(Code)}; MessedUpCode != Code)
+ _verifyFormat(File, Line, Code, MessedUpCode, Style);
+ }
+
+ void _verifyIncompleteFormat(const char *File, int Line, llvm::StringRef Code,
+ const std::optional<FormatStyle> &Style = {}) {
+ testing::ScopedTrace t(File, Line, ::testing::Message() << Code.str());
+ EXPECT_EQ(Code.str(), format(messUp(Code), Style, SC_ExpectIncomplete));
+ }
+
+ void
+ _verifyIndependentOfContext(const char *File, int Line, llvm::StringRef Text,
+ const std::optional<FormatStyle> &Style = {}) {
+ _verifyFormat(File, Line, Text, Style);
+ _verifyFormat(File, Line, llvm::Twine("void f() { " + Text + " }").str(),
+ Style);
+ }
+
+ void _verifyNoChange(const char *File, int Line, llvm::StringRef Code,
+ const std::optional<FormatStyle> &Style = {}) {
+ _verifyFormat(File, Line, Code, Code, Style);
+ }
+
+ /// \brief Verify that clang-format does not crash on the given input.
+ void verifyNoCrash(llvm::StringRef Code,
+ const std::optional<FormatStyle> &Style = {}) {
+ format(Code, Style, SC_DoNotCheck);
+ }
+
+ int ReplacementCount;
+};
+
+#undef DEBUG_TYPE
+
+#define verifyIndependentOfContext(...) \
+ _verifyIndependentOfContext(__FILE__, __LINE__, __VA_ARGS__)
+#define verifyIncompleteFormat(...) \
+ _verifyIncompleteFormat(__FILE__, __LINE__, __VA_ARGS__)
+#define verifyNoChange(...) _verifyNoChange(__FILE__, __LINE__, __VA_ARGS__)
+#define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__)
+#define verifyGoogleFormat(Code) verifyFormat(Code, getGoogleStyle())
+
+} // namespace test
+} // namespace format
+} // namespace clang
+
+#endif
diff --git a/clang/unittests/TWClangFormat/FormatTestUtils.h b/clang/unittests/TWClangFormat/FormatTestUtils.h
new file mode 100644
index 00000000000000..fa42b61c547d58
--- /dev/null
+++ b/clang/unittests/TWClangFormat/FormatTestUtils.h
@@ -0,0 +1,74 @@
+//===- unittest/Format/FormatTestUtils.h - Formatting unit tests ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines utility functions for Clang-Format related tests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTUTILS_H
+#define LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTUTILS_H
+
+#include "clang/Format/Format.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace format {
+namespace test {
+
+inline FormatStyle getGoogleStyle() {
+ return getGoogleStyle(FormatStyle::LK_Cpp);
+}
+
+// When HandleHash is false, preprocessor directives starting with hash will not
+// be on separate lines. This is needed because Verilog uses hash for other
+// purposes.
+inline std::string messUp(llvm::StringRef Code, bool HandleHash = true) {
+ std::string MessedUp(Code.str());
+ bool InComment = false;
+ bool InPreprocessorDirective = false;
+ bool JustReplacedNewline = false;
+ for (unsigned i = 0, e = MessedUp.size() - 1; i != e; ++i) {
+ if (MessedUp[i] == '/' && MessedUp[i + 1] == '/') {
+ if (JustReplacedNewline)
+ MessedUp[i - 1] = '\n';
+ InComment = true;
+ } else if (HandleHash && MessedUp[i] == '#' &&
+ (JustReplacedNewline || i == 0 || MessedUp[i - 1] == '\n')) {
+ if (i != 0)
+ MessedUp[i - 1] = '\n';
+ InPreprocessorDirective = true;
+ } else if (MessedUp[i] == '\\' && MessedUp[i + 1] == '\n') {
+ MessedUp[i] = ' ';
+ MessedUp[i + 1] = ' ';
+ } else if (MessedUp[i] == '\n') {
+ if (InComment) {
+ InComment = false;
+ } else if (InPreprocessorDirective) {
+ InPreprocessorDirective = false;
+ } else {
+ JustReplacedNewline = true;
+ MessedUp[i] = ' ';
+ }
+ } else if (MessedUp[i] != ' ') {
+ JustReplacedNewline = false;
+ }
+ }
+ std::string WithoutWhitespace;
+ if (MessedUp[0] != ' ')
+ WithoutWhitespace.push_back(MessedUp[0]);
+ for (unsigned i = 1, e = MessedUp.size(); i != e; ++i)
+ if (MessedUp[i] != ' ' || MessedUp[i - 1] != ' ')
+ WithoutWhitespace.push_back(MessedUp[i]);
+ return WithoutWhitespace;
+}
+
+} // end namespace test
+} // end namespace format
+} // end namespace clang
+
+#endif
diff --git a/clang/unittests/TWClangFormat/TWClangTests.vcxproj b/clang/unittests/TWClangFormat/TWClangTests.vcxproj
new file mode 100644
index 00000000000000..15cdf61d7dad82
--- /dev/null
+++ b/clang/unittests/TWClangFormat/TWClangTests.vcxproj
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>17.0</VCProjectVersion>
+ <Keyword>Win32Proj</Keyword>
+ <ProjectGuid>{AA84F965-B2C5-454A-891D-B7676C30B2DA}</ProjectGuid>
+ <RootNamespace>TWClangTests</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v143</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v143</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v143</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v143</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <AdditionalIncludeDirectories>D:\work\llvmwork\llvm-project\build2\tools\clang\unittests\Format;D:\work\llvmwork\llvm-project\clang\unittests\Format;D:\work\llvmwork\llvm-project\clang\include;D:\work\llvmwork\llvm-project\build2\tools\clang\include;D:\work\llvmwork\llvm-project\build2\include;D:\work\llvmwork\llvm-project\llvm\include;D:\work\llvmwork\llvm-project\third-party\unittest\googletest\include;D:\work\llvmwork\llvm-project\third-party\unittest\googlemock\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Text Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="DummyTest.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/clang/unittests/TWClangFormat/TWClangTests.vcxproj.filters b/clang/unittests/TWClangFormat/TWClangTests.vcxproj.filters
new file mode 100644
index 00000000000000..c1e6e711277af7
--- /dev/null
+++ b/clang/unittests/TWClangFormat/TWClangTests.vcxproj.filters
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Text Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="DummyTest.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/clang/unittests/TWClangFormat/TWClangTests.vcxproj.user b/clang/unittests/TWClangFormat/TWClangTests.vcxproj.user
new file mode 100644
index 00000000000000..0f14913f3c7209
--- /dev/null
+++ b/clang/unittests/TWClangFormat/TWClangTests.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/clang/unittests/TWClangFormat/TestLexer.h b/clang/unittests/TWClangFormat/TestLexer.h
new file mode 100644
index 00000000000000..8b5949b32fc9ed
--- /dev/null
+++ b/clang/unittests/TWClangFormat/TestLexer.h
@@ -0,0 +1,122 @@
+//===--- TestLexer.h - Format C++ code --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains a TestLexer to create FormatTokens from strings.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_UNITTESTS_FORMAT_TESTLEXER_H
+#define CLANG_UNITTESTS_FORMAT_TESTLEXER_H
+
+#include "../../lib/Format/FormatTokenLexer.h"
+#include "../../lib/Format/TokenAnalyzer.h"
+#include "../../lib/Format/TokenAnnotator.h"
+#include "../../lib/Format/UnwrappedLineParser.h"
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+
+#include <numeric>
+#include <ostream>
+
+namespace clang {
+namespace format {
+
+typedef llvm::SmallVector<FormatToken *, 8> TokenList;
+
+inline std::ostream &operator<<(std::ostream &Stream, const FormatToken &Tok) {
+ Stream << "(" << Tok.Tok.getName() << ", \"" << Tok.TokenText.str() << "\" , "
+ << getTokenTypeName(Tok.getType()) << ")";
+ return Stream;
+}
+inline std::ostream &operator<<(std::ostream &Stream, const TokenList &Tokens) {
+ Stream << "{";
+ for (size_t I = 0, E = Tokens.size(); I != E; ++I)
+ Stream << (I > 0 ? ", " : "") << *Tokens[I];
+ Stream << "} (" << Tokens.size() << " tokens)";
+ return Stream;
+}
+
+inline TokenList uneof(const TokenList &Tokens) {
+ assert(!Tokens.empty() && Tokens.back()->is(tok::eof));
+ return TokenList(Tokens.begin(), std::prev(Tokens.end()));
+}
+
+inline std::string text(llvm::ArrayRef<FormatToken *> Tokens) {
+ return std::accumulate(Tokens.begin(), Tokens.end(), std::string(),
+ [](const std::string &R, FormatToken *Tok) {
+ return (R + Tok->TokenText).str();
+ });
+}
+
+class TestLexer : public UnwrappedLineConsumer {
+public:
+ TestLexer(llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
+ std::vector<std::unique_ptr<llvm::MemoryBuffer>> &Buffers,
+ FormatStyle Style = getLLVMStyle())
+ : Allocator(Allocator), Buffers(Buffers), Style(Style),
+ SourceMgr("test.cpp", ""), IdentTable(getFormattingLangOpts(Style)) {}
+
+ TokenList lex(llvm::StringRef Code) {
+ FormatTokenLexer Lex = getNewLexer(Code);
+ ArrayRef<FormatToken *> Result = Lex.lex();
+ return TokenList(Result.begin(), Result.end());
+ }
+
+ TokenList annotate(llvm::StringRef Code) {
+ FormatTokenLexer Lex = getNewLexer(Code);
+ auto Tokens = Lex.lex();
+ UnwrappedLineParser Parser(SourceMgr.get(), Style, Lex.getKeywords(), 0,
+ Tokens, *this, Allocator, IdentTable);
+ Parser.parse();
+ TokenAnnotator Annotator(Style, Lex.getKeywords());
+ for (auto &Line : UnwrappedLines) {
+ AnnotatedLine Annotated(Line);
+ Annotator.annotate(Annotated);
+ Annotator.calculateFormattingInformation(Annotated);
+ }
+ UnwrappedLines.clear();
+ return TokenList(Tokens.begin(), Tokens.end());
+ }
+
+ FormatToken *id(llvm::StringRef Code) {
+ auto Result = uneof(lex(Code));
+ assert(Result.size() == 1U && "Code must expand to 1 token.");
+ return Result[0];
+ }
+
+protected:
+ void consumeUnwrappedLine(const UnwrappedLine &TheLine) override {
+ UnwrappedLines.push_back(TheLine);
+ }
+ void finishRun() override {}
+
+ FormatTokenLexer getNewLexer(StringRef Code) {
+ Buffers.push_back(
+ llvm::MemoryBuffer::getMemBufferCopy(Code, "<scratch space>"));
+ clang::FileID FID =
+ SourceMgr.get().createFileID(Buffers.back()->getMemBufferRef());
+ return FormatTokenLexer(SourceMgr.get(), FID, 0, Style, Encoding, Allocator,
+ IdentTable);
+ }
+
+public:
+ llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator;
+ std::vector<std::unique_ptr<llvm::MemoryBuffer>> &Buffers;
+ FormatStyle Style;
+ encoding::Encoding Encoding = encoding::Encoding_UTF8;
+ clang::SourceManagerForFile SourceMgr;
+ IdentifierTable IdentTable;
+ SmallVector<UnwrappedLine, 16> UnwrappedLines;
+};
+
+} // namespace format
+} // namespace clang
+
+#endif // LLVM_CLANG_UNITTESTS_FORMAT_TEST_LEXER_H
diff --git a/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.log b/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.log
new file mode 100644
index 00000000000000..a053c904a81fe3
--- /dev/null
+++ b/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.log
@@ -0,0 +1,357 @@
+ DummyTest.cpp
+C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.38.33130\include\optional(11): warning STL4038: The contents of <optional> are available only with C++17 or later.
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,32): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.38.33130\include\memory(31,1):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,32): error C2065: 'optional': undeclared identifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,8): error C2974: 'llvm::CastIsPossible': invalid template argument for 'From', type expected
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(253,1):
+ see declaration of 'llvm::CastIsPossible'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,8): error C2976: 'llvm::CastIsPossible': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(253,1):
+ see declaration of 'llvm::CastIsPossible'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,45): error C2988: unrecognizable template declaration/definition
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,45): error C2143: syntax error: missing ';' before '>'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,1): error C2976: 'llvm::CastIsPossible': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(253,1):
+ see declaration of 'llvm::CastIsPossible'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,45): error C2059: syntax error: '>'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,48): error C2143: syntax error: missing ';' before '{'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(266,48): error C2447: '{': missing function header (old-style formal list?)
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(280,2): error C2976: 'llvm::CastIsPossible': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(278,8):
+ see declaration of 'llvm::CastIsPossible'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(330,14): error C2955: 'llvm::CastIsPossible': use of class template requires template argument list
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(278,8):
+ see declaration of 'llvm::CastIsPossible'
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(330,14):
+ the template instantiation context (the oldest one first) is
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(336,2):
+ see reference to class template instantiation 'llvm::ValueFromPointerCast<To,From,Derived>' being compiled
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(343,31): error C2955: 'llvm::CastIsPossible': use of class template requires template argument list
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(278,8):
+ see declaration of 'llvm::CastIsPossible'
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(343,31):
+ the template instantiation context (the oldest one first) is
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(359,2):
+ see reference to class template instantiation 'llvm::UniquePtrCast<To,From,Derived>' being compiled
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(366,14): error C2955: 'llvm::CastIsPossible': use of class template requires template argument list
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(278,8):
+ see declaration of 'llvm::CastIsPossible'
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(366,14):
+ the template instantiation context (the oldest one first) is
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(372,2):
+ see reference to class template instantiation 'llvm::OptionalValueCast<To,From,Derived>' being compiled
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(368,16): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.38.33130\include\memory(31,1):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(368,16): error C2065: 'optional': undeclared identifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(367,14): error C2974: 'llvm::DefaultDoCastIfPossible': invalid template argument for 'To', type expected
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(309,1):
+ see declaration of 'llvm::DefaultDoCastIfPossible'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(367,14): error C2976: 'llvm::DefaultDoCastIfPossible': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(309,1):
+ see declaration of 'llvm::DefaultDoCastIfPossible'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(367,14): error C2955: 'llvm::DefaultDoCastIfPossible': use of class template requires template argument list
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(309,1):
+ see declaration of 'llvm::DefaultDoCastIfPossible'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(369,65): error C2143: syntax error: missing ',' before '>'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(369,22): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.38.33130\include\memory(31,1):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(369,30): error C2143: syntax error: missing ';' before '<'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(369,22): error C7525: inline variables require at least '/std:c++17'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(369,1): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(369,48): error C2334: unexpected token(s) preceding '{'; skipping apparent function body
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(371,22): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.38.33130\include\memory(31,1):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(371,30): error C2143: syntax error: missing ';' before '<'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(371,22): error C7525: inline variables require at least '/std:c++17'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(371,1): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(371,22): error C2086: 'int llvm::OptionalValueCast<To,From,Derived>::optional': redefinition
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(371,57): error C2334: unexpected token(s) preceding '{'; skipping apparent function body
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(475,26): error C2955: 'llvm::CastIsPossible': use of class template requires template argument list
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(278,8):
+ see declaration of 'llvm::CastIsPossible'
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(475,26):
+ the template instantiation context (the oldest one first) is
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(496,2):
+ see reference to class template instantiation 'llvm::CastInfo<To,From,Enable>' being compiled
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,26): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.38.33130\include\memory(31,1):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,26): error C2065: 'optional': undeclared identifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,8): error C2974: 'llvm::CastInfo': invalid template argument for 'From', type expected
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(475,1):
+ see declaration of 'llvm::CastInfo'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,8): error C2976: 'llvm::CastInfo': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(475,1):
+ see declaration of 'llvm::CastInfo'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,39): error C2988: unrecognizable template declaration/definition
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,39): error C2143: syntax error: missing ';' before '>'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,1): error C2976: 'llvm::CastInfo': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(475,1):
+ see declaration of 'llvm::CastInfo'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,39): error C2059: syntax error: '>'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,44): error C2059: syntax error: 'public'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,69): error C2065: 'To': undeclared identifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,73): error C2065: 'From': undeclared identifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,51): error C2923: 'llvm::OptionalValueCast': 'To' is not a valid template type argument for parameter 'To'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,69):
+ see declaration of 'To'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,51): error C2923: 'llvm::OptionalValueCast': 'From' is not a valid template type argument for parameter 'From'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,73):
+ see declaration of 'From'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,51): error C2976: 'llvm::OptionalValueCast': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(366,1):
+ see declaration of 'llvm::OptionalValueCast'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,79): error C2143: syntax error: missing ';' before '{'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(538,79): error C2447: '{': missing function header (old-style formal list?)
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,50): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.38.33130\include\memory(31,1):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,50): error C2065: 'optional': undeclared identifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,30): error C2974: 'llvm::ValueIsPresent': invalid template argument for 'T', type expected
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(601,47):
+ see declaration of 'llvm::ValueIsPresent'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,30): error C2976: 'llvm::ValueIsPresent': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(601,47):
+ see declaration of 'llvm::ValueIsPresent'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,60): error C2988: unrecognizable template declaration/definition
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,60): error C2143: syntax error: missing ';' before '>'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,23): error C2976: 'llvm::ValueIsPresent': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(601,47):
+ see declaration of 'llvm::ValueIsPresent'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,60): error C2059: syntax error: '>'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,63): error C2143: syntax error: missing ';' before '{'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(608,63): error C2447: '{': missing function header (old-style formal list?)
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(623,2): error C2976: 'llvm::ValueIsPresent': too few template arguments
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\Support\Casting.h(619,8):
+ see declaration of 'llvm::ValueIsPresent'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\SmallVector.h(362,10): error C2039: 'uninitialized_move': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.38.33130\include\iterator(20,1):
+ see declaration of 'std'
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\SmallVector.h(361,15):
+ This diagnostic occurred in the compiler generated function 'void llvm::SmallVectorTemplateBase<T,__formal>::uninitialized_move(It1,It1,It2)'
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\SmallVector.h(362,10):
+ the template instantiation context (the oldest one first) is
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\SmallVector.h(442,2):
+ see reference to class template instantiation 'llvm::SmallVectorTemplateBase<T,__formal>' being compiled
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(46,35): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\SmallVector.h(1337,11):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(46,1): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(46,43): error C2988: unrecognizable template declaration/definition
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(46,43): error C2143: syntax error: missing ',' before '<'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,13): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\SmallVector.h(1337,11):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,13): error C3613: missing return type after '->' ('int' assumed)
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,13): error C3646: 'optional': unknown override specifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,21): error C2988: unrecognizable template declaration/definition
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,21): error C2059: syntax error: '<'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,34): error C2065: 'O': undeclared identifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,34): error C3861: 'O': identifier not found
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,22): error C3553: decltype expects an expression not a type
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,39): error C2143: syntax error: missing ';' before '{'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(47,39): error C2447: '{': missing function header (old-style formal list?)
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(56,29): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\SmallVector.h(1337,11):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(56,29): error C2065: 'optional': undeclared identifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(56,41): error C2988: unrecognizable template declaration/definition
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(56,41): error C2059: syntax error: '&&'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(57,13): error C2039: 'optional': is not a member of 'std'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\SmallVector.h(1337,11):
+ see declaration of 'std'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(57,44): error C2065: 'O': undeclared identifier
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(57,44): error C3861: 'O': identifier not found
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(57,22): error C3553: decltype expects an expression not a type
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(57,50): error C2143: syntax error: missing ';' before '{'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\STLForwardCompat.h(57,50): error C2447: '{': missing function header (old-style formal list?)
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\iterator_range.h(68,26): error C2988: unrecognizable template declaration/definition
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\iterator_range.h(68,26): error C2143: syntax error: missing ')' before '&&'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\iterator_range.h(68,26): error C2143: syntax error: missing ';' before '&&'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\iterator_range.h(68,16): error C2365: 'Container': redefinition; previous definition was 'template parameter'
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+ D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\iterator_range.h(67,20):
+ see declaration of 'Container'
+
+D:\work\llvmwork\llvm-project\llvm\include\llvm\ADT\iterator_range.h(68,16): error C1003: error count exceeds 100; stopping compilation
+ (compiling source file '../../../../../clang/unittests/TWClangTests/DummyTest.cpp')
+
diff --git a/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/CL.command.1.tlog b/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/CL.command.1.tlog
new file mode 100644
index 00000000000000..46b134b197f35e
--- /dev/null
+++ b/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/CL.command.1.tlog
@@ -0,0 +1 @@
+��
\ No newline at end of file
diff --git a/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/TWClangTests.lastbuildstate b/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/TWClangTests.lastbuildstate
new file mode 100644
index 00000000000000..2244357198108e
--- /dev/null
+++ b/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/TWClangTests.lastbuildstate
@@ -0,0 +1,2 @@
+PlatformToolSet=v143:VCToolArchitecture=Native64Bit:VCToolsVersion=14.38.33130:TargetPlatformVersion=10.0.22621.0:
+Debug|x64|D:\work\llvmwork\llvm-project\build2\|
diff --git a/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/unsuccessfulbuild b/clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/unsuccessfulbuild
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/clang/unittests/TWClangFormat/x64/Debug/vc143.idb b/clang/unittests/TWClangFormat/x64/Debug/vc143.idb
new file mode 100644
index 0000000000000000000000000000000000000000..c8eb872576c54937d2c989db59b1bd3b73c64a3e
GIT binary patch
literal 19456
zcmeHOO^6&t6s~AuG at 8W3zcn#Bi4l~T$?R_2gy3zLs4+Qc0v>D_da8SNYqx)fuIiZ`
z6GiYC1P_7`jNU{9QG^@<{#-ox1BnszBqAzag9kxWvVPS)f1B>j?#xuJNUET_YkGQK
zz4yIW at 4c#ibBxg_<Y845CihM5*;6=n{BYqwu~gc)VcXPkg0_~B8*sT5M*)Xy>(h%l
z8w3mj|8oR>y0T!JLBJqzogy%Doyu**HV7C578b5tzH)gDa+u8z;p7~$8eueNd0yS`
zboSPwaMq>5qMjX0TXDdIaJk@?Xe4*i4^Hg+P1!BdT5T9Y^Ar0m$F0QER+nU0nI%(w
z at pj_5Ny+VrgwZL<o9qt2TQ!V)TUhBu%2%<uTb$`r!VHyIFpsa03=60iJ8ldAMWhCz
z00|hiBs^hFurL^mkCX}xecug4mk>Q<!Cs~#+b>j^=W@&MEHLYg$F^7CB6e74jg`j6
z<fB!Wb1-3hR-IZR3_bjWqdU64IDW7=K0Z2Lvf2o65wT#JXdR<jw>@5_VI;Mzb)-6t
z;y^H8`#{|Gbjw1+fW}ee2DG^fqt$K4txB`is-O8ew at GJQI;VZ0)v)VwSx&1mx8c9p
z3vN`lgCG>PaAE6#uvy?n#TmG6t&p;iR~wGrF_H<Kqq4%o^9Ls$u^KFJ!UiwQF@&(u
zu5TGF6-&jjv5B$KV#$hWgm at PTr!uXC61)kh<&aY99y<=D9Jq~g5=56B^7Z2AnsaaL
ztI9pSuj at x&wf?CddFSx^Z=F82^Hh6lL*@ta=xskdGrq>e|COdni-NYyB24@@@xL=&
zmz|`;rcKv~|LZWR3pgI{o!sbS+n>nqR+yQY_&-EiJ8$B@!bO6K|85`g|0c}wAxyX9
z!{m^<{g_P1Rw3_?xr^kOGwtGVfrW4;8SXnzO~~Xh+czP(=mo~*hH{DtLAlVVvb=;^
zX%<YE at TPskk<w8Ktnd0^)KpB7)|%zKweZU19Wu2r^MCN&EEuYp|LQjh&HPVyURO5%
zd-glrC<?+H=cLp-cO8a$_lmeB_lI?hKpS+%j)srh37H&b`&L{hZX>|5JPi&(Q8a6L
z`_qF{bQqG1ysfaoNvf5ZL%C{2##;`Gw;W1Ujo9I_ic*qGyo%^sFTBYuj-6!{%t>0(
z1oOaC>X+t4G%8<ag+XRws~soJ0rd`&WEO$YJBZ9)f;=TF#Y>6;L(hoPw^iaT?u-hH
zY&%<3^wdve-}bzas+5(xc0`q+2Whc{&*4p}(Rj?q+nv=JC1aUNC81R>w6hbrZ|hIU
z=mvzQxa&m(J_ku&Nw+NRVOXI3-8pv7^g`y&Q#Yyf&^wHb(`6Can0k5#k}&~ZBr{0g
zvtmh4sdNr^mpmOs=(b*0iL-8pI^jk>3s5Sco9%g9gs2zNK8$?(%0x3`KuXo#D!5=k
zuT at T@ySidk#A333#P*UB5|8n0Y*Gp$rP8Zp6xH`kPsr%Dt2!38VRmCcDIhJYsxVP*
z)ex+(+_GImmsWAMY5-B^2~e(G_9=@&I~91z2OigIp)8QGxk&e02Br}DHB<?r@@N?*
zDlzk%vBhkpuM?7D)xDip3xjgf6TEbr31H)Hl$|(z8+A%YH at mB`V3p{zpqhOdrgZLf
z195vi-Pomdv9`C2b!VrT?Ffs@^d$8uy7{!d=`dnq#?N?Kr3$FV0hJZU07Pq<p@?f<
zHfSgnMTT``E73BVO}%Zd??wGJcF6+AjvT1BU%!<YNV44>CF|)ye($&ecYV7iXWqap
zcwMEs*hI7CvU?C_xbRRV*8m#WhN~sJhl7x5>!ln4UzxBDLd16DqVEz)BigO9IqhBC
zMF`tK$WyxsIrShRjoaE!q}O-xU+MjKEWRf{o!!~J_b6&9&)i4IxvOg`@yK>rbG1Yp
z!GEw{DWqR|;6t|a4-j$z{QP_mA(J<!_nz31Ugi1Xy=ni~t%SUIKOrB3=f88tEpF`o
zMt*%3$H^NB*?J2hQ;_M|+q>Ui-TS`h|KNWV2>AuF<+aa1OSU8FC39ZCrF-jB`G51A
z_Ge4B2KapwGRbxczuN@;Yy$@Cp^pW~coKcO9sEOv=Xa*h$@4nYyBq=zzjbfr_I}?6
zJ>%JzpvyCN5%TSwggkjSWJCWP#`+HW--UaBjS%7k;}Kx+C3t!b_iqAL at 3nMsHSr6e
z$y at k;h~FN748bNsb`%KlKyL%|c@(vG+i`EHHqpZO8}RltX!N!T at b?uk_yD}-wY9LD
zFMx||FT>Wn7Ut)H>ue9^AAyG-f!$-k@@>eo1vVCfw|4s+7|M1UILTIrZg-<kTek2?
h5C602Bj#)nFbEg~3<3rLgMdN6AYc$M2>jOw{0jnbECB!j
literal 0
HcmV?d00001
diff --git a/clang/unittests/TWClangFormat/x64/Debug/vc143.pdb b/clang/unittests/TWClangFormat/x64/Debug/vc143.pdb
new file mode 100644
index 0000000000000000000000000000000000000000..51f554f250ccd9da8fb657cd4ba0219b15b69420
GIT binary patch
literal 156672
zcmeFa2bdMb5;j~jvjhpU2x3MQ3?L$)q9W=Fh at zlKG@!?2Il#)YyKEpBP_G#==bUp+
z*PL_C33JW?^%|~$?|pl^=Jd>&v#j9f|9tm9^E~JDba!=ib#--hb$89o$jXYkn);e4
z4c&%pG-QJfx{Vw&tlMUN`u1(#X4Ro%1Xrnuk6=0cy5YyGRTvciiySC&pvZwD2Z|gh
za-hh8A_s~bC~~04fg%Tr94K<&{}B$n_vhl`RpdaC14RxLIZ)(4kpo2z6gg1jK#>DQ
z4iq_1<Uo-F|Kl83`G359#pV?`P~<?714RxLIZ)(4kpo2z6gg1jK#>DQ4iq_1<iO&^
ze}4Ptw;p^I_zVAXjth$y2PQ&3 at x~2XinjvOmY3G0ArvBbR-l)(SW)C)J~H53naY|;
zjZ>u0HrtL1Z_CQ$`$cWUFZEHT9V%`kUg=Df at N9aCO&^wyFH=$1kg2MvD6h(9YHKR1
z8?trvA^Nl&)W*76TAZtb_7<qCJAMJuTHx0TzuJ~zdm0SoEzmN_l`HXN>m}1NxxAq~
zpAM#48rlLU+uKyTW;9kcR8E at Pkj*5}#WNxvwzoKYNw7lu6$5F9xCppYSv{o&{AAkl
zNNX)KCTSY$_wi^)2Lo#wjPA>%aWB6;%5mE!(^ue6)StLt)zT7xry`kARpk}gX*E at o
zvvsnFG6H$?J2`c?mUJ1Re04WCfClhg(03)cT><wU at oR%$yx&Ts3)2BdnQp|-$SBe%
zT`MEJsz5)^qEMCB*JlyTD$mq6l;ftdK2u%Okg3Z~$<}47E3$)9dDN{}w~CtT`i89y
zv$pAx$utXD*{<7RM5Hmj443 at y{URTH4CxhrHPZ&RgDq)h75^~3lz~-2XE>()QuYn+
z=Pwh_XID%sugf%qJYITU56(;gR~Ln}EG<9(URubnH7&ooLS`xI)JrpQ!!TVpwUo6{
zhB}ilsxzrS+nI6bl~RW>eQn_6^I9&>!gyQBdcdo6tb_X=_Ln}^T1rpkt3Flubl4WM
z0bo}EJpt%RhY4guz~~q!zI3<}*$8<@{GBrOS4Zxs?Luk77!B$8o8)O3=%6h117A4a
zTpqFy$;YIg+yrUb*D4bl=Ff*MWdPt6FYy)Xo6V7T(K7W-s!HtE>#y^sDebx_q;YBc
z?Vq8MeL4{QWS{CdBj2 at 8^XI=7vK8{F8)~f%AdYPkIM~m$eai65 at 9P$_Ez+ZM&?(yQ
zoOg#X55J^54Mp0rjY+EcWmfV-spFSzO#XdzkcY#-7xte!*2p{dK|23i%5d at +WorRL
zovwYq6VloD>3z^bMj+4C`C3omx?0K3D5JC~{=#*%lu>|JJ)TZSAfo}JGDDo{a3wM}
z0jKpQWota(mdD)TgCE2d&-Z0Fq-h(pts3UbcT3sBsh9W)(Kiu!Zd>!~4rFh at u&)B!
zSF|@9IFa)*d7jDBd3qAk*r$q at HZtdH(rav0Q#O#v7O#Pa{J8K_ke7s?iZq2`zKfG_
zjCiR;sC=Ytp*R at wN$=@MV_Rr{P-Yb$<Ak4K%C|Q8#8++NVZSh+HVE6md*Z82<TKsP
zuXFM_7LxQdB=XrNmM1Ln&r0Mo-OZnaxXK}Mv;KT}D3Se;uJS_|))W0~{}3<JL|V!L
zfT51<gqZg0Jfx9ly7o8-ah4(P2z9V2<ChvZr~lQ~Q~0osKn?|b|MYnjYm<fnn^bPx
zKU|zeQK-IfU46KvMf;jKkFfNF_<cDN at wQL)^EM}WxHmrpT<3F*)ztcbw6y2~5E(LX
z;;6cssdeQux(%zW%GP&Vf6nFudQO~BSv|RCc73;<DjVu2_Uk)wcy&cp<K!%E`}FP8
zzyE;#{rdEs*ogJk#EP1_EW$q1WYO}{vP-F at qY?vskH5K&%<TGx$(1#z>U&dHXVk_0
zht<&z*1fuoe}aW0<K1lh7aQ+y<BPF*!2B(3{0$h`e;YrPMA((AV|&!WeTW@`zq5|H
z^%E&F-~{Vf0Q{WKCs;llYvTiK{1n6~8#B=-e`h<ZDknvKaVzk1k75<e>pN|HO~mU8
z$ic*s(aS5wSJpR{S9KfH(1;G6*uQW8{uIk8+4}m*n(FeZiQ|V%99vUURX=g$7~J;T
zq|e5i_t|*kejE3lSZO7*VQy_U(@<9qf#tfJeEAYI(AJuOmtQdcvyJa#<6g%wztYBA
z+jt$~`~4F%V~?S+x}kDLHj|xGk*#e&TXh`u0xjGJ>1+G2pN+3#<Kt|6s*O*#@j4qn
z#Kw<6y!xMLOVol;51fnoIUe6d{rlSbhYp-LyQXgX#Hy-UGoqUfYwK$E%~n8>RFzjx
zo!D4i+0c-!ht?T8VF**knn-P3c5-$~Wp#FPH@@YBoefo0Q8S|!N~^A$*+7Jx^fdi^
zFY4}!y3et^c*D}Nvz5*N*!b~?|0BGa)7Vg1RoO7t>a9OeKiB_5FdiwFCD at 5&{C+6y
ze}<kJ*%>u;b9J1og8J7%{oSCWNKbDYKN<8ezM+kuXycpP_*phS%*HRV at d-A54dVYu
zd*;q6ud2t$vE#l5_4h`5_O$)|FH6tsmcEN@{46^UTw>#=+4#*iehK3L2>o;F8|o^n
zrz-v5qJGX*>$VB`|D%l$xAB8vv at pL_=P>_v8&~+dZCv4p0*>&lE&M??uJDK1xWc!?
z2>{{SS@`X3T;WI9xWd0|<Lxc{`-pSCnFRU%hxI5G19#1%d8t3FoHEcd-0FhiHr~_5
zvo?N`jnA|3D{cIA8-EaS)niGU>2ICK?9k-6y8(3%1MTCj+&*FBlWqJJ8{cI4P!8U*
z at oNzOM`&$mtgXt1`u=m&&2{2C;L|@cW~MY&S8&2CuQEF7Pt-pW^&bkED_%to6gg1j
z!2cgOa7v$k-mRx^G=*nGjhjBy^26)z9)9Vo1MmB=ZEZ%|4>Jh67xC+ at T{kvK+~0uN
z7hcexz0&t9is%1jWoBQkEqKH|qG9QLGDpGjV}9rOJ)QxK;a*RBi?ewCPcbZ>|NnpK
zufV<IRjoXl^9$^KQr_nmkoRV}NeudX&)h>=miFB5 at 1=!2DxUxAzIyTee<{wmBR>Sn
zQa?NP^vr|%GCWh`K4$#PtVA|Jnx1*+*@%YuXC%e*|7Pjczu8BDeL4{RL>;PUz{T_b
zg5G&>s2f~7|CgN4SMmHm?Yy^m{?BbLo^w;*a}CF^c>W*yUy?5k;70WOA3p!b5ruTa
zZxDX&g)L%X9xvDLU*mt<IdJj(Kkg4vJpVWQ at x}B1X80@=&;Mu5D4zcp&;OUz_osON
zAM+O|p8prm|BL7U#`G=z6**AkK#>Fgvm7vwCgeS at Pv>xR?#!F$ocU<(L*u!HckHv>
zjfN}r4VlT=S at b>RbLMLytwfMkSzY6%wPf0in#oz5SrZN}tau(BY1LJg)zc+PYs0k0
z%E?-maP62jHJ8SEOPN;3ibH&Gag@$XtFPQo>)^8)D>JQ}KGI<wOzXz98S%9BnFfb2
z!mW$5%C^`HI|l95t1t4CJn5eb$LGciKbxV?W6-BC`8>vPNb8e+PC9ZDv1Y?g$!N^@
z6nLd4pqxH~aw6_|Rxr@^(b}c~nF)NNO?evjQD!jSFd*7zEhRICH4uh01Ze-sz at -<S
z&(~T*hXjpT8d#6gaH^$2pB>_U+Dzo at UL)gtcIb43`m9VD1d;oY>~CT^)5+U5k$1L}
zR|aU7<6a%ho$KUno5(vKc at h7SR~F0n<w7T)W#i?2x!B~lE at e9Fa`7>Z&wP=VFyEKU
zEPNTk at vKr3KWTR1uZ-c>`od?ch*SBX_^$!H@{jUQTntIubzz=~hy4=14}tPeIEI9~
z5pV^3cB&><&dOMc3-8g_Yg at Sr>zUbD(-4j;#!I9wI|Jj9_<S_ at 7U0$k@{@{B`-A2A
zBW*XEa=!c<VS({b6+;$L$LHO{cVL9=%hAVpYfB$-lD<0}`ta_Hf;g2%;^2=o-fn5U
z3nAlWNLTsWSxVr+d@!nTFKp}$99Z2rBU at Klk*TVjfd@?nO~NxN=D=|LHa+55WtpAJ
zPy!tPe$lG3TxnmRy4RtX{?WXeUl%n%fx3p;sxbChS1s_~pHkQ8X1A-paw;FSXrjs?
zwo2B=svb<KZ+x at sYph;!joZce*$s6*oKk1=+sMZC8;}WK`H|9pV`BB~hx#5}=K417
zU%0+;vHJE$eUC3web&#VfXLuY8liYvnW27vGNr!e%V+(xnz};F92RRE=ZL3M>e{i{
z@`C4m3bbnnTNCAy`uW+EdYa#+s+#Jl1uEJx&OhqD=TquxzC31Na>4E>P+cZbANAOa
zDfKPIm}{!zwzsV`dSxxt`SRaWXW<SU9_K4<#aI8HI-BUsoouC{{#+Y%zMfL&9?h1|
zNS`gCQ{(m0zFL at 4Z}a7KN>xpHp^-5%*2Xf__0}@gHMyp7QdPEqxa#C*<c9XnJ1KQF
ze{8Vpx;0thF1B?X_pI-|l=}F*cQ at pzo%;b`xE>mqYO|a9ep-3`v_Uzpj at zaOQ_6C@
zB+ie3M{#~^aWcIusw=eJK1CksV?VRZC-|}CXC at RG4BMv^mPZ*<%j>4X)TnOA at QEha
z5KL#ex@<k(E*7SCgq8m}%GT6o>&hEy>elZmi`bSxI{RN(oG5}Cn%fq?lr;863AIbV
zLY(#y>n5hJ5vNZR;lg!F+WX>i^*NoU%!_1$Jo*lJly{4W6aB$-_MvO{{(wB?9m{-=
zA0d7;VUBk!*IeHH2W8WE_mjmL*3jIx_@$)L<=rocyS)1qaq^CE<X!sv=yLTXrCu4R
zvQ9p6t(#`6CfB;Gx48a~?}-%G|Jaeh3WajSIZwx7asAJcUtIqe*Z-6Qy^LOtFY=4)
ze={dzIxDXKRZL8nCM(=;D6ao$!xh*6Y4WjzrDAdYAC5388(d4V&rw|eJNwaP;9+t7
zUtIsk_cDs>f9{?9zqJ1U9r{q$ZGUiI0sAMqPr|%EjlNvAeUin%;qH at g--3KHP5@NK
zxZFLaCGA_JKRch>_pq~LRaI>RUK(z87<KETM~|^~qYvj6T(|l#Cbazl?(P233La<*
z at Ta^WTnP;iK({bqZqJBt&D}F<iLx#)*cS4lmBks>urzJ)OZNev-TkBGfYaSSYJ)i1
z9JbA#RR^pPZE9y=gB7;{4(`?Aw at 9B2<vEBx6T>h(zYlST=k6_~gDqcT%kPHr%S*7L
z##<-iryxGC at P2siZE*Nz#P}%Y_MKna8FjM1T5?xR#+mO)bYU9W!@gy{_U+2JcX_i4
z;_O?tpKvSUCq87KAuc`h<@;XQ#(Y>`R=2RqQ^MxM;k~~WE<X>5QHIyr($c&aeKo+6
zrZsH1rVYCx<Q^PpWjly#ZQMt+GYxTGdG#>S)<YcRg^u$wq!Y(FwyeUXkFgA#TPEjT
zHt2qzB0mE=L*aP{-*4;Exw56 at ChS))*I8sG)ZJml5?Kpj)YT}<{ps#V)A6#EN$Vs%
zEUoi$z<})}>mnU;CbOqu_Y&i~J-#xro=M9L<##!N&tut4_~nqytSJrUID&xNPfcB>
zqN=98vCjCv0GGGEtpi_K$W{!^Rt*IVaZ+a6%DR3}n@@S8j}gxHbJR2;vmV+W>KMOt
z1C$MA)i3Ss+>>Ta?_=-RwSEokFSK9+n at HcCzKFrMVrb2<x-9qk*>651xi8A;#qWCL
zcaMFqNPb4H-+;jFH<e?`5a|eM^h!yuj<ZcHy*hq2MVxJ*9->@xUu*#4D$B%?FR!_=
zm7kZB^GKF~gZHe<(qwd8yk1YXvh{MD5{~*w^&QS%p|3(;8_Fy6UySB$QFd@)eKo1v
z85ZR1_*hC at Zw(=x=A6PW<^2Lff2fzYLtNX;yrK9}FAZaei+YXe%I_U;-`goa9PzaB
zJKFO3c|dApishh#Fqdr)ScW?>MD~a at oFvAUBkxHQ=^*}Ha39f*G^IT)Pw860);)@K
zqV8R_PV|L~OLfO-7!T4JGbiA1nzN__#==P4$JlQ4MJsP-q|b|I0N$6;NRR85z`!;~
zKa4T;QkTT_17&16=!da3-_Z|o3Yw4+S1$1?J~OY82b9?+=1k%*ufk`4BKb41xa{pl
zJXZF2 at 5<gDh^u at sZ+HACdwVj(McHGz%HCeMcV%yH#M8=WZ27c2)hYRTsL;xnnHwP!
z6M=`au at 6E7QqDNSNeJ`GBVEf=K1sLAXBPKS`+!N?M;ysKrCsH73hPAWQ?*XWr;AJF
z^SC_uERhP7$#oLvw^rU{q#4-^d(Oz^G^8cvl5owD%SyoUO3EeWrVZqBUz?wh%O>T<
zmB$W{$9!JrY#ik^Wwi;v1H*>8y7IZ1>g?=HRknI+!?c{(CNiu9n{iMB`c-~;@5=8?
z#FaMY)#69_tz(Fb^2>CU-v->f^4o}bTKQSFe10B~CUj>#U at 0H786ta58cq`9=uXn4
zvbjI*Bicc!($2b*c}kbc<^ik|bswm8LN;AoDw~&C*`(a6?wpJJ)J}oTLpj|K`JtR9
zI>+c<U*;h{DYGoo9GN``aJ-T-OZlNLJ=o?aWj0BPs?_pChRTmC$2j!P$rJcYxiz*K
z?rEzWX6s}>H8Jl;HeUv7O(Vdul(_Ca0ysn2^-6iKa(EQ(T{%1&ag{Z~9f=?1cs at g1
zX?ZOQ=AnQqqlg{@Sjy%C8y<@=4=3`q9C<@JR7Ow0eMA>p;ntnZQ<{y80_BOe&XW)l
zFWXL at u>QWtC*D)=Ggn0Sa;ARfnTyKb=D9Z86r>Rk;c~FPoNmkMI;}g3=eHL==N8W7
zVeAlx;XT@@W9J);9oiblAura|#?}brc%<jnB}OWYPCpsxiSZ$)I%(bL3T$w+mD7-(
z8PZsX at 69#j7F&XG*jCOkc{R0joeZvXXtSae*E#)k?ZYUpEKX<YxD#qyc*#)cZa
zFCA~k$LrFgyt7SSzCF`krugR|PcJ at u;jVX at Bm1PK9r&oS#QU^9aAk=y>h^)klDn2*
z-$rs|@P~FZWr1*g4bh%l0yuphfwVARVOS4G#ASeS<%w`^T~|2yZuzhdU#@cUIfnVm
z(csH9iG1p6H~%^(pLxmhH&}cjy<wXMr26k<>NA<K)9Pww59b#kp%=%+Qn13~TzE6^
zsSdgY_u4=0qx+DT<PPZ!_j)|J4f*8x?G|pwf;0>%Z@{r7*4Sg=g|;o#azspimRWa_
zt~-HO>AK6-QH^oO^=>1Hk at 5z-@O)AuUi2TzdLaJ>T#3}qm{L8idNw{jqUm>-^0mWi
z>SmYMO&)?5{_EaAAa^6Lv()BOf^kT`;vFddJ%G_`b%}8?YD&auv_NH=bE~nR(ULta
z4)Uxs?iV0U;oSMzo$J}hE)KOriGy~xJAPaoY7-ES_6^~N6<)Vi<Le07<kB^nsPiXr
zK1!T+&&`ujW)6Ma*2BJIzV_XdxbKaa>fNUh*LD-`G5k2MJ<SkTejXArPI>A4 at eE+e
zn`aR!J*<OepGR7R7ik6Y5~0OQ9Hdj{AmS#Dm+&)}g(LnWEPj*c%t3i{qweHf;?kva
z$xo1J?teW2yj+hyhcL-|tGDF^<i+QYPVyqsc+JZz6z-k9jQqN61N8vRY<4u~kU(C^
z)kCYr?31x=m at BrMQ(<7dR}n8XPq5zR*mbV~j#tvIqdamC?RA?^`LTOwc`cz$mrPW7
zq)sB;V7KW{_T~AAQ|47R^xpKbO}{vT3H2Ls5SQxJcM)&mSpu5Lv&!o#%P~8bS5)8|
zGsf`CPgXiPF5U-D9Ty+4e!B)|`T|2&NXtivlXj-NGRgQS_;I{^%n%phh>P;CW9&1;
zRUX|kpW8C|c|a7&c)0)bDPTGOe8CXeUs{}HfFsTi at iSLcF5E|t>SLzO)3%UC*8MHY
z=HPN|Ny}53b$#<4%95@{2u(XMKfAbeTwRB8mE0Tp3T5(ph_c>FzDAzz8FQ`k4dQ04
zljvoR(eIHLABTZ~Z_ar50cCk5#{*@JYx5s%eiwvxJfx7UtDHD-Dr at c<2hVsI{Y)Nl
z9OU&q(o~kx@|6E7XT*^{*Bg5<Gp at R^9+OFJIlcy##TU852{M^#DTO^syuXn)jD-+y
z@}0a(hgaJ|+`r>zE-Q~s(Lb~j582`q&zZ*R>D4u}t3&#esV at Cq>0;p5am@!9b<8r|
z<nh5CXRhc1*`yBkk*;#IA?yv(<w=PT$&D_1CYni7uw=S?Ll^tY=rxQJ62Uo%JnxPe
z$0P4)<LZ46 at QC!g=YAaXwEGzH$17(G;^YnVx-y3<%(<WLt3!Xp;#tJ?J*Ik=$dGm&
z>B{Nh7Sh4u)-%K>EiR4wiTJvR<GpmL{_I$<WVWp at uf`6kc{VZe)%esb9aGfbok5HC
z^NP6Fe&#xWd0p@$1lJk7wnjhGUS&Q;{IJTpdV3}nrg5%?m1^eWl~6W=k5$d6%{0_x
zvPk~kv;(~JS2lQwgDN!~52?h4LXn!4YlmNIXt#Y|0oo`dlmoUw?@2T7)6W1y8iv$V
zH<aUhT6LL8<@MRVVeN at Tx8APA582YO$@rSuHp8P(HklsEV>lnKg?N4$Pu8|&o1$@8
z`SfhKBhIH=LK5R?mO`V8ywV=PseQaof{t|y(6OGSL)VRjONaHPr-j|u>VR&DXLhNp
zoo2+ciszHkooQocm)B<SU9&lJGv(EjGnLS#Y(c%*9|&Z9!feZ({t!rQ#9mAvoy9X;
zP{J$?c=Ctqm<^Dpm+F;7cQx6EA)nLrbDXD5^SP=18gAR^ic~z!?JvKy58C9)6yqD2
zcIL(*$1Y_``?Vj-7 at 7A>c}?G#=~h1b<DR%S!OvWge0pX-fn|o-KI{va%(jzjYVjOA
z`)^amx6d|IV0^G&mPgtEreRrHhhCjMEnAKGWfq<SpHc~foc!Q8-%RU5h1x&ywugL;
zr{(z36kl`w97=`R4 at e}sV|5GALS8gASLTXy{P(lpAx);{=%bF=l6XVjoAcR0i0jy9
zodfZseY+JyT={uOw0)uL!L0!c{>e57+1IQ?`*d5}FG-KZ_^HiEB)YsAVsY+>{-- at y
zhIl5|?2y6eck2GZ$V2YPxfK+KFl{K(p!-M8ox&NRl2(!(qrShLfoGYVu1}(Fs_*jn
z1x_e0$$!(YhW~ykX$$+pFC|TSZ~6#*Pk8dLx6 at xE5Z5{gw-bKsuaOLK<>w(W(O)|Q
zmi at I0LX`>D!Lqv|Ey9bmf_Pb3ZcG|kV%fa<fnzMvd3Eu^{u+h2(_dD2!}aoL<f%;-
z`kDkXhVTg;J&tKj=xFx+4uCOzA4&vtgO|hwH2 at Vp9TxMfjiLKJX%cS)O+Ay3D~E|~
zSrV=gn)-=joNJHqhF;Q4`AnPRb#UY)GGtzEj1MTh&y*Q~mR6dViHx`RxpI_)-B3Su
z4#zO>bqw!;dshbcL|prsaJ%D28Jx%v7s?xXpv{^Fx3`7M&qDz#Q^pSh(Y*jmS<TpR
zAB1`3kgw&Uc7S at d2P#k|NehdBXqk*WUP?1zUHoCLCsQn3T3)U_Emy#2XC(_*hEoyZ
z9Y!(@A$4UkO=;D!Hyv;hKS96p)6|JIf}5x7Z2DmEETkM|wSzeaPC|U1CP2mrQ<;M?
z{#KMd>d$?h^vTx8ia4r}?v6#CagdL;Ci7G?;Jg_upYXw;9JYf at S0hg^zLSb;fTrZo
z<*$(|@Im=Yei_|wWt8_Sqjk7<Wwah~#YMQ8_)$h17~;y$Lt;WtHUgHiHw&TGt$j5I
zX%SvfQ4lXHOXx}J{k-~tV}GRcVqI*H+Cqe9T?g8H#g~R7Mh9fZrBP*OKdXml179XF
z&#E0e7kO^qQy%t1+Pu61q24}#xEvd79^-$(220b|OpE5~>g=3wst$GQL8d+&o=v4G
zm(!)xyKbJ%G5R=1W3C9{opcKx*1`7byo2vMYc-rI48BBuSeCgMR~#1yvwUJ)&_*o9
zxHtrPdg+=n*%ijlNF-W~ZT4+AzqNzhMDk+q2Ri9H+Ix3 at 0N<aE`2`O^oH)qqa13Ej
z0{bNkfKPSk(a4*RANK|bN8Nc0LY5;e>DU=<OM8x;W8SP!%skAK%1q^q+A3#}63=kk
zcpT~o=Olbr2lu2;Y2q611pIUy5cYWd#P{VyhPaxdX+*YsR at ScZ8mlMOG-B0nc%G7>
zG`V%3T%hh#Y~7qkNt5cR({La1H=G|&Pc84s8MeI6fhQqOJ#?xK&qPSR6F2d({b%Do
zYCqBx2jRLRkNxA)elF7T_=Y|`59z$}^N?uu*dBJyISa6<9UIEOoP+$N4mqD?2J>(*
z)EgHtj`eaDD;SO&_E$@cj|-8mm#)Q at Muzg+;fwZ9C>!bP=@b!IqHLtqrE<7;6Juj=
zc|Bf7#sx~an-h%&HTRkTP`PA3Uk0A(oI!bE{Bq at EGzW!n3m^|_^IQoSr9CQxx$-Jo
zmU7H=mE&u0 at 5=GD1<GG%%je?;ah4v+IQ9_bYQQqQ-i9|I+!=D_%nPF$uukJVbOrKU
znW1fSBh#AT6J?8i&;rWgCcx^Yc6L)mjZSC+Ag>P`-j<=Ax&2g6ZbjX$E=KmE^9tMS
zlZ<GDpB5j)r;mFZ6N-14hPraTzmE4?hsnl+kh at f2VmE!UkBg;jD4xS{%9q&}&*AN9
zQE{a8FSD%z-zZzRgKp}OCj79X;$iI^E(xTd9mn&FW)&U_5e{vgX>OG2whPUO(k*mZ
zT79{8)D`A4UcAY#x8qE)YEWpTj^PxQH81J0JdW7u0GEM^j0>vlRGDaEPsr(n9LLf-
zC!C*aA++JR^Gmt6&-=@k+$L^t7@@EYYfek^+Nwy%;^wzM$NQU>OeYi|-v6o<X*Vnt
zwQ*ESOY^IRX|Bs+_pm-&fZC;NL&WnWa+iKZ?WRF!mmr5>Kd4N8u(a)pv-Pj_P_tSW
zuV7i)*u;Cu=x<kvBdGmwa8iZi#@yh8Y$r2yJahiwJa{Mcpw5Gj;GSbp?W%_ne-yt+
zUt*oAb078R<M`1weT*TlNrm;G4l%=!y2kM7sG91Ea=bRId}?TkSe2CyqJ6EjkWTfz
zdlL0OWq<kf1 at g3|kL at Mh+TLezPds`yNj%Tt$7gwXZmD5D&X)2#;CLxL3mm?^h&=Kw
zznm{GMdd=9nXvhAp1fk=w2h>PIx-z^Ag at _??K_3f$L-4-30Sr>9j`BMTG)I%Isbg6
zQTdgQE0A|m>Ls1|xP5ug!s<6i*)N3UFCBl0d|=BcJz6FmK9G+R^bkHB)|XE#tlF4_
z&8Hjh%}c<g<MZST3zv at rLWMT+n$PE#5IzA|hR at jW1slF>!&hzix(yfF at GTp@ZNqnM
z_`VH4wBg4#{M3e at +we;peua?lK=xsm!YbXi0S{M{<LH at jkN#cd6%AE$WzoIT3cGKu
zeeS7!gED4*c5OAInf{u^$0K&0O5%0vHPtv^ud1vt{+<&y$xkoariWYGU$qR4T}XZC
z>Xz>i-^t3I+gE5Ju0R$cpBLYaZuv8;u4YDt#t?O^<&jCFV;ti?R+)qe&0tydAov!5
zZ{2|Bhrf?+Luh|c*RmqKhJC6sE<a-#ITy|)W{;dYihQCzj^+qR$$u=L((>HrwUXtM
z<B4-p8jfF^z^}TrmmN<(0hW^dvkiZ-;eT!T8^ZiLa(Xi at PxVz&_jE at +`S5`(MjgBc
zTAKc_bt_GO+BjbhPFf4m$UK+NNq&)^tUn1C at MXQYRG-!2KA%oJhhgFLS at M>a9;MTz
ztN&88g>&))ppkR3@@_fQ;m%+8BR^`R7f2gRlg at R7SGkMB`qIwADsG)a6h1C*fh?cE
zO?b|0`MmMPzVKdL+&Ty5!w0g0#jSH1aqAqFE+-|@IfWjbd*ZbF(#67(ryM8bsmr64
zkx#mkJX*z;8*KZpE#j1y_BQNb!;UuWWJ5e2Z{Sw4;i?F=ZS0d|KgQ`Tk<|giOZlf|
z()k at oR|}u4qcG1)q+5YH(s>xj+KD>YN9-Gh=`vFyJrZ>gmcK&nShqkOO|@fvTSood
zl&+ at br-k$?KwF{q_fEiTpQ!A_`!J9`7Jjsqoiz}r?5t_SwQShkhU?gHJsbA4;RZI`
z(1sf!q^uHGH1=_?wvj8>q%lpd`y-u~>bP_`Pd2e|ic|Y9e+=V20|}gj&4=@3a|@?>
zb7REWmQ8KAnGLr<=+;YF%g5)-mVo2M^#<21x-UxIN&albe8(p=pC8Bvt-K;X7fZu7
z2no-<y$BZpEj;u1&F{2+P+Z$uT!SsHhnk at 4L7QjRj}Fa>YpBJwoyB#ZiwliZ-jc3+
zU0hC{;@aNg+QH(A%TwGgiPsZvf4rVtp4PLIt!IR-hy7THmvI{6c11id-qyYaaH{^K
zoyvMuCgU^&G8(k;QvIoRZQ(K{GS-%%+}#ac(>7Ll9gjTz*bho~Sc5MUY&nIc?o6l4
zm)$Ka at x*D)tpl}<sw2~J1u`*Fuj<D%+<RMC9iw|7&UWl+!@X>nL8$E at KGK+muN-i^
zmV|GTgOBYggl}>Id|9NEPM1E?LwSp2&dcd4=EY?vw{}m<QyWrcdz!7U5~0ct`OlyB
z2k~&-7uAm^=cZfw^Ya4HIWRxZrOjJ`-wW5ev at f;q<Mp+W8e5;r3i-;P&UJD4KxP)C
zFSm~GZ|Aitz>?=PY*=l>S{v5cupS}X#C2rE3rEK>k2FPjF`ea^^}e=O+o|v<hAWWS
zsDl^#hp1;EPG6ikwr=h@<nSW{{ltrPb3MyEqkEZX^Ay*9z(Jh*BYd{-zAD_^X4K-n
z|KYP4m386XX>@)OZb61Ceck$N`Y57zKRw(@qUNq?gjlyPo4ae at zpO{!zPfkF_Vd|<
zT>Ep+U at vSHe&>MwhMk25`Z at Fa26t)P9?5V`&vfd-%$SPuy16`K5tDWg(!xWm at LLFk
zBfg0GFxkM?g2yP>7 at o+4<=M~t)LaM_)`M=4$(2*4WbxoOo+2?mO2o_gxV8qLEXmdh
z<D9$A&Z$0xVCm<)RhPBJZ5rpf5H^=X99$RZe!RAm_C*LA<rw-ohbQ;-wG8Ke#UDRb
zfS(5ZQz+M&!Q+Ny#th$MJFZbQ&Fu7KW|Y at Ymndz_46x5`m1HW)Ys)Jt(K)#?IN0Xb
z_;Pzh=3{*(e*oyn41pv3jO>gGJl)QYitvt%(lRwurqtszcsZO-p23Db at 33M=`5O4#
z4W^~o&N6-VE$K3CjqPgTEO<Hjo_RyFwmsR*6uw4GTWw|UN7JtS-JK3N4gMW at u8%?o
zJd5T*i1=Lo)auaB$45Nlv~dbHqu6)!9V%hoSU%){9&EtN0_p{AFOgPASG*f+#k7{v
zns{q#`EUv1tz|XDE350Xb>L+Oc!2grye?Z?RbG)b&mr_f9M8bfIUwBnS{ep|PWr!7
zhN^38%(L30Zy<2vSP)JZVLJvPp4pBGnd+MGr3w)Z71+M41Dx at -2Hd3V)XHin&IU1W
z2yu+7u9%iJ9<?Euk%hcG%L8AAp-f!}Y4Dpka}9q3*&6v3HlJtzChp|Z_N}l8m><Ro
z5c-#phxOBNwmY5A^-O{LYuJwANXJv?rcT~#U+uY9=wq-W(rO#)r{Ot>is=rn+M3!h
z$+l}G;2;mix12m++!V3&)6O^DXK^q-nJ>b#`8y+SU%g{|8yMFy#P%>gqkK;INlja3
z7o=e>;YT*3GOo<C+^7&HTQ at 6|rCkxv&Zsqdn)zc8ufQuTl#X$TV<y3<uSdVPmE9OO
z{?(J_WUBCH&1`0NWy7>gJ=KeCi;;Z;V_IZrVOl*NogrSz**=I*vF`%Vc%4az=c8-j
zix1Ue`Umf6vgJ^Bm~8P)(ex0$y2dG^b%kYYmgU)0($$DBc*2Lo_`D*X*=}Yd=OT{H
z2E;4)W&*r^ko;*xd}=mQlr<{<b6IXkc~wPY6}E^oQ}J9k-kKDSA<9~2a29B?4xjLZ
zKGU}g#~yWtfg4*nc`m*d27xqsB$qZhQfAsWCNJjyZuL$R{_kw#0jw83m~10`cMn7y
zDI at 3BmRGVpXs0)iFbN+;`lH+;1N?&wJj;lz|F at h@Sf3DAr~TDa2lS`0OF&c3F3GKX
zt}1MUxwQ_mU)IY%T+vVNB|U01JvzsB(UoN;Bpf&N+k7!&42em<nty at E?O;JR at qP$9
zx52ANX~=V}(b{CueudAJBRmCsYZQCf!X>)bXr0ztM8C``%=;x6wehN#WUMA?HqTEK
z at H=&VY_t+{dLH+IQjDRW%}mG^*X>-xmtfxHeG_t}ZBv7<S$+{pOt-BgflA_8qWgnV
z9ri%3AO5}Meu$f>%Sv$^+fviLurS?8(>YG at Qgc4yeG<Rh2F32C!8Fcyxk>8}+bfGc
zS=zS6c^hvxsL%x0Tg{cNX0<S0$1=5ZeBpK`U2Br+ESV3bnv-ds(HsU{slF)3<KEp{
zI}Y&^@Z*>@I at R&LVf-Zgj9)lITna}Vy8l6cmQ#?=pUyG4vVoi$mGw*=O3Ud;Cmz=?
z<_x5Dgzli-tzkaSmU3o<Go*U~@aW#z*~nv?^2_;hPE;=Riy>@2oG0g5IBg^8p-xN3
z8^{F~UTIMHeB8cVlz?SB)A9OpiG|g(1;Xazgg;|~UgcdnUibp1&_J5=apT=!7FPG<
z*hhrrFCBl0T$7+j%cR2xa$SNR!l%Rfa)X6co)9*lZclDXz at _8!<Q5B;j{^daHu6#*
znUev_{khX at c$N*%wc+_TywHXh+wf8wUT(uHZFsc}ueIUzHoVb>H{0-58~z*NlS}k}
zv6^gYth8lug!${%obiRBescB69f+ at E<;(38(-GkQoyh0)>=ON1mW>ZX^0z+Vn+=bk
z{EVby%U|aN>_C<0611J|raq1IDD>Msw%uuYI{wr0lH-6nKMn4ICh)61RNt0+0n2f4
zpAGM~;e$4O2w{F5Io+3*r+P+puIdc#SLVY9@)+virM at kX*t(UbM{WFZ8y2FG?Qr>=
z<X7svhW>cU*023W`!}CXPoA-GdS3IarAO&>>C$t6ztR at eUwRC1y1p$hAWr?PvNRv@
zsEuAAFCxxM=PSae!}{{Fh1Gr`UKe*<P6K&0ft#>8Z^dDKc|8TU&RzMu3}m5&*SUze
zo0gLjc`Jn;oimd3yklX>Q;rkYw}m`<4?ofs=ch04+j4{LInGOnQ?6dI;cGU0!-j9#
z at NFBuYr_u^YTH;}vLEC0mdHnd;iY|}WzzW_$R`#)Sw~@>m&j)Y>PY8dAYUZvU>|V|
z7nYe4`6^KdVfic6j&BOo(NsIWvt^RLEltZ$3;DhPZH3zZV*+0LL}e%5hk^WL;YVB9
z`51A^&Zjo~+=gG;@M{}>Yr{o0{K1C*vEk1MDXVe)2E^biFL&&d#x%M9FVcCbj!TF0
z<aY~~KW5|S!|}G~{0>w%{sugx_YWKXX~V?`({OKzbY5JSa6O^^D%6M6cYbGNCeB6U
zV;A|BA3U36-2uulEJ4UR`Hrs$7t$4;c{6c77U at +dPjR)hxLR3U$2LLN0-JXdLYHR6
z#rJKJt~M6e(Jn3&*qr5Xk*=d$Tuz?iYG-k^x44Km*N(WY5w8b;mS6ex<npwhQd>_)
zTTgdekLefOySU;s#BGImUc9Y+3*c0pNL!NiQlF6KI1PcU1loA1PE^~oaG4TW#g?Jm
z9RXg`e%0}`8uIvKT}pRY1HKJo%PDLLXiBHcm#!8zpXS_}Oxvh>FCAAPYbEMcotK8Y
zyM@&;xhCRlM>iX;ZNnZ2wH?Gqex>1C7jV3mgl|0uAKOz1U(W*gdLf;3y7ZAA%5^k;
zQ~Xt;JoKS!NB0FTH&5+CmF*2}eSHwB?2!NbX at 9W(h8Ug_=?i#X`FVlpyq2Hm(iZnu
z(Z1BakJr~iHnH`otdOt#v0Q#Vc;{C^`f_XP{#IA^11x#o--a98a8ny at X2Z=9vM#Rm
zBAzDnGHHtP9G%5-ng<YE`MxPz0zZ9I2HASJ*3aQW2Ks~-adCagJfmlsX!F>wBx!5l
zV7Lv!CZ1(XI*^20iqUC7v`yD6_mte;V{<)JbeFH$yZ)&@Dmgynd{n-%J}T at h*GJ`W
zjVF9msQ;2aDn}wM>7zn?5qlgT6|S3>#Ycs6u<N73`8wR1)zr|(g>z!g6D3UJ+!n&-
za_FN%8$ma)d7j8L+7uydlw;C4ZzngxwG8Kb#s9zLqjDSC<(}lJv at gw;lk)0z;4I{?
zau at TK;IDEwVTR;y+R$I+VdSZ=0^g5Df0ZYY=K8BV$?^sKRi0*EioeQp4qo+Fd7gM3
zf0Yjrcl}j<LEQCM`4#cFzsfS~TcK at fek=G`K+JE&Lp;rIg|xVSD=h%$`mHcdFA<)T
zw<eAPek+MQ7BT(<ZBfScTQPCRFNL<Z>$hU!PCjj5*KZ|^6Cm_kA^mB7E6bx?x%FG&
zy~=|6t#m+I(r<;hl71^I0M7MWVchjwp}p_=tuXHTt#m@%^;==w^;=;)>9^7uX|CT2
zVJaM7E&5%o7{Ww;D_szG{Z>|H8OLvBRm5Gtl{FY&g5Qc60|~zsrn!DA>j01Ix5BvV
zx1#w;zm at fExuoC92AZDYw-VtpzAkaUmEI`l`mJn)xa+sF1>&yX%0R@^{8qMNxdMJG
zl#evO750Vew_ at NDek-}Oe7_Zwm+)K3 at jiUZP4eBk9FJwJ*YR7~7ICD+{8k1NCgHcj
zGkW^13^DL5lkT^&ELtgisfjydES>KM?Kj$+IlCpd7HY!Rz^&ML1NIw`X~>_e==Q*z
z)c3-ejObk0#aNaZlXPPl6CT0F-B`xt+*r7790q>3gQeLlAC`!;d?yxLmn?%1ON2da
z-;$kJY at PO?d0Bi|5>+qJoQ>Dq#Cv{;SY39aO46KIlz-gw-4C**=hGu>|FEx^&NV*o
zna=wr<SprwqV5Jud at G9;vPjI5h?eYR5aUnOKmT`pTOzimxZ}hv<)x+jpYd&pwIkwv
z(x!LYpeq13E#0{#r9W)1{FA;df4zl&L;u-!{uSSrh)%2K@||0Bw1)4M*#Tow$Llyd
zE_F|8EaKzwi*&8y+d|#D8-Da{nZOX2!f|ZtUI~3$_CP*=I``zt2C`>V)-(ECY1s?u
zuD;;DwCm at xH}W(1anDA>eEcnCp9p_AUn~G^+P+E1WBc;U`BD*;3;kROn-Awn*1~Cf
zNe}f~I^IC0T6m>F;q!6(Qkj5dJJa#{GTp-JIRjzyae6Yt!YRGVyL7yP)L3|>SK;$<
z`!dtQ>RulEi0$Jq9Y5a8o1jO_q{G8MIzbQN(_wv?ZDExsgw3bhler1FbbNSEu7%6T
z0pUj*d8wbv?trD8HPMFUHk at q3DK?yD!+mX7Wy5M4*4nVnh7C5HWy3i(+|Pyw*ziDv
z^zT^mdtR2_l3ONMm%nWBh3^BTzEZtFn}T{lW%*#_9fBX_&Fv%h3wz^V$m6wSzZcb_
zOK0JNFDbhy&31kH%bZd9rru$@scR!03w?LEZFgFp>Vver<hbB`kOp^j6Zlm>s^7~I
zfaSP2(uPObaJ~(XL6~1hP8X)-soqgJP#wZO?|gWCrxkVZQoomDZQV-KaW;N}4GYo8
zcDQ^_ at +)=DLw}rX>(_px9Ou*N$*C4j&wWm_^eCM!U3#AISK5O5OLqlM&bi9FGZA;^
zq)~`RZS(>;3vpgL9}r&UE)EM{Q46cMbuLi&xSR%ZUII7absmeu`f@=EZg*~q!v}Ja
zh1a=>xSN)f61gOW9-Twt_<gy|!jh*PC*-NiqbrccK2GxJN?UHQJr6n?amv-XHay>k
z7uxV*8(wO|%WZfSLTwxSB-xK~df{IR7+%^pS|**}@GrIS$vO)2yhLs&P)9ls1Gy<t
z2m6R)m|?oil*lcKIta^Op?3VcKpjoB<91sn>G#sK{Irle3(!`m{dXtewNF%b;(Zv%
zy%v77m7Qx5r|evB!y9dQvkh;x;cYg&!-jX+ at E#l9hmf)w*Ka@!zVdSAnlz@#^@B*~
zr8+Jh&Xb2NT)zH``@O{5p7UQ&-S`mjklsgZ_^1sZLzsr!^?Tu3L;YT;52^2-#1Dfw
zYIA-Yb9p at XWZh4p48x}p5`HAY2p7_of6UttXKu_hYbYmAaXo8sJ!f%^ad9Q+8g26o
zE+<cMy<l;@XmRc0;zA=g$384C(zUaT%gIw*FI!x%SX^-#iQ5|SdQgFtpZt1qd0Nlw
zww^a^J>3CPh?j91;<iFOFW%O^1#qfPq%FyMsZU6AoQ6Q&MLsXpiE4WmE>j}!+cI1$
z?}&TavO1nVM4Ug?rF4fi`0|l0r?AwA>2%>8m=-pl=G+=h+o*ak9akWqC+bz5mxlXG
z3#()DQ^eVh&usXG4ZlLD?I1q#D-GW_$m6vneBV0w*q%c878StvJ<>_1OCRZ>yhSpX
z;`b8ep$}(R+$<NDtK9lhW&1z2zMl}P?2!NbX at 3w;18B<CQ6j%Mb;R at V4fKL}E^TqY
z7wt>!`#4U#qrl=+Ss`EfW4V0#0{OEE8s^%({#IB1ia2 at xUmN~r!#`}e*oFeX0oJtx
z;t?+#9mhP<6y-TO%gqA_u6)0j0Ql+mQex{F at 7BX2=o4PV#q}lYNz>URsU>hQY=y9i
zeb*)Vz3Af89-`<Dc7ccPBIs^gH{0{YZUHv?sKE7n(dVFJ^H<LI<$LS<!v1o7UxsTu
z;rl`znDl+w328~+7vf9vec{?^S$tnO53838eN;GShdZ~L8v3qqUd(y8glU}LLfBjm
zanQ!s{cZKlpj{E)5f0xa!?`=TPp)M+=PUmICEu5MXqS8Zx2y+><oQ9sS;+V0Q06Vc
z_vJ9c3`zHWS%5tCcTnG#6OrcnzMRDJ1$<vlVP1;w%jphY^?f;mcpcxDs}Xm7U+zcT
z^?i8&@wo4cDukumyQ1u+`M*4ldffN6Jb`$c{|o7H{a>Cz-1UE9oZcopZ-1UR3i!Vy
z@>s<9zr2JpuK$aPJN_-S!Cn6s6L<1y3%mX=VVnS={|o6)^M832>E+h{h4(5C>i_Z@
z(vto!#Fg}aS%@^(|Alea|AltH>;J;I>;Lj5;;#P-<F5Y;<4OOQw~*%gzYwM(;s5e>
z2ow3gyo0#w|MDKoIQ}mmAny9Ve9ZU~{9nvCNcg`n&Gmoz8gbYEg>l#aMe~#XFW=d6
zN&lB0G(E-tCBl{B|MDZsx&ALdBkuaYc+fen|BH`!n*R&GOjgMMh4PW+|H8g-{a*}R
z!v7_gmhb;!@)G_pIo=oce`!rx9sif*5JyVP|D_FK3i!XYHSjEx?*Foknkmf%<}dG+
z(~hIvnX}_^YoaFn5%Q+1jr$k!e_>9l|BK0p4#!=LWtnkF|Ce#$*>BwcWnA3<WqI(s
z9W2gf`@a|p^8H_IUCZkK;<Rtc{x7!9$iHG%;rBN*!vJ=wUZPPOulX<dzeL<C&{y2+
zD%~HlrDxckZU1ns&vZSvVmj}ekT-3!nvu=+f3cj1#4L$u$^I5G{zU!rf6xD=5XEt8
zd1>ixVjY$=yW>1wdd^3 at PgdZzLD9Qu>HaS%{b76MpZ0%=da7A1{2Thuw)3z0zeEES
zx**^G#qtyO9>*)!4mw`fu;WtqrdCJ1D}EfmM%Oz2FN}A?kNz)fGQ_2D9NW5QLjRYw
zk<XvbJ-M=hbdSn<rVgcL9i+SZBI*CKF7nsIk9#*7=HqWE>qq#*HY@;b+P+ at MWBc;U
z`LaP&F7$sPY(AVP8(KJRFX^FvOUE0?MiyRaQ22b at zVu7LvYqL8ec9N;>UjfU^Kp8z
zsfAN|m3QfQ1KG^NE4>PzkK30mEUfP7v5(k3{?hT6$d(Cuv`jjDAX_EqA$&TlFWXpH
z<q2W)>GovX1Y9~kPli~yd>jydw2_zkzpMpV+F3np*wco+ZP>?#eQns^hMU-MfDJdd
z;XoS>vf<V?EVJQY8xFPMb_kp2|3Yn%zE(DRB+QDop3Gi_RfNmr|MHhDzR>@L`bzZz
zZ3@@_We4O9$B**n_7VGqy|E+mcs0-eWtsSrvXjzm|Chha8I^D99k!dgHqx=scOz}P
z)ACdwq~#^Y1?Ph_xLupTuliB_Uv>s8$Hgu-9A(4NHXMU6zmA+POv_WfqdHA>2=~SF
z;RBg~I(Vu7%Q#!N(lp-2ce7z38rcq)&q;oz&UxsMJ#GEkZ<OPFIz8FT!s+?X-j*Jv
z)1^z#75++FP=Dzvz{xpRc~_3OJ14D-c+^HOkV%O1()ob!DtB>MUnW~v#jSIJ!pG$_
zkSPh=gx7g24(rRb6x{CI6o(IFUkk5u6LB{!CnZvqLXXZNas0kiTUhdx<AgkQc~pxu
z_HmL&Gi|xS_FSj}amrQJhEr`=X~XF at oMFQn8`dGzwy{r={TQdWL>d6YOZ!I4r1LwF
zSr$H7M`50q$eaRor1LP4{StMsk2r=Irpru;9FVAku>2Kj$Gie{G}VrSZJDJ1OVjex
zLjF~NwnFVcECH{5qOue3!$6L(@T0BlG$KyfnQg<lHr(Ha2iou;8y;fALv47t4Ua at f
zS&i#AAO>G~xpGY!)8u+S(s`+lONaAhfrZQ0e{uhpc-wP+45}NC0UpwOtPPK|;qeI5
zaJ&95Tx+QR3-uxO-AVXi5Jzp!Z(}Y`&$UlR8PaeHLc*_zFv5j&<sb9*$GIEx%o at tc
zQ(UK6T&G)HtGT!mbggRh3@#^6ah+*#on>*Y<l;gjUH_LZE-oieah+pvoojK$Wh8EE
z#OsN-KVDBRPwTnB)^nk)r#nCj at iI<B+*XL^#oOAq08Z73v?W<D^$GhdPD3D<BcGS*
zM72E&mno4eZ5ghWSHL}OSshPTBhDY|Qo6$$e7VM!Q&{T5bh>=G&cf!?oLi%58&&V6
z;|k=)M7^r>(s18wVRcMik2u?LgAH%8;VlTY9mGd|rQ!QG@^~!?-)#;)wx<xjI||^t
z6X~SWrH}Mb-XfVx at qdZ((1)8^+$<NDtK9lhW&0jm- at OP`cF2GJv_FWa0W{_6D3SY}
zI^ubO=)9I+&ZRBx|Dt`VeILh(cOKaKR947W{#Y)*o<JTgNMDWz{q0=!0AR`U2W|L}
z4Ii=LV>WyoA?qqd81cf<am*u4QJ$l-+&qBb%J+YH3V7-N^0cj|t6L9?pig)a7uT1p
zCrxLQq-T-G at HvD{?7KF{|HWB)>kf7k{x5bt-faIDy9L<nqk;ndFF9W1`@gWiT>qDj
z8c+DYPzNUcUpgTz>Hk7}(I$lR?ia3|mc{>t^RRllunx}I;m)n5hQ2PGuX0{4VH)SR
z5H^=X9JKLue_MT7XjjB{ghT%q&fUp<axKF-U-ADh`M(T9yWHcyXisVBwxP_oina&N
zLjEs1F>eX}FCz#uB;EgIEb`RfLH%ELN1E&ZvIol- at PC=eycGYJjDuJGU-lth$N!}s
zao7LlD8ya=m!lES_kUUXy{kh0FDIZL*Z<{2#MAs=NRR9Paw_7k{|n>vHlhE^8N^Y*
z|0R*fBF6vaY?N{RUrgNbZ=ntD`oEaClTTaN^?wQD1PJ|KNPn9D%Xvsw{}<k?JgEQ6
z`AAFpzYtf_|K%d2x&AMVyZ$eyA at 2IWFz))lT#UHu|H8QI|H63E|K$>-x&AMNN&3HB
z8p1^WFP9<i`oCPkGLHYtRfxO(FV`}@1pgN^4if$^OmqETZbjVne_`D9f6 at G;|I6*R
zT+;vLE=^DIe~ECV_`lqZa<2c&eTcjMFHa!u`oBDhc$)vqGb~r&{V$Y{H2)X&h3o%f
z;1d2XxwL%$7n7Ipf64K_u>Z^Rtk>~>c>!^x#Qa}gBuoMSmzNAY%M|v1Sq9CN=Ku1S
z_sVI<(eBLIF1a-k_wLq0o}NLziuQ0{K=&}#g)O+ev^I7*p<YKm%Mf2+&Qtx;g;5#5
zv>o8v0dD8iZv$mA6?F}ns+x-Os%(ZsJX6~^sj9NVykVqJW?7l7=WW&l++0T*I&r_Z
z1S_=1yPV!d9(u{5uB|X1V}xHL^JwF at j`C(q%2YJg;Y)^dsP~!Qi2Qa at epLlNuQxec
zTRxTFt7ALRR{uSNpLNhYE=1~*+o9`<R^SuqGV70szkz&!dK8Ad=dTTZxjqQwBfx0?
zyor0}y<_O}<P($Umy#dkmEzL6Sg(uga|_S>-j=uK8`e(QGL-3xpVErsZCrtTjk3#2
zup+-7%=JhY!FL*+_-ZEJx^(RV at GB+YSGVxtqe+UtwOQ+=)wgn@{2C_it>B|RrI~Fl
zGxhuOi=nr5>9$UsvSi+Y?6jBfLY$G(-rsF`ZI8y4UX7C%q&JL*^e9f39uEv-T<Os`
zzcnUaZmcyjYQ{i#F5kkIQ at ECht32EQx`|WsT042CCi2=idGiu^?GklxzfAWp_+4RM
ztcNmz;UOIWuj_jKc6B~niF5><>Z9B@)jWA66sj2Q=UbZi-YVq>>(n^g?Z(+wH_rCC
zacz^9ciY5w&+;O?wrMp}K3K5?dF)dxn-*ys^?k?r<w~S0%4r*O at 7&6LAIGJMZS0fk
z2S*KtkM>QeG0uBY4BC+TcWu<6I=egWL!IrH@;)5Lp{%TfIAxshy59?ZCXBC#pZK1v
z%Mh2su{`PTiS!5#X$r?Y@`HIjY*}~Dpl>WMUXJ6kP`MagBnYs)h837g>Ki7TRk7ic
znNF<!&CdYW?6>^TiEf)#wsm}hd1SfHB2RS0dx)X&*GIb|o}(<&dLd11V6KUnwgJ+n
zmE+r;oHJ}%Zx;^VV<nuMww9ANDT}Yj+HY%ah;r5CGqRkQScdVs^4XbOS|{m)G+y&^
z#F_6cZiIBqaYOmJ&yFj0^7>l1q}@VUYbWda{cQf at Xz$8SOKEUKsI9CKx60baxaYj0
z`eqZvDbJJ#LT!pT<;cjSf%8jQJ}l#xZf@`0c>?=K=9 at NzTj1c{(&94Z9X~9_x5AII
zJBT4J)=AnZyGq+Oi0e3X%aqwN`FTKO<zZF3XSX$ADVN*Ya4<sFMSQG_IELar!jCki
zDJ at Uy)_u|KEZ$)VtF0}=F#=m=T=isp-?I*%{+zrsrNY=M0|Cc=j^#jJIzV2AATNW@
z_vVcXlkdy+$am$J<Ej;8VF#q^McXC?1H at unT80@{IxkQbR321^?ufLl3yj}L&hQyv
z44$x#c%s2ievbei%8=GYIU0!{WiRBHFFPYnSn`Ol15))WS~qaur1Hu5baQ=!(XAS>
zu7^ezcO?#E2m7VGUjTe6S7Q)Y*<s#j{3wfK8RDXTX1b1<@wlg~X!!|<r<LE$me0?_
zJMb}1dFAIJ(aNkjGr(XP2Rs47-4P;?Js3y0CqkAdZTy)Fc1G7ixCvl!ldmkpb`VF#
z;xKJTnzlVHPupc=9t7=!vZSvZp=l3vGI1*|)ye<Hc#zJ4bT;&b-|(FXIPI at cPqvl4
zkOqr9+Q`CQ!wmf at d6n6etb$H#<?RhP>>JshCq7>$A<Z2V(7OgM6D}n(v!*nZPr_oQ
zqJba#uBxeTgtj*Nxsz9cvb>TymU7n?<7%?a?_zZ9lI70TiP)dd$)V*r`!L6+CS=0t
zkAY2(0gkrH$<ZhXqwYA^7j4jSz<YNbR3UEq4|FkaI({4nGZ^CHIAFStgBsks<DeGt
zwDL1;`TV^6Hs|U^g^6)c4Lp>yI)oet^^7BIKuFvy%b&SY#zBOe0M0mIx{iZ67Kdp&
zYSFe6e=<+orQ={O%96hQ5Sq4P9OUZEoiC(~gGQ90DBBK%z0g)>A+0&%U^d{)IIx8|
z4)#Y{avTt at Ipg2}!0}3s1Iix9!GShEF%FuPJ$Ed$wPS(2X$KzX$pzLQN&V>ZQTt at a
z!eb$WDX2PA*U(UzshPBIwj!Ju@>1={!1$*=Jk+6w_xzd5ktKz5$ITId({$G+XZfRu
z17qk&i;H83={kny<K7)Z#~`l!aLX^S<@57gUf~@kkiVk=%kWr)94E)6;bg;{F~GWX
z44jDjsBU0T+F5rpPwCPza1zS0?vu4ni~$#y&IRY$xq$sD#?EdlhvR-p@=m+xcmtR0
zVA|NNyc3W&FR!1&efLw47atRyyi<|JD=F)gt>qx=r`dc**7LE`$j(d6$yQ#UrO3C-
zBbVRtIl>d2dns?ULpXl6E<6sXQf6n%r)O&M at p_W!Cb;v$ImBh{Bi_66eIDZ42IifM
zA7%P{hPWuxOjnt{5cjT3UxavC`HOA&{5&AFvT5vg$kPRYrCeRY5ZRX^BoA1Zj=3_F
zAsv_FXRZiGxL+F4&P+%4nXa;b74CCzxi*r<WS-KmvVS$olE!Ngnl?f9U0f>rm*v?(
zfn0_%Zr_A9Nh`Sm>9eQd)W+B-t-LD{H at ZIR)zI#_7U^->4h(E_^!;@x%PTnsC|7MT
z2CldH&KQW1T1c*3o!{Q-eDZ at bo7d+^Q+Z0uQ(i}X4)`XXnaqsNPJsp4Sly7pDXm$H
zj8CNH#wT(9n{+|`TSBTzWZXEW-JYP8Ft_1nu1J17Q&wgFF66tie>dXVo~S&=&OH`S
zejcz}+(xbty%(@P!ut>^ttzh%AT7cRp164XqD(F?hnF}=r;ZzL)e-Jt{LE$RH?%>9
zb9wQ-pTOpYJjvNN^Sp5H<qqKMxZ)~ur^Sm^Zhb>t&D>Cy!}Qju5b0IfhHR!`T4g=+
z+OO!rU&^eD$JJ-+MdR4hp8#EEU})pq54?#^HG4e|B0WA9IvE<+ta- at -W?TjG5OEE!
zu7DRrrh30{kB4;IG=o>;vjG&g0pH;z3|8+<;vSF2U6 at A*gO-E>N!*>}QKVtN+niNp
zCY$!xS)881(Tw%VW5B^SCC4qt#R?d=k0YNK<+xPLdL`L<GjqkqO3Ju^Tv2A$Mt^hc
zQr}Z%e9YTSe;WA1^zh!wzu9+HnCBuG&!p>F(+g3$l}X_55B=zam$3A+RpoQCJlAI2
zlUlGjTUUn^#(lJ at t`fE#`fzLW9c1yjPw_Hvn$}wPmrQ;6lx)LX&VLg&iKp4de!pmR
z>Yhf(voUyyes(ga&`f=8Wi at +dI+2abq~*l<_bS`x>~%5z8h&O#yW<Q=Q6BD92k02g
z<>kiN9^eyY?secxCB^PvzJdIC=>Xi9^cJ#w;yjf60EhiINvplQkgMsKn!%4I)~*eW
zwN=?cTN at K)n;s at s)}zPxI4|D at E#xKTkN2u`-^IO^IrHtZ_YhaTO1O9MqrLJzLtK<u
zrn_Z6L_DtyYWT=0!+NwY`vMPfd}8u*xCh%l`2gwKDE86Eh^vnP<DViPp2gQ2y<y at b
zvi0 at oGxDhfy#LJLHY9@*Ba4cX<2IE~O{|GHXHRLYu4t&l(g-KERgpm$OO5mV3(yeq
z+%M(*0#E|}8$N%9xblp7U*bnTf6WjV`-$n=Pv7F+<@tArr<Gr1%jf3-X*6cSwazzy
zrOov{LuCJekp0WLw6DrghIIS~KXXMmLc1`cotZX|IG9d)Nyjg^&%x!|n3kvXt6lgj
z%96(aA~bD+9(8f4U3eX2C%!)x$d4$K-*INGBR?U}wGDqp+}MV({tVYXzacL^Ck7tj
zn`0mT4me&(9YI;6efWpXPuPcXDk!me4avz`SVQr@$bljUiX13%pvZwD2Z|gha-hh8
zA_s~bC~~04fg%UeIB-~xK;EkpIsQxRHyt2Sb{^hyad99wzwgW4$NI8qMId7q1=98B
zK<c0Kq}M@#JoSPvrFUQt;`l%Y9p=diZ3CJAvL`do3}omkf!wl{$V*##GH;+K``w3w
zn<;?|tirS6Eq$50A at Ztx>3CEiYhtft$3{;MI at p&(uMTARhazuYB68{%BEMf7$i#Lc
zXRH~>)m!?~W<O8f{Q^6RYrv1IlP4XrzHIll$oXIRa=;;;-1>_zukPf_Ss&r~)-!zh
zw6`yhZHacg?a4_mij+Sc$fzd*8Bm7%d$FgqY9OD at _hkMiA|Kx#$cRnx&VmKlA^y;l
zQ{KfM=}vebd^b-%Lz#O|hA+~yc<<KlzLdWf$S>=A(zC&rD~`Z<&g&xkzv;^zLjdoA
zz6}HEcb>=t69VaRF!uF&2J#i0cW!!L<j>OrnRyEKQ69s$ui6E&xKiW~(7yQ2K)wL(
z|D5m3*?W5O=U1L|Mwu}y`*P24?Dy`EZ!q-n<lg0RemUBgGsk&y#&_6T9O}u-U&9Az
zzR2N#8G42%`+nd_%}FAgEe<4j63+&V7Fqlm&R|Xy*>b!mPoEsfut$Aa<rPn^UQ^^m
z_)@R>AllsM%X`=RGH at 2!xQ#De7UO$HGw|&D1tP0qv-zYMB6nRM$jB=LsoKkvai{t6
zM>W35^Q|WX{|Mw^>`%Qs9Ock=$DiWMm#=#A+q&pq?0@|SdwK!-;@d~ChqXHVW<Q3^
zJS1`++Hmegp1g&_J?|v6WsWZ;lTm(XAa8E$%g=wp2jL`N7Mu{siN6Q(BA!1V4*uS-
zo+k&RT&Imasl&n6?U0An$NIAJBlvwQ^3 at 5Rd_E+Q6E^T<xjTJ1<y`Q6WltU}_vDz%
zJn3=^Wc&k9c3OyM04hCsrv|?2hxyWL3-t2>k$1=Y at -$@a at B=-$05bJ_Pwdq`2Kk08
zuZZ${jr62Nf5`8VzPy1xKW7}CJ-;B3RdyHI6#RMRNBF%C!FM6w@#U4hf%6#bU_J|e
zU5a<qfiDj>cryK&Kq~gbJAAIin1X-En at 8aL;~jjt<SoSK;2jdHqD^~X#DZ^K2V+kX
z at -YuG*)s^_zE6D_b`N~e55qT{_rRImQ6i6j<jD;i`0`VCPd<cvuKWkS0R;Nz{Taxn
zb3J+fa_|lDmhC-x8+F|Y8EDbQm&cC|<c=48nRTJa5vPM+7=u3z_GRIUo=m*klcyGX
zvMc2DEsVc)!LNIF_2ickB6C*}Id~6WPJYRk8nm|*yg9uqzCp18-~Sd!C&=`5kf~!a
z2A*Fdkew!A{}eK{*&3c~zr8P`{^QG{o}O&;5x$u-0dkA;xYORj^LFTiUlx1fT_Li;
zhZy&};N862c+$PAFAsl<ei`V?luZJ8wWBBBt?f(p7+-q4C9=}Nc;5U$k(+l3<ia{U
z=Q3O5g=yd?bkEnzfoD^F`Eweca~}r(LCDnv at MG-z(0w=Jdz={Wr~K&4a*(^Td!e11
zLBBi(+5a!(_bp$>Yz|#l;X(e;W{k5tKk#KF+Fyfl((VAf_vjQ){s=tj_bm7TJ-5vr
zfvf<Xap1!^6a5*_DsBcHQw6{Ec96H*pwEE2#~ygE;G94%LD}8*_vN!;zC5_8FDIaH
zkD7$BjP~u&E0ABmN1vY{a!VibDUj1Jo_`0QkGRm2iw}ao>y0?qZ9raYd`I<nwD0*q
z+VAVje)S>`p}%@;2|rJ?@x7ZxzBwn5me4Q9)dTNII8%V$`W<q5YR^E%e+=LK*1q&V
z9eN%(s7vobeZ4T&);b>F(QNC<MZ-L~4*m8O^!7pM$Bt*CE_{69ioF8aZFx_|bO#To
zdvfW|fgA}L+w)#eUPHO^_0d+y{bgCa at 3x;Oi#CRiY=OSV*s1I1%NG}W(gV8bTeSHN
z^uxnlJo$7j at Ez^=<t$&e!r0sH1L#ojyu%}qNsRH)sPp9$Jvr+-k!>(%4cQ`){Xh3)
z;hmmbi9VYExi0-3W8xW4R>9b~9ddum8@}vyzb|9UFo!`0y}WNAx2+b)t<cGDK?Zj`
z7T;-s9{6w|+S=Ebt1s}S_n)3L?gjbW+mkKth3p*(S%mKFcAqDwVQ$?1R>%tbd5R~;
zpYO>YGXpsty8TP&jOpl;Z=k>a`vUrB7W(=*=&v0D>9{@Q>3)&zFt0u{60-AaAmgCO
zIzzsHgN*o)yOTQmviJk+->(WixQ8znzag^9(-^1F^_zq4`U>dkUwv6=KIYDSJ!v%&
za<mT48=wz&Z}8>g9ylL{e%}4aKq{dhx<Kx?2alh4&zD=kpSE{-vi?ID%LhQWw#8U^
z4tn<qk?$5`eui$n<7>za^x~ce<COGz at V(xXeNfk%(2ezvquxHydE0xk<~hF9q3o%k
z;q at aR|KDNEp6tnl?w+)}!I!5R1KAsM$D;i`$-IGgV2p$=K)4YOuRrV(NbB{W6Bc`N
z81(Q%|G_g36*v=H8}Bgu$(KGC`*J$cdT$iSAN9Wch)HG_$lPnNFSdRe<KmJ~*Y=-;
zGo^8uA2BvQxF2(48~FRY2%WhR+PZll$KvV4J8y at qK&~eZ1sr^c&w`HI1LNoz^#9Qq
zi`CF|*MEg?EIk8%vzDHWg06k%GGEpoCDQj@@cMC2MnKjs*b4L5S)M!z-tRmY=Wyuf
zs`~=@WOs~_{vyvn_f3aR8i~Ffacm$nE)3+_UD0Qk2C_T)@otQTj}JrnHn1U%!?QkU
z`_Gu$_uUQi+0}R#6#C`g?_$pV1mBGXzq?NGW#XFn?kwz+y=tMKptmbdz&li-)9-Hd
z<OlF!*gBrP0NH-A3ghb>ob;6hvL1B(hTlR5kAN&d$G&|X at UQR7IOv+KF;Dlq$(JY2
zhrcsypNeW<KG;2wX_x!*)(>b4^uzpnphuzK_Sz0U{FvWfIuzppcHd0sj~8(Mv=H-Y
zXO!!46rPuatept at KE|9_iShHyhR{8wz8rrl?5fF-p__2-2YI;yx`t;#yF=zWZh?0I
zVhp_Fd(wI|bkKBPI(>%k>R^uE9`v4pF?lTd^~!4kDFf^au%B8(Hys6e`*;lKg<g30
zLCC{;fxOiZGI1?zHO%=J-w9f_!}B^Pq0Ptp;@#oP4qw9`<am*t7h|l<_T)_P=;IeW
zx#CJ+ral09DHpl_XJ4w&hA$5er031x`Q4DeCm~PcAiJ-?jzT}|*c-BfF?2m-a=R-7
zxd#2$`Vz<m<m{LdkykJW-g}iVnRNiajxWFV at MX8pd|AG?Cyy at lrK~mVp3h(hSNd`y
z?ANZCH_vZ`UFvz#7O;aL+pB`Nb<pWuuJ&b5*iZcqf<FUz^ELG5pxMw9(2GN_giqz_
z_ at 3pio|Ir-eD|q9cExyo3_9=105%cy#w~Bdu7mE`^h9`2tN at +=Y9PD723fd?$mb{c
za#wfw!1V+F4}jilhwmptZcjws<8NZF+|`%&7s3{Yj(iGp?X?p{Zbbf71K^LmFKle|
z(JRmcJ<&I}ltGt`fz7a^$l&8K)=+=d9E_6=_~zH1ft<MyaDwMg)j;mhwrftqxPh#H
zdoKDKbK($`J8X0y3(tg|jkXMWO5}ufVZ)&8Wyrf3eCyxRm-|Kq@?XrAx7>y~uNTfO
zAHugqyFuq*JZ%J7ZgmL0*Eh(QQ!ziB at t`k{t`0l47Hb8Jm79TYK4kf!M)c*sM8;kY
zxqLm4buLC<z~<~Q0yg at JSbvPb7(t)z26;Gqo+meL at 5}DD_;Tq~PtL~tv)4r;L-&G>
zf_Z)o=n>+4{b|U3D^G6g277BCz)kgKEzIRzhk0_>Ya(Coi}^_~77;&lb@=n{CbH&m
z%$u-TZ-s7Id%nn37*pR~fN>8Ucn#*n=|_8VG{VcEBTjz_{D3Z-iE&@Ol_wkDjc-ex
zgEdF at KvrHG_T?8M2W$$P7Q7z?ebxf>zO}%UIpE(~DD&8B81uit*9rRjq}N3 at M1TGJ
z2H4)u!ng1bJgYVj>z>`Ai+ at KSw4mM%WC7-jJ3xEGe!i at Ob;O)^Jb7*k^e5)QUXaUI
zpc_^~`qRr{-kpNJI2^if2I%YV$x9ep$NUPKF;8CC5jq>P*6;}A<nut<G-6B*hg}I9
zaRGRF);-YgupjS-e!QX_?Li-BTVV_w2^uku9tZwYzVzh?%rh+?0iPf{eRjgS1mp0L
z`>-z9$A?D``hE`T-NBRgp#7O$JXsNT<V~16F2x%5=m$g|n*`hW5MK^?2J^w8BCB`u
z<&n9NwHnAL#>l{(V7o(K{n-)E=t7rW@~1EBt$?w2Ic$FD#ml#cez_jD?Ky#*j4{02
zIA6Byi)XWYL&m|kGuDExM4dk^f^Ik%W9e0qZwHFpITUix8S^Z3=W`zha>16+`7k1{
z>yPK{|G=8~4%nU0T{W1`XSMTXOZ4ri->|-#2c3aF9#9uZpFY3`S*(Z6G<ipn7r%fW
zf_-?`b%7i(1 at _4%SYtwGZGW6Es|~_<?f_c=yr2BA$W9oC^FY at Z7`vmMht2ja#x(kH
zB>MN58mzf~gRa;ea|_bC9fGk0S=+h0FB^`A+<%Pm0$sB{+Pm3Lkk1C_cJ#%Srv`G*
zSWljTtOe7t?t^TM?f at MOowIHm=-iGN)4xC$4)En=^y^`e?KO|VdgNTpwbhuHpo1?j
zfgNxq<ZLQ at f!~C!^eNt7)Gd$>eW72 at gx!L1HEE$I&*J{lkHOm-te<e-{>MNLJ~@!z
zV1s^kG;HJ}U?-w)w!9g9g|7Ov9i9if1Z%WkJn3^N<lr3e=Lgtw(Cx3 at kMY_9HueTs
zzh4JFW1PJFWgtHs7)Y0|0?B-Wbu{eX2cbVEK at PrK;LEd+(awu}`2l_T5%~TA`s at bG
z{f|O7KJzQaDrE6rn3INef=%!WWCitJjW!*BHF(_zw%UoFOxqFs+Zp!Zo{&YrZ-_bV
zKGeN&8TzEolMj}IK6xdOQ=!Yx_%HPP%IN?0u+PxHr-3g&FMu73cI*W?`PVI2$3mty
zhrMv$@92w-(Z{D?{QL{=nn2nEu(cn at 7`qL+rX~7x`3JBLf{c83JA6P61KtlX&M<HO
zQVqM|DPK0a0b{dPWSzHsdEg<~$TMK?ZwMa4j_eBkvjgUzvCzMBF$WEWoiZJE#RHf(
z&V&td9bP)MKE~nt>w)%H5#JeOX-C);;N9c*!1iAe^`akd0?m`5qwaXZlUIj<pXb6}
zgq?G;VC-Y;-hCK!6nJsw-hpg87xT>Wur(oTM{Nf?9P6g<Ucemu5!NT$Kv$t3cDNC|
zyB at p*{_;ZuISll#j(w{8Fs=qx!Yi;H)^~M~tCgV>As-8&gRa{Z<9Za<r5Hb}or}3}
z7Us{ska_gg4Un&)gJ7rPepkrcZMD7}l!Y#VU3BPP&~<NP-F}oWe7DV?kk$1zN4O8@
z1#JB%*t2;QeQ~VFuWMjUT#qq~zG#Df+!W*Je$3aOK#tzWymtJDus2I!$3qXCi(eJ&
z#$Vrsyg)WS$2xBeY{~N~JXvogj5F9WhaQgoALRAA$CF>t{^8KEBfzhRwnm?J!x|HM
zXX?(FS8j!TKI6#|W1!!*!1y~6wh82V?aqPR4O#9F`Fi;q*f*<VodaB}VBGfq2+ss!
zp54C{bi;!vbF?p4J%PCqboV~flLMYWA7Spi6uNWferO-)-2yc9fxg=H0<4>F1)uJK
zY(i(Bc%CQsWBjb~5pZLC>;@US=z7eRpJ06dgfTM>^H at 2))r~UeK|j}R7RY~Kn at z%a
z9k4t0zuLgIzZ_$BP3+^%_vFG`VYfivbw0_HOIrDI<7x04!W{nns)5`Ny}2gF%G__U
zrr#g>=OFC6-3nRx05;efShsJD_a{TQ4<3lIggNle9WX~g?$!hy-#`znffrCLJOgb#
zA8W at OU@Jpk{0 at C^1o-{kr?8>0HtPBtZ1>sNH^6+>0R8^_O3-x}SI<0!{Xf8deGS&C
zRj`L)51xDz#{FiP&tNZK)z6nr9`<BB_;EP;{>Gi4L-xcv`b+3+=<Y!n&#hZRwlgA!
zv;*GdJh}Y8u!W%$4uLN0 at -z0MuvQ;31kc|<M?41|aosbp-=Bo7@(bn)^zkW|LdH6P
zKNw#>{f7Qn)00O~_RoW`9)c}?I>zVX>pl7MF6=2{KDhQdjG5D+4<5q0a}U_%;M>02
zVSfv2hV{Clzuv$e-9+rw+z*|*Eo8yRoOd>Cmb+kE!KS+dbw3Jy at x$8K3ppJ8IxdjW
zBYm0kJ?!kQFkWB4e#Ih at jmM$j6~2sK0c&;4cbB0rUxs|Ogl*J*Kp<^5 at ns($>%~(s
z-<*PWqHn84dNSoy%tIKnA1uUv1p4;@@b0h%*o!E8BgXLjm(V9|F;*bQH9b9<1-<xr
z27G)Fdh!~y0dsP<iN5eVWqn&<e!*PzH0FZ0U|)9|jkPHH_+5;XhIz0*e#Dsn5%^%E
z4Z at t!`y1>_z6RU!Uf91sL%(c_ISljjGtZ&#!PBS4fflswt5-3W(a#>_^{USUdHz6*
zoiAXku7UA~dGrGGS<At&QQm_6JKvY%x<L=2j$LlU{DpDU^IOOT#{I|8Z$I9IZ(U;?
zUv~ub9_Sl16Jz00$Unxx9<WhnV$Y<{cd$Vr1C{T<e!K#EPOwGiogmU5df`{p`_3*t
zY)_HbLG!2EdUDP?NV^-l5IXH5*o#+S++PMdFNR&a?gH%n!baM5eQYCQe(Cxdbo~w3
zTZK+~;YRFlegk`^J8Y>-Jh}N#*s&PH$AFFz^T3C9vHyngJstAD%WklHPsZ~SZLmjy
z at i*scUk+Rw>$;br2kt=~7(bVu0-oLr+w5UqR>0WU1a{N2d%^aCjWP2&*jj6%k4C^2
zt)b^O_P at GfzhoA8wg%Q<SfkxD3c4D+JoQTGw8wo3&W0 at A1-lHk-`i)Qy>mU8x>#fo
zc>OWPb8qOZi(kew?4OD}+8*QnK<uS9;{87zfqOFSHR!GGus^oh67sb!bQ<()=NHjG
zQ$(&k5py$StM{u|2SP7iF#!8N(0%i(F!sUo^)Rp9_BP&S`5fM#b1-xSWU&$R@=XI_
zdjWPH`fTjZzT8}gwQDDlEd+Z+(C0_>g{_9RY`dB#`+!gFF&-dR!uK0~beG6QkjrzQ
z#D38ko>cdTt&6#8i)%&JdKUKFuD<L7J^kUcpb2wrk3%8PFL=^>HR#zxFpi;9kAw`p
zd^q|K^7Axg`vS<?N;P<1iT#K9`{pO`9Kz9_9QYQ-657puuZxd?Ee`$j>vEVAM#0vE
z?%5nVq!MlKc_H>^!ONp3V2psjn>_`c+!1zgZ(nAh%^g}o2Vadjcn6GewC7pK`zC8+
zKYT-scl6tx0r+t|@XZfo=OM6b(bx}8#`+n3^FHSI6`<EgK#y at PKI9PSYs@kIP{(i8
z*vsD+>$!`er!(-6EyenNIQRqIF&cS4wZL97^zE-3!LHpO?-D&7>y0C^UdY0xI2~i5
z7IRxI=1$=H2zuoBMbKsFpO2o#-2MaX!&k9(=!dnz2Cy6Ng>0MxnZ(@O2%BgA4$#?<
zuM&)dFQDsJc^~iK8xI>~3+NW;_DNZhvn$a4;h2j~fjte~cWzJUheM$wu_n6eCg4~D
zYlKJfZ58lz1oYc-&%<UwnQ8Yy|6?51fxpLM-dgcKAL}8^jl*Hf?SlP$=&UaRcl9<{
zd)^73W9-S5-w2!GOz6x*d}$BZkN&{^*9)+t9>)3*G;OvD)-o8YUt+u*^EB+S_IQ`p
z?-;Z1Vs3+8f;yGE$BA6_AkHrqV&A+iWFGqcY}D^#ZO^@mJ$>vcevSR)7U=7GoLjU3
zzE at DNRLtdd#JK8)b?FM&KP<!kJ3`q9YcR<6$_GO?LBFniK`6)9+>bdF^4#t{*g;*O
z7a;q^tH^;O2masWK-(w#d05gIU9cGA`2>vTma=$p36d6LkB8Uqn1lGkG$2D)H%Wl;
zs3pw%RzfI5pig?GJ_nVlteMm}C4A<|+?MhEOMFJcN11l0lh1n01PW+ulg at W+F}={c
zo}Bjv+9$H=L-g(&1vLk?v96XDr+&ktJL(IN#&@ytJ$SXS&vWnlYJoS&U at fQRO8A^~
z3uwNBG5NVy-n;+u>EN3UEe&mfb4l%*(OA_`IcYAQXf$s<#gh+s*A5#T&xm-~-s0?q
z=Rf%VLcVhmrxG<4=51l&I}MjdT5FjxNz=$zG{o;<V8iw#-eaiT%Wse7*fyEI0)L|Z
z#Qmz47Cz&N72K$*@`~)VnySg!I$1;+!K~qTa_YuAj8bL9yi3a902;vS`_@*#J>Rv)
zcOl06twg#o-9BT~h+ at R?f7(0S5UHv#j$gKYF|v{pbyZ|E!`9VpcXrtpHQI7Dq*k}I
z-LOmRx;t(+XLr__*>#o3UX9YSH?pKx6SD9_5P?)g^eyO97$k at qND+M~qo^-Y|Np(u
z*~Zz~P<I#*{sRwZo_n4-=efW0a_`)8?l~-H)-Jv)^T7n=I6}r)&^Uo$qz5a;^x#X7
z!BP;}?(oII#9(h?#X05eNW>P$!u4jtH_)&*C|-3rpTt`4TII^ttyGx`2D6EDrWGH)
zmxw#zYa)NWvN_>7 at H}`X=b1%`{be1P4L_qcT{ewn!|%^biurbK8{D0Z7+*Z=+q%0z
z^=#zJ#qun!FXY8}P-HX at b(U3~{n9pkVOY3ts`M7%H|#TM<N8eYpYHv}tQ}u~G^_AE
zH_eIDt at 0KjUFU~e({Le<6>e*lUJc at 0f9mWD+g5nBuyyN?7Pi6oFKk>JXL^P0%Do#A
zx4W2i>Oxy?$Ev6{p^Zj<6sbN<!VlJ^25 at 0r%4O)vFTbB`f~_lSS0`LJ{(4yHHN)Pe
z%W|2hY+4X^a8hM6K_7eJZ2qrzJsbIWvE^18A6cf$z>{U_+8MdKG97>YtMG0{Jo|>B
zoW9|fyfj$Oye76n#+P-4cPoxF at 9=lHp1X4Ab(ib7j?cH;Ys2x$wMlmKlkVi(*vC(<
zO%~4&GF%NV`TaZFBFmsK|4MHS8RNG at u!-J7j`pp|T}yX-8B}<8;&-`yzRPFgysEsl
z_>JoaT>7kEh0D3p>p-0A#|zuwIWcTpone}V?aI9kd3G+}{JyFac5balrgd&S=2_sF
zI|p~JE*xLKE4__5`7*tU{PPi)d#>a2#{4GOu&ge#vI_r0 at IuZ{7#FRN?yl3Dag1f^
z(&areuh;Z9yjKl>i*YkcH?&9l&$ZuzxP1G59CJ2|&rOp$-*68QI*z=zaA`2aExET9
z$9OKh|6rYU=~1UW*TJTb)S2F3sQ<U7HSa+fPg|xplo!wAx$)_oc(#Rnf3kV;JSYC1
zwoHE{FP_J9<42*pddRey|M>b)?(M{JSAS^3e8vRl>hfjCm7gDi4f|L;A_Jx9KP%VF
zCNuZnV;6M#60yRZ<?uIU(?YwP@@G7KbM{dl7=MI)yzq4t|4p*ZO+jNk`g1m>qU(!%
zdD47wWz95qn?F(dW!_WJ_u`rK9Q>zWK7esDgo_|oK&l}NAaBpdd>w>)Fz&Y>;j56h
zAg?`-`3wl(ft<mdk8cp3giOV=(Q6^KzhaIT!nu%5kh>v!A?q-fe;DD+qZl(lcm{GB
za?@eVr9gP~Jk+r!T;CARgv^3m2Wf}g4+(bT89TzKP4*!?0C{d9#@Y~`g6zRq!@H38
zAnRsfFAc~($V at y-T?^@goPvB!fgjbg at mv+s0ZBmKgv@WnTzrJbAg3WeLhi+QI`vNn
zF;;@m13!I4Km<fU1VlgtL_h>YKm<fU1VrFcAdox$zYhOrPhbvzRo?jj3Jlg#rr?Cy
zY`PED_rz=gJU3hBccfGO>7Ieu>L8iO#BLaEX|D0Rg2BGj_Dt-KAe-?U>V2$?n;h;-
z;A>rdT|C|#Z>X#HhcQIzV at DgTew(d(fP2MN&X~sk)DS$D at HQ4XkM8YQ12ae=tKY)B
zrXwHDKfq%PJg2FgG1v4TaE{btrvGJn-1L7iKaKIrO+StSwxaQHE at E7XdEAaXI1d5S
z){2<Nj*QPoMj*jF_9A^gOYSlb&zjzB`peK+CfiUZ#XQesuz9R3K1TYSqfl+EKQSFs
zoW1k}^}ufrdef;)YD+fO8DxfglCkyKVHB_*uaC!BEw^AjR4i87lk_`R`WsTIWX5k_
zkFO0)b&V}`jg1YB^?qPAle<sk?8{9qKf?!(wRBw`mG_^fZ!(?p<`^HCKE?Dj^qr;f
z8FLJ<LU}Nd=uV9GCWg2$t7}J#;S1+M)LR)gn2twYVVU1!dcWygO;4NtsOfmzhJC0C
zxAmg(A3KAnA9w@#vpt?d{tsIIZOi=asq|JqnH(7y`?3^!xpIRJzc<-4*zXSy2H7l@
z3D5W&x>oYYhET!6&wUB(shjAFt*ot$v9Qrqar0VqTIpCg=K}SlCS>zD@}7shUpE%V
z%@@3G5yt;v`ab9-VKX|M4X|<14(qr6M*bZCUy1g}dRmT|Sk%A3q^;8UGmscarNedD
znSV9%zaII=&__{UV){$)hx$^}UogGJ^aG}^HvN$4U8Wy_UXt_KG18OFpygPfn?n9e
za6b20c|T_Ud}sb0H2r{G2M(G3is>Jjeh7L={2%2y=7ast|6h<luT^{>kNkf(eU0gl
zV9<i`Rnw#RqozCi&rEmrZLp*L6tmxDy0d at 6bZ0*mv*c($)$F-1eXc*;XP&yVKW6%s
zX8%2OUT-#|ewVl(4fi0z9-Cv=r8w?#TIs9x1#3*NF+E}Wi>5zp`unEuH~mZKt{=<4
zXDVtxYE6^n{vq;S4c|Mh-hO3zpXuM4-gH$|4^EhV1bRt)4Ob(N`um at dH^+%jf>TM_
zj9Xp0CmFU8&Sh^${*R;1=_3LnAOa#F0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F0wN#+
zA|L`HAOa#F0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F0wN#+A|L`H
zAOa#F0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F
z0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F0wN#+
qA|L`HAOa#F0wN#+A|L`HAOa#F0wN#+A|L`HAOa#F0wQo}6ZjW*XSM18
literal 0
HcmV?d00001
More information about the cfe-commits
mailing list