llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (yash-kumar8) <details> <summary>Changes</summary> Fix endline comment alignment, inline constructor definition alignment, variable name alignment with bit field --- Patch is 197.17 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/90590.diff 28 Files Affected: - (modified) clang/include/clang/Format/Format.h (+7-2) - (modified) clang/lib/Format/ContinuationIndenter.cpp (+27-1) - (modified) clang/lib/Format/Format.cpp (+4) - (modified) clang/lib/Format/FormatToken.cpp (+94-1) - (modified) clang/lib/Format/FormatToken.h (+859-1) - (modified) clang/lib/Format/FormatTokenLexer.cpp (+2) - (modified) clang/lib/Format/TokenAnnotator.cpp (+632-4) - (modified) clang/lib/Format/TokenAnnotator.h (+100-2) - (modified) clang/lib/Format/UnwrappedLineFormatter.cpp (+125-9) - (modified) clang/lib/Format/UnwrappedLineParser.cpp (+17) - (modified) clang/lib/Format/WhitespaceManager.cpp (+1238-5) - (modified) clang/lib/Format/WhitespaceManager.h (+62) - (modified) clang/tools/clang-format/ClangFormat.cpp (+179) - (modified) clang/unittests/CMakeLists.txt (+1) - (added) clang/unittests/TWClangFormat/CMakeLists.txt (+15) - (added) clang/unittests/TWClangFormat/DummyTest.cpp (+45) - (added) clang/unittests/TWClangFormat/FormatTestBase.h (+179) - (added) clang/unittests/TWClangFormat/FormatTestUtils.h (+74) - (added) clang/unittests/TWClangFormat/TWClangTests.vcxproj (+139) - (added) clang/unittests/TWClangFormat/TWClangTests.vcxproj.filters (+25) - (added) clang/unittests/TWClangFormat/TWClangTests.vcxproj.user (+4) - (added) clang/unittests/TWClangFormat/TestLexer.h (+122) - (added) clang/unittests/TWClangFormat/x64/Debug/TWClangTests.log (+357) - (added) clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/CL.command.1.tlog (+1) - (added) clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/TWClangTests.lastbuildstate (+2) - (added) clang/unittests/TWClangFormat/x64/Debug/TWClangTests.tlog/unsuccessfulbuild () - (added) clang/unittests/TWClangFormat/x64/Debug/vc143.idb () - (added) clang/unittests/TWClangFormat/x64/Debug/vc143.pdb () ``````````diff diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index e9b2160a7b9243..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, @@ -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 @@ -5272,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/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..6af05765d0d561 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,800 @@ 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::identi... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/90590 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits