[clang] Dev trunk (PR #90590)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 30 03:53:07 PDT 2024
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
More information about the cfe-commits
mailing list