[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