From 3b42c794901e4c10c15eafcf2dae30ab021e76c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20M=C3=BCller?= <mueller@kip.uni-heidelberg.de> Date: Mon, 3 Feb 2025 19:09:15 +0100 Subject: [PATCH] fix(llvm+visionary): port patches to llvm@14:15 --- ...ion-to-keep-whitespace-when-tokenizi.patch | 238 ++++++++++ ...ow-visiting-of-implicit-declarations.patch | 416 ++++++++++++++++++ ...blic-ClangToolingCommonOptionsParser.patch | 12 + packages/llvm/package.py | 8 +- 4 files changed, 673 insertions(+), 1 deletion(-) create mode 100644 packages/llvm/llvm14-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch create mode 100644 packages/llvm/llvm14-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch create mode 100644 packages/llvm/llvm14-public-ClangToolingCommonOptionsParser.patch diff --git a/packages/llvm/llvm14-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch b/packages/llvm/llvm14-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch new file mode 100644 index 00000000..88250852 --- /dev/null +++ b/packages/llvm/llvm14-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch @@ -0,0 +1,238 @@ +diff -pur spack-src/clang/bindings/python/clang/cindex.py spack-src-new/clang/bindings/python/clang/cindex.py +--- spack-src/clang/bindings/python/clang/cindex.py 2022-01-20 22:31:59.000000000 +0100 ++++ spack-src-new/clang/bindings/python/clang/cindex.py 2025-02-03 18:37:54.447765317 +0100 +@@ -529,6 +529,13 @@ class TokenGroup(object): + + You should not instantiate this class outside of this module. + """ ++ ++ # Default tokenization mode. ++ TOKENIZE_NONE = 0 ++ ++ # Used to indicate that tokens for whitespace should be returned. ++ TOKENIZE_KEEP_WHITESPACE = 1 ++ + def __init__(self, tu, memory, count): + self._tu = tu + self._memory = memory +@@ -538,7 +545,7 @@ class TokenGroup(object): + conf.lib.clang_disposeTokens(self._tu, self._memory, self._count) + + @staticmethod +- def get_tokens(tu, extent): ++ def get_tokens(tu, extent, options=0): + """Helper method to return all tokens in an extent. + + This functionality is needed multiple places in this module. We define +@@ -547,8 +554,8 @@ class TokenGroup(object): + tokens_memory = POINTER(Token)() + tokens_count = c_uint() + +- conf.lib.clang_tokenize(tu, extent, byref(tokens_memory), +- byref(tokens_count)) ++ conf.lib.clang_tokenizeRange(tu, extent, byref(tokens_memory), ++ byref(tokens_count), options) + + count = int(tokens_count.value) + +@@ -1875,13 +1882,16 @@ class Cursor(Structure): + for descendant in child.walk_preorder(**kwargs): + yield descendant + +- def get_tokens(self): ++ def get_tokens(self, options=0): + """Obtain Token instances formulating that compose this Cursor. + + This is a generator for Token instances. It returns all tokens which + occupy the extent this cursor occupies. ++ ++ options is a bitwise or of TokenGroup.TOKENIZE_XXX flags which will ++ control tokenization behavior. + """ +- return TokenGroup.get_tokens(self._tu, self.extent) ++ return TokenGroup.get_tokens(self._tu, self.extent, options) + + def get_field_offsetof(self): + """Returns the offsetof the FIELD_DECL pointed by this Cursor.""" +@@ -3105,18 +3115,21 @@ class TranslationUnit(ClangObject): + return CodeCompletionResults(ptr) + return None + +- def get_tokens(self, locations=None, extent=None): ++ def get_tokens(self, locations=None, extent=None, options=0): + """Obtain tokens in this translation unit. + + This is a generator for Token instances. The caller specifies a range + of source code to obtain tokens for. The range can be specified as a + 2-tuple of SourceLocation or as a SourceRange. If both are defined, + behavior is undefined. ++ ++ options is a bitwise or of TokenGroup.TOKENIZE_XXX flags which will ++ control tokenization behavior. + """ + if locations is not None: + extent = SourceRange(start=locations[0], end=locations[1]) + +- return TokenGroup.get_tokens(self, extent) ++ return TokenGroup.get_tokens(self, extent, options) + + class File(ClangObject): + """ +@@ -3957,6 +3983,10 @@ functionList = [ + ("clang_tokenize", + [TranslationUnit, SourceRange, POINTER(POINTER(Token)), POINTER(c_uint)]), + ++ ("clang_tokenizeRange", ++ [TranslationUnit, SourceRange, POINTER(POINTER(Token)), POINTER(c_uint), ++ c_uint]), ++ + ("clang_visitChildren", + [Cursor, callbacks['cursor_visit'], py_object], + c_uint), +diff -pur spack-src/clang/bindings/python/tests/cindex/test_cursor.py spack-src-new/clang/bindings/python/tests/cindex/test_cursor.py +--- spack-src/clang/bindings/python/tests/cindex/test_cursor.py 2022-01-20 22:31:59.000000000 +0100 ++++ spack-src-new/clang/bindings/python/tests/cindex/test_cursor.py 2025-02-03 18:37:54.447765317 +0100 +@@ -10,6 +10,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 +@@ -480,6 +489,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/clang/include/clang-c/Index.h spack-src-new/clang/include/clang-c/Index.h +--- spack-src/clang/include/clang-c/Index.h 2022-01-20 22:31:59.000000000 +0100 ++++ spack-src-new/clang/include/clang-c/Index.h 2025-02-03 18:38:17.919863604 +0100 +@@ -33,7 +33,7 @@ + * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. + */ + #define CINDEX_VERSION_MAJOR 0 +-#define CINDEX_VERSION_MINOR 63 ++#define CINDEX_VERSION_MINOR 64 + + #define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1)) + +@@ -5036,6 +5044,28 @@ CINDEX_LINKAGE CXSourceLocation clang_ge + */ + CINDEX_LINKAGE CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken); + ++typedef enum { ++ /** ++ * \brief Used to indicate that no special tokenization options are needed. ++ */ ++ CXTokenize_None = 0x0, ++ ++ /** ++ * \brief Used to indicate that tokens for whitespace should be returned. ++ */ ++ CXTokenize_KeepWhitespace = 0x1 ++} CXTokenize_Flags; ++ ++/** ++ * \brief Tokenize the source code described by the given range into raw ++ * lexical tokens. ++ * ++ * \see clang_tokenizeRange ++ * ++ */ ++CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, ++ CXToken **Tokens, unsigned *NumTokens); ++ + /** + * Tokenize the source code described by the given range into raw + * lexical tokens. +@@ -5052,9 +5082,13 @@ CINDEX_LINKAGE CXSourceRange clang_getTo + * \param NumTokens will be set to the number of tokens in the \c *Tokens + * array. + * ++ * \param options A bitmask of options that affects tokenization. This should be ++ * a bitwise OR of the CXTokenize_XXX flags. ++ * + */ +-CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, +- CXToken **Tokens, unsigned *NumTokens); ++CINDEX_LINKAGE void clang_tokenizeRange(CXTranslationUnit TU, ++ CXSourceRange Range, CXToken **Tokens, ++ unsigned *NumTokens, unsigned options); + + /** + * Annotate the given set of tokens by providing cursors for each token +diff -pur spack-src/clang/tools/libclang/CIndex.cpp spack-src-new/clang/tools/libclang/CIndex.cpp +--- spack-src/clang/tools/libclang/CIndex.cpp 2022-01-20 22:31:59.000000000 +0100 ++++ spack-src-new/clang/tools/libclang/CIndex.cpp 2025-02-03 18:37:55.855771214 +0100 +@@ -6882,7 +6882,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()); +@@ -6903,6 +6903,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; +@@ -6973,7 +6976,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 NULL; +@@ -6987,6 +6990,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) +@@ -7010,7 +7019,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/clang/tools/libclang/libclang.map spack-src-new/clang/tools/libclang/libclang.map +--- spack-src/clang/tools/libclang/libclang.map 2022-01-20 22:31:59.000000000 +0100 ++++ spack-src-new/clang/tools/libclang/libclang.map 2025-02-03 18:38:37.647946177 +0100 +@@ -398,6 +399,7 @@ LLVM_13 { + clang_suspendTranslationUnit; + clang_toggleCrashRecovery; + clang_tokenize; ++ clang_tokenizeRange; + clang_uninstall_llvm_fatal_error_handler; + clang_visitChildren; + clang_visitChildrenWithBlock; diff --git a/packages/llvm/llvm14-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch b/packages/llvm/llvm14-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch new file mode 100644 index 00000000..1380b699 --- /dev/null +++ b/packages/llvm/llvm14-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch @@ -0,0 +1,416 @@ +diff -pur spack-src/clang/bindings/python/clang/cindex.py spack-src-new/clang/bindings/python/clang/cindex.py +--- spack-src/clang/bindings/python/clang/cindex.py 2025-02-03 18:51:43.871219854 +0100 ++++ spack-src-new/clang/bindings/python/clang/cindex.py 2025-02-03 18:39:41.616213701 +0100 +@@ -1426,6 +1426,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 +@@ -1515,6 +1524,10 @@ class Cursor(Structure): + """ + 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 +@@ -1831,8 +1844,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): +@@ -1845,18 +1862,24 @@ class Cursor(Structure): + children.append(child) + 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): +@@ -3928,6 +3951,10 @@ functionList = [ + [Type], + bool), + ++ ("clang_isImplicit", ++ [Cursor], ++ bool), ++ + ("clang_isInvalid", + [CursorKind], + bool), +@@ -3991,6 +4018,10 @@ functionList = [ + [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), +diff -pur spack-src/clang/bindings/python/tests/cindex/test_cursor.py spack-src-new/clang/bindings/python/tests/cindex/test_cursor.py +--- spack-src/clang/bindings/python/tests/cindex/test_cursor.py 2025-02-03 18:51:43.871219854 +0100 ++++ spack-src-new/clang/bindings/python/tests/cindex/test_cursor.py 2025-02-03 18:39:41.616213701 +0100 +@@ -94,6 +94,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/clang/include/clang-c/Index.h spack-src-new/clang/include/clang-c/Index.h +--- spack-src/clang/include/clang-c/Index.h 2025-02-03 18:51:43.871219854 +0100 ++++ spack-src-new/clang/include/clang-c/Index.h 2025-02-03 18:40:48.276492163 +0100 +@@ -33,7 +33,7 @@ + * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. + */ + #define CINDEX_VERSION_MAJOR 0 +-#define CINDEX_VERSION_MINOR 64 ++#define CINDEX_VERSION_MINOR 65 + + #define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1)) + +@@ -2817,6 +2817,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. + */ +@@ -4274,6 +4279,32 @@ clang_visitChildrenWithBlock(CXCursor pa + #endif + #endif + ++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); ++ + /** + * @} + */ +diff -pur spack-src/clang/tools/libclang/CIndex.cpp spack-src-new/clang/tools/libclang/CIndex.cpp +--- spack-src/clang/tools/libclang/CIndex.cpp 2025-02-03 18:51:43.871219854 +0100 ++++ spack-src-new/clang/tools/libclang/CIndex.cpp 2025-02-03 18:39:43.000219486 +0100 +@@ -203,10 +203,11 @@ 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)) +- return false; ++ // 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; + } + + // If we have a range of interest, and this cursor doesn't intersect with it, +@@ -713,10 +715,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; + +@@ -725,6 +730,7 @@ bool CursorVisitor::VisitClassTemplateSp + break; + + case TSK_ExplicitSpecialization: ++ // Always visit body of explicit specializations + ShouldVisitBody = true; + break; + } +@@ -945,7 +951,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) { +@@ -955,7 +985,40 @@ bool CursorVisitor::VisitClassTemplateDe + return true; + + 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) { +@@ -4596,6 +4659,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(); +@@ -5983,6 +6064,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/clang/tools/libclang/CursorVisitor.h spack-src-new/clang/tools/libclang/CursorVisitor.h +--- spack-src/clang/tools/libclang/CursorVisitor.h 2022-01-20 22:31:59.000000000 +0100 ++++ spack-src-new/clang/tools/libclang/CursorVisitor.h 2025-02-03 18:39:43.000219486 +0100 +@@ -104,6 +104,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; +@@ -152,12 +158,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; +diff -pur spack-src/clang/tools/libclang/libclang.map spack-src-new/clang/tools/libclang/libclang.map +--- spack-src/clang/tools/libclang/libclang.map 2025-02-03 18:51:43.871219854 +0100 ++++ spack-src-new/clang/tools/libclang/libclang.map 2025-02-03 18:40:21.600380765 +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: *; + }; diff --git a/packages/llvm/llvm14-public-ClangToolingCommonOptionsParser.patch b/packages/llvm/llvm14-public-ClangToolingCommonOptionsParser.patch new file mode 100644 index 00000000..7641f8a3 --- /dev/null +++ b/packages/llvm/llvm14-public-ClangToolingCommonOptionsParser.patch @@ -0,0 +1,12 @@ +diff -pur spack-src/clang/include/clang/Tooling/CommonOptionsParser.h spack-src-new/clang/include/clang/Tooling/CommonOptionsParser.h +--- spack-src/clang/include/clang/Tooling/CommonOptionsParser.h 2025-02-17 12:35:27.296733912 +0100 ++++ spack-src-new/clang/include/clang/Tooling/CommonOptionsParser.h 2025-02-17 12:35:59.393070972 +0100 +@@ -64,7 +64,7 @@ namespace tooling { + /// \endcode + class CommonOptionsParser { + +-protected: ++public: + /// Parses command-line, initializes a compilation database. + /// + /// This constructor can change argc and argv contents, e.g. consume diff --git a/packages/llvm/package.py b/packages/llvm/package.py index 80e72b37..1af09da1 100644 --- a/packages/llvm/package.py +++ b/packages/llvm/package.py @@ -395,7 +395,7 @@ class Llvm(CMakePackage, CudaPackage): "bindings generator") conflicts("@:8", when="+visionary") - conflicts("@14:", when="+visionary") + conflicts("@16:", when="+visionary") patch('llvm9-0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch', when='@9:12 +visionary', level=2) @@ -416,7 +416,13 @@ class Llvm(CMakePackage, CudaPackage): patch('llvm13-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch', when='@13 +visionary', level=1) patch('llvm13-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch', when='@13 +visionary', level=1) # 0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch from above + + # 0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch from above + # 0002-libclang-Add-support-for-obtaining-fully-qualified-n.patch from above + patch('llvm14-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch', when='@14:15 +visionary', level=1) + patch('llvm14-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch', when='@14:15 +visionary', level=1) # 0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch from above + patch('llvm14-public-ClangToolingCommonOptionsParser.patch', when='@14: +visionary', level=1) # disable check for member `mode` size in `struct ipc_perm`; newer glibc changed width patch('llvm9-disable-check-for-ipc_perm-mode.patch', when='@9.0.0:9.0.999', level=2) -- GitLab