diff -pur spack-src-newer/clang/bindings/python/clang/cindex.py spack-src-newerst/clang/bindings/python/clang/cindex.py
--- spack-src-newer/clang/bindings/python/clang/cindex.py	2025-02-03 19:37:00.122475192 +0100
+++ spack-src-newerst/clang/bindings/python/clang/cindex.py	2025-02-03 19:42:19.199796814 +0100
@@ -1463,6 +1463,15 @@ class Cursor(Structure):
 
     _fields_ = [("_kind_id", c_int), ("xdata", c_int), ("data", c_void_p * 3)]
 
+    # Default behavior.
+    GET_CHILDREN_NONE = 0
+
+    # Used to indicate that implicit cursors should be visited.
+    GET_CHILDREN_WITH_IMPLICIT = 1
+
+    # Used to indicate that template instantiations should be visited.
+    GET_CHILDREN_WITH_TEMPLATE_INSTANTIATIONS = 2
+
     @staticmethod
     def from_location(tu, location):
         # We store a reference to the TU in the instance so the TU won't get
@@ -1648,6 +1657,10 @@ class Cursor(Structure):
         """Returns True if the cursor refers to a scoped enum declaration."""
         return conf.lib.clang_EnumDecl_isScoped(self)
 
+    def is_implicit(self):
+        """Test whether the cursor refers to an implicit declaration."""
+        return conf.lib.clang_isImplicit(self)
+
     def get_definition(self):
         """
         If the cursor is a reference to a declaration or a declaration of
@@ -1965,8 +1978,12 @@ class Cursor(Structure):
         """Returns the value of the indicated arg as an unsigned 64b integer."""
         return conf.lib.clang_Cursor_getTemplateArgumentUnsignedValue(self, num)
 
-    def get_children(self):
-        """Return an iterator for accessing the children of this cursor."""
+    def get_children(self, with_implicit=False, with_template_instantiations=False):
+        """Return an iterator for accessing the children of this cursor.
+
+        By default, cursors representing implicit declarations or template instantiations
+        will be skipped.
+        """
 
         # FIXME: Expose iteration from CIndex, PR6125.
         def visitor(child, parent, children):
@@ -1980,17 +1997,24 @@ class Cursor(Structure):
             return 1  # continue
 
         children = []
-        conf.lib.clang_visitChildren(self, callbacks["cursor_visit"](visitor), children)
+        dispatch = conf.lib.clang_visitChildren
+        options = Cursor.GET_CHILDREN_NONE
+        if with_implicit:
+            options |= Cursor.GET_CHILDREN_WITH_IMPLICIT
+        if with_template_instantiations:
+            options |= Cursor.GET_CHILDREN_WITH_TEMPLATE_INSTANTIATIONS
+        conf.lib.clang_visitChildrenWithOptions(
+            self, callbacks['cursor_visit'](visitor), children, options)
         return iter(children)
 
-    def walk_preorder(self):
+    def walk_preorder(self, **kwargs):
         """Depth-first preorder walk over the cursor and its descendants.
 
         Yields cursors.
         """
         yield self
-        for child in self.get_children():
-            for descendant in child.walk_preorder():
+        for child in self.get_children(**kwargs):
+            for descendant in child.walk_preorder(**kwargs):
                 yield descendant
 
     def get_tokens(self, options=0):
@@ -3783,6 +3807,7 @@ functionList = [
     ("clang_isExpression", [CursorKind], bool),
     ("clang_isFileMultipleIncludeGuarded", [TranslationUnit, File], bool),
     ("clang_isFunctionTypeVariadic", [Type], bool),
+    ("clang_isImplicit", [Cursor], bool),
     ("clang_isInvalid", [CursorKind], bool),
     ("clang_isPODType", [Type], bool),
     ("clang_isPreprocessing", [CursorKind], bool),
@@ -3810,6 +3835,11 @@ functionList = [
         c_uint]
     ),
     ("clang_visitChildren", [Cursor, callbacks["cursor_visit"], py_object], c_uint),
+    (
+        "clang_visitChildrenWithOptions",
+        [Cursor, callbacks['cursor_visit'], py_object, c_uint],
+        c_uint
+    ),
     ("clang_Cursor_getNumArguments", [Cursor], c_int),
     ("clang_Cursor_getArgument", [Cursor, c_uint], Cursor, Cursor.from_result),
     ("clang_Cursor_getNumTemplateArguments", [Cursor], c_int),
diff -pur spack-src-newer/clang/bindings/python/tests/cindex/test_cursor.py spack-src-newerst/clang/bindings/python/tests/cindex/test_cursor.py
--- spack-src-newer/clang/bindings/python/tests/cindex/test_cursor.py	2025-02-03 19:34:29.005849262 +0100
+++ spack-src-newerst/clang/bindings/python/tests/cindex/test_cursor.py	2025-02-03 19:38:51.074934760 +0100
@@ -96,6 +96,39 @@ class TestCursor(unittest.TestCase):
         self.assertEqual(tu_nodes[2].displayname, "f0(int, int)")
         self.assertEqual(tu_nodes[2].is_definition(), True)
 
+    def test_get_children_with_implicit():
+        tu = get_tu('struct X {}; X x;', lang='cpp')
+        cursor = get_cursor(tu, 'X')
+
+        children = list(cursor.get_children())
+        self.assertEqual(len(children), 0, [(c.kind, c.spelling) for c in children])
+
+        children = list(cursor.get_children(with_implicit=True))
+        self.assertNotEqual(len(children), 0)
+        for child in children:
+            self.assertTrue(child.is_implicit())
+            self.assertEqual(child.spelling, "X")
+            self.assertIn(child.kind, [CursorKind.CONSTRUCTOR, CursorKind.STRUCT_DECL])
+
+    def test_get_children_with_template_instantiations():
+        tu = get_tu(
+            'template <typename T> T frobnicate(T val);'
+            'extern template int frobnicate<int>(int);',
+            lang='cpp')
+        cursor = get_cursor(tu, 'frobnicate')
+        self.assertEqual(cursor.kind, CursorKind.FUNCTION_TEMPLATE)
+
+        for child in cursor.get_children():
+            # should not return an instantiation:
+            self.assertNotEqual(child.kind, CursorKind.FUNCTION_DECL)
+
+        for child in cursor.get_children(with_template_instantiations=True):
+            if child.kind == CursorKind.FUNCTION_DECL:
+                self.assertEqual(child.spelling, 'frobnicate')
+                break
+        else:
+            self.fail("Couldn't find template instantiation")
+
     def test_references(self):
         """Ensure that references to TranslationUnit are kept."""
         tu = get_tu("int x;")
diff -pur spack-src-newer/clang/bindings/python/tests/cindex/test_cursor.py.orig spack-src-newerst/clang/bindings/python/tests/cindex/test_cursor.py.orig
--- spack-src-newer/clang/bindings/python/tests/cindex/test_cursor.py.orig	2025-02-03 19:30:48.340935255 +0100
+++ spack-src-newerst/clang/bindings/python/tests/cindex/test_cursor.py.orig	2025-02-03 19:34:29.005849262 +0100
@@ -11,6 +11,7 @@ import unittest
 from clang.cindex import AvailabilityKind
 from clang.cindex import CursorKind
 from clang.cindex import TemplateArgumentKind
+from clang.cindex import TokenGroup
 from clang.cindex import TranslationUnit
 from clang.cindex import TypeKind
 from .util import get_cursor
@@ -608,6 +609,14 @@ class TestCursor(unittest.TestCase):
         self.assertEqual(tokens[0].spelling, "int")
         self.assertEqual(tokens[1].spelling, "foo")
 
+    def test_get_tokens_with_whitespace():
+        source = 'class C { void f(); }\nvoid C::f() { }'
+        tu = get_tu(source)
+
+        tokens = list(tu.cursor.get_tokens(TokenGroup.TOKENIZE_KEEP_WHITESPACE))
+        self.assertEqual(''.join(t.spelling for t in tokens), source)
+        self.assertEqual(len(tokens), 27, [t.spelling for t in tokens])
+
     def test_get_token_cursor(self):
         """Ensure we can map tokens to cursors."""
         tu = get_tu("class A {}; int foo(A var = A());", lang="cpp")
diff -pur spack-src-newer/clang/include/clang-c/Index.h spack-src-newerst/clang/include/clang-c/Index.h
--- spack-src-newer/clang/include/clang-c/Index.h	2025-02-03 19:37:22.846569316 +0100
+++ spack-src-newerst/clang/include/clang-c/Index.h	2025-02-03 19:39:20.307055840 +0100
@@ -34,7 +34,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 66
+#define CINDEX_VERSION_MINOR 67
 
 #define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1))
 
@@ -2366,6 +2366,11 @@ CINDEX_LINKAGE unsigned clang_isPreproce
  */
 CINDEX_LINKAGE unsigned clang_isUnexposed(enum CXCursorKind);
 
+/***
+ * \brief Determine whether the given cursor represents an implicit declaration.
+ */
+CINDEX_LINKAGE unsigned clang_isImplicit(CXCursor);
+
 /**
  * Describe the linkage of the entity referred to by a cursor.
  */
@@ -3827,6 +3832,32 @@ enum CXChildVisitResult {
   CXChildVisit_Recurse
 };
 
+typedef enum {
+  /**
+   * \brief Default behavior.
+   */
+  CXVisitChildren_None = 0x0,
+
+  /**
+   * \brief Used to indicate that implicit cursors should be visited.
+   */
+  CXVisitChildren_WithImplicit = 0x1,
+
+  /**
+   * \brief Used to indicate that template instantiations should be visited.
+   */
+  CXVisitChildren_WithTemplateInstantiations = 0x2
+} CXVisitChildren_Flags;
+
+/**
+ * \brief Visits the children of a cursor, allowing to pass extra options.
+ * Behaves identically to clang_visitChildren() in all other respects.
+ */
+CINDEX_LINKAGE unsigned clang_visitChildrenWithOptions(CXCursor parent,
+                                                       CXCursorVisitor visitor,
+                                                       CXClientData client_data,
+                                                       unsigned options);
+
 /**
  * Visitor invoked for each cursor found by a traversal.
  *
diff -pur spack-src-newer/clang/tools/libclang/CIndex.cpp spack-src-newerst/clang/tools/libclang/CIndex.cpp
--- spack-src-newer/clang/tools/libclang/CIndex.cpp	2025-02-03 19:34:29.861852808 +0100
+++ spack-src-newerst/clang/tools/libclang/CIndex.cpp	2025-02-03 19:38:52.634941222 +0100
@@ -207,9 +207,10 @@ bool CursorVisitor::Visit(CXCursor Curso
       return true; // abort.
     }
 
-    // Ignore implicit declarations, unless it's an objc method because
-    // currently we should report implicit methods for properties when indexing.
-    if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
+    // Unless instructed otherwise we ignore implicit declarations.
+    // ObjC methods are currently visited in any case, because implicit methods
+    // for properties should be reported when indexing.
+    if (!VisitImplicitDeclarations && D->isImplicit() && !isa<ObjCMethodDecl>(D))
       return false;
   }
 
@@ -717,10 +718,13 @@ bool CursorVisitor::VisitTagDecl(TagDecl
 
 bool CursorVisitor::VisitClassTemplateSpecializationDecl(
     ClassTemplateSpecializationDecl *D) {
-  bool ShouldVisitBody = false;
+  bool ShouldVisitBody = VisitTemplateInstantiations;
   switch (D->getSpecializationKind()) {
-  case TSK_Undeclared:
   case TSK_ImplicitInstantiation:
+    if (VisitTemplateInstantiations && VisitImplicitDeclarations) {
+      break;
+    }
+  case TSK_Undeclared:
     // Nothing to visit
     return false;
 
@@ -729,6 +733,7 @@ bool CursorVisitor::VisitClassTemplateSp
     break;
 
   case TSK_ExplicitSpecialization:
+    // Always visit body of explicit specializations
     ShouldVisitBody = true;
     break;
   }
@@ -954,7 +959,31 @@ bool CursorVisitor::VisitFunctionTemplat
     return true;
 
   auto *FD = D->getTemplatedDecl();
-  return VisitAttributes(FD) || VisitFunctionDecl(FD);
+  if (VisitAttributes(FD) || VisitFunctionDecl(FD))
+    return true;
+
+  if (VisitTemplateInstantiations && D == D->getCanonicalDecl()) {
+    for (auto *FD : D->specializations()) {
+      for (auto *RD : FD->redecls()) {
+        switch (RD->getTemplateSpecializationKind()) {
+        case TSK_Undeclared:
+        case TSK_ImplicitInstantiation:
+        case TSK_ExplicitInstantiationDeclaration:
+        case TSK_ExplicitInstantiationDefinition: {
+          const Optional<bool> V = handleDeclForVisitation(RD);
+          if (!V.hasValue())
+            continue;
+          return V.getValue();
+        }
+
+        case TSK_ExplicitSpecialization:
+          break;
+        }
+      }
+    }
+  }
+
+  return false;
 }
 
 bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
@@ -965,6 +994,40 @@ bool CursorVisitor::VisitClassTemplateDe
 
   auto *CD = D->getTemplatedDecl();
   return VisitAttributes(CD) || VisitCXXRecordDecl(CD);
+  if (VisitAttributes(CD) || VisitCXXRecordDecl(CD))
+    return true;
+
+  if (VisitTemplateInstantiations && D == D->getCanonicalDecl()) {
+    for (auto *SD : D->specializations()) {
+      for (auto *RD : SD->redecls()) {
+        // We don't want to visit injected-class-names in this traversal.
+        if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
+          continue;
+
+        switch (
+            cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
+          // Visit the implicit instantiations with the requested pattern.
+        case TSK_Undeclared:
+        case TSK_ImplicitInstantiation: {
+          const Optional<bool> V = handleDeclForVisitation(RD);
+          if (!V.hasValue())
+            continue;
+          return V.getValue();
+        }
+
+          // We don't need to do anything on an explicit instantiation
+          // or explicit specialization because there will be an explicit
+          // node for it elsewhere.
+        case TSK_ExplicitInstantiationDeclaration:
+        case TSK_ExplicitInstantiationDefinition:
+        case TSK_ExplicitSpecialization:
+          break;
+        }
+      }
+    }
+  }
+
+  return false;
 }
 
 bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
@@ -4877,6 +4940,24 @@ unsigned clang_visitChildrenWithBlock(CX
   return clang_visitChildren(parent, visitWithBlock, block);
 }
 
+unsigned clang_visitChildrenWithOptions(CXCursor parent,
+                                        CXCursorVisitor visitor,
+                                        CXClientData client_data,
+                                        unsigned options) {
+  CursorVisitor CursorVis(
+      getCursorTU(parent), visitor, client_data,
+      /*VisitPreprocessorLast=*/false,
+      /*VisitIncludedPreprocessingEntries=*/false,
+      /*RegionOfInterest=*/SourceRange(),
+      /*VisitDeclsOnly=*/false,
+      /*PostChildrenVisitor=*/nullptr,
+      /*VisitImplicitDeclarations=*/(options & CXVisitChildren_WithImplicit),
+      /*VisitTemplateInstantiations=*/
+      (options & CXVisitChildren_WithTemplateInstantiations));
+
+  return CursorVis.VisitChildren(parent);
+}
+
 static CXString getDeclSpelling(const Decl *D) {
   if (!D)
     return cxstring::createEmpty();
@@ -6296,6 +6377,22 @@ unsigned clang_isUnexposed(enum CXCursor
   }
 }
 
+unsigned clang_isImplicit(CXCursor Cursor) {
+  if (clang_isInvalid(Cursor.kind))
+    return false;
+
+  if (!clang_isDeclaration(Cursor.kind))
+    return false;
+
+  const Decl *D = getCursorDecl(Cursor);
+  if (!D) {
+    assert(0 && "Invalid declaration cursor");
+    return true; // abort.
+  }
+
+  return D->isImplicit();
+}
+
 CXCursorKind clang_getCursorKind(CXCursor C) { return C.kind; }
 
 CXSourceLocation clang_getCursorLocation(CXCursor C) {
diff -pur spack-src-newer/clang/tools/libclang/CIndex.cpp.orig spack-src-newerst/clang/tools/libclang/CIndex.cpp.orig
--- spack-src-newer/clang/tools/libclang/CIndex.cpp.orig	2023-10-31 09:00:30.000000000 +0100
+++ spack-src-newerst/clang/tools/libclang/CIndex.cpp.orig	2025-02-03 19:34:29.861852808 +0100
@@ -7199,7 +7199,7 @@ CXSourceRange clang_getTokenExtent(CXTra
 }
 
 static void getTokens(ASTUnit *CXXUnit, SourceRange Range,
-                      SmallVectorImpl<CXToken> &CXTokens) {
+                      SmallVectorImpl<CXToken> &CXTokens, unsigned options) {
   SourceManager &SourceMgr = CXXUnit->getSourceManager();
   std::pair<FileID, unsigned> BeginLocInfo =
       SourceMgr.getDecomposedSpellingLoc(Range.getBegin());
@@ -7220,6 +7220,9 @@ static void getTokens(ASTUnit *CXXUnit,
             CXXUnit->getASTContext().getLangOpts(), Buffer.begin(),
             Buffer.data() + BeginLocInfo.second, Buffer.end());
   Lex.SetCommentRetentionState(true);
+  if (options & CXTokenize_KeepWhitespace) {
+    Lex.SetKeepWhitespaceMode(true);
+  }
 
   // Lex tokens until we hit the end of the range.
   const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second;
@@ -7290,7 +7293,7 @@ CXToken *clang_getToken(CXTranslationUni
       SM.getComposedLoc(DecomposedEnd.first, DecomposedEnd.second);
 
   SmallVector<CXToken, 32> CXTokens;
-  getTokens(CXXUnit, SourceRange(Begin, End), CXTokens);
+  getTokens(CXXUnit, SourceRange(Begin, End), CXTokens, CXTokenize_None);
 
   if (CXTokens.empty())
     return nullptr;
@@ -7304,6 +7307,12 @@ CXToken *clang_getToken(CXTranslationUni
 
 void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXToken **Tokens,
                     unsigned *NumTokens) {
+  return clang_tokenizeRange(TU, Range, Tokens, NumTokens, CXTokenize_None);
+}
+
+void clang_tokenizeRange(CXTranslationUnit TU, CXSourceRange Range,
+                         CXToken **Tokens, unsigned *NumTokens,
+                         unsigned options) {
   LOG_FUNC_SECTION { *Log << TU << ' ' << Range; }
 
   if (Tokens)
@@ -7327,7 +7336,7 @@ void clang_tokenize(CXTranslationUnit TU
     return;
 
   SmallVector<CXToken, 32> CXTokens;
-  getTokens(CXXUnit, R, CXTokens);
+  getTokens(CXXUnit, R, CXTokens, options);
 
   if (CXTokens.empty())
     return;
diff -pur spack-src-newer/clang/tools/libclang/CursorVisitor.h spack-src-newerst/clang/tools/libclang/CursorVisitor.h
--- spack-src-newer/clang/tools/libclang/CursorVisitor.h	2023-10-31 09:00:30.000000000 +0100
+++ spack-src-newerst/clang/tools/libclang/CursorVisitor.h	2025-02-03 19:38:52.634941222 +0100
@@ -111,6 +111,12 @@ private:
   /// record entries.
   bool VisitDeclsOnly;
 
+  /// \brief Whether we should visit implicit declarations.
+  bool VisitImplicitDeclarations;
+
+  /// \brief Whether we should recurse into template instantiations.
+  bool VisitTemplateInstantiations;
+
   // FIXME: Eventually remove.  This part of a hack to support proper
   // iteration over all Decls contained lexically within an ObjC container.
   DeclContext::decl_iterator *DI_current;
@@ -159,12 +165,16 @@ public:
                 bool VisitIncludedPreprocessingEntries = false,
                 SourceRange RegionOfInterest = SourceRange(),
                 bool VisitDeclsOnly = false,
-                PostChildrenVisitorTy PostChildrenVisitor = nullptr)
+                PostChildrenVisitorTy PostChildrenVisitor = nullptr,
+                bool VisitImplicitDeclarations = false,
+                bool VisitTemplateInstantiations = false)
       : TU(TU), AU(cxtu::getASTUnit(TU)), Visitor(Visitor),
         PostChildrenVisitor(PostChildrenVisitor), ClientData(ClientData),
         VisitPreprocessorLast(VisitPreprocessorLast),
         VisitIncludedEntities(VisitIncludedPreprocessingEntries),
         RegionOfInterest(RegionOfInterest), VisitDeclsOnly(VisitDeclsOnly),
+        VisitImplicitDeclarations(VisitImplicitDeclarations),
+        VisitTemplateInstantiations(VisitTemplateInstantiations),
         DI_current(nullptr), FileDI_current(nullptr) {
     Parent.kind = CXCursor_NoDeclFound;
     Parent.data[0] = nullptr;
Only in spack-src-newerst/clang/tools/libclang: CursorVisitor.h.orig
diff -pur spack-src-newer/clang/tools/libclang/libclang.map spack-src-newerst/clang/tools/libclang/libclang.map
--- spack-src-newer/clang/tools/libclang/libclang.map	2025-02-03 19:34:29.861852808 +0100
+++ spack-src-newerst/clang/tools/libclang/libclang.map	2025-02-03 19:38:52.634941222 +0100
@@ -375,6 +375,7 @@ LLVM_13 {
     clang_isExpression;
     clang_isFileMultipleIncludeGuarded;
     clang_isFunctionTypeVariadic;
+    clang_isImplicit;
     clang_isInvalid;
     clang_isInvalidDeclaration;
     clang_isPODType;
@@ -403,6 +404,7 @@ LLVM_13 {
     clang_uninstall_llvm_fatal_error_handler;
     clang_visitChildren;
     clang_visitChildrenWithBlock;
+    clang_visitChildrenWithOptions;
 
   local: *;
 };