Skip to content
Snippets Groups Projects
Commit 3d4e0591 authored by Eric Müller's avatar Eric Müller :mountain_bicyclist: Committed by Eleni Mathioulaki
Browse files

fix(llvm+visionary): port patches to llvm@13

parent cccf2330
No related branches found
No related tags found
2 merge requests!651create new experimental release,!629Fix newer llvm
diff -pur spack-src/clang/unittests/Tooling/QualTypeNamesTest.cpp spack-src-new/clang/unittests/Tooling/QualTypeNamesTest.cpp
--- spack-src/clang/unittests/Tooling/QualTypeNamesTest.cpp 2022-01-20 22:31:59.000000000 +0100
+++ spack-src-new/clang/unittests/Tooling/QualTypeNamesTest.cpp 2025-02-03 18:25:49.156686779 +0100
@@ -66,6 +66,10 @@ TEST(QualTypeNameTest, getFullyQualified
// Template parameter expansion.
Visitor.ExpectedQualTypeNames["CheckC"] =
"A::B::Template0<A::B::C::MyInt, A::B::AnotherClass>";
+ // Template parameters of nested name specifier should also be fully expanded.
+ Visitor.ExpectedQualTypeNames["CheckNested"] =
+ // "typename A::B::Template0<A::B::C::MyInt, A::B::AnotherClass>::nested";
+ "typename A::B::Template0<int, A::B::Class0>::nested";
// Recursive template parameter expansion.
Visitor.ExpectedQualTypeNames["CheckD"] =
"A::B::Template0<A::B::Template1<A::B::C::MyInt, A::B::AnotherClass>, "
@@ -111,7 +115,7 @@ TEST(QualTypeNameTest, getFullyQualified
" InnerAlias<int> AliasTypeVal;\n"
" InnerAlias<Class0>::Inner AliasInnerTypeVal;\n"
" }\n"
- " template<class X, class Y> class Template0;"
+ " template<class X, class Y> struct Template0 { typedef int nested; };"
" template<class X, class Y> class Template1;"
" typedef B::Class0 AnotherClass;\n"
" void Function1(Template0<C::MyInt,\n"
@@ -119,6 +123,8 @@ TEST(QualTypeNameTest, getFullyQualified
" void Function2(Template0<Template1<C::MyInt, AnotherClass>,\n"
" Template0<int, long> > CheckD);\n"
" void Function3(const B::Class0* CheckM);\n"
+ " void Function4(typename Template0<C::MyInt,\n"
+ " AnotherClass>::nested CheckNested);\n"
" }\n"
"template<typename... Values> class Variadic {};\n"
"Variadic<int, B::Template0<int, char>, "
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:35:08.767069975 +0100
@@ -2428,6 +2428,14 @@ class Type(Structure):
"""Retrieve the spelling of this Type."""
return conf.lib.clang_getTypeSpelling(self)
+ @property
+ def fully_qualified_name(self):
+ """Retrieve the fully qualified name of this Type."""
+ if not hasattr(self, '_fully_qualified_name'):
+ self._fully_qualified_name = conf.lib.clang_getFullyQualifiedTypeName(self)
+
+ return self._fully_qualified_name
+
def __eq__(self, other):
if type(other) != type(self):
return False
@@ -3869,6 +3877,11 @@ functionList = [
[Type],
_CXString,
_CXString.from_result),
+
+ ("clang_getFullyQualifiedTypeName",
+ [Type],
+ _CXString,
+ _CXString.from_result),
("clang_hashCursor",
[Cursor],
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:35:08.767069975 +0100
@@ -316,6 +316,14 @@ class TestCursor(unittest.TestCase):
underlying = typedef.underlying_typedef_type
self.assertEqual(underlying.kind, TypeKind.INT)
+ def test_fully_qualified_type_name():
+ source = 'namespace uiae { struct X { typedef int sometype; }; }'
+ tu = get_tu(source, lang='cpp')
+
+ cls = get_cursor(tu, 'sometype')
+ fqn = cls.type.fully_qualified_name
+ self.assertTrue(fqn.endswith("uiae::X::sometype"), fqn)
+
def test_semantic_parent(self):
tu = get_tu(kParentTest, 'cpp')
curs = get_cursors(tu, 'f')
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:35:52.971255790 +0100
@@ -33,7 +33,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 62
+#define CINDEX_VERSION_MINOR 63
#define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1))
@@ -3447,6 +3447,14 @@ CINDEX_LINKAGE CXType clang_getCursorTyp
CINDEX_LINKAGE CXString clang_getTypeSpelling(CXType CT);
/**
+ * Retrieve the fully qualified name of the underlying type.
+ * This includes full qualification of all template parameters etc.
+ *
+ * If the type is invalid, an empty string is returned.
+ */
+CINDEX_LINKAGE CXString clang_getFullyQualifiedTypeName(CXType CT);
+
+/**
* Retrieve the underlying type of a typedef declaration.
*
* If the cursor does not reference a typedef declaration, an invalid type is
diff -pur spack-src/clang/tools/libclang/CMakeLists.txt spack-src-new/clang/tools/libclang/CMakeLists.txt
--- spack-src/clang/tools/libclang/CMakeLists.txt 2022-01-20 22:31:59.000000000 +0100
+++ spack-src-new/clang/tools/libclang/CMakeLists.txt 2025-02-03 18:35:11.263080474 +0100
@@ -52,6 +52,7 @@ set(LIBS
clangSema
clangSerialization
clangTooling
+ clangToolingCore
)
if (CLANG_ENABLE_ARCMT)
diff -pur spack-src/clang/tools/libclang/CXType.cpp spack-src-new/clang/tools/libclang/CXType.cpp
--- spack-src/clang/tools/libclang/CXType.cpp 2022-01-20 22:31:59.000000000 +0100
+++ spack-src-new/clang/tools/libclang/CXType.cpp 2025-02-03 18:35:11.263080474 +0100
@@ -19,6 +19,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/QualTypeNames.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Frontend/ASTUnit.h"
@@ -303,6 +304,27 @@ CXString clang_getTypeSpelling(CXType CT
return cxstring::createDup(OS.str());
}
+CXString clang_getFullyQualifiedTypeName(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return cxstring::createEmpty();
+
+ // For builtin types (but not typedefs pointing to builtin types) return their
+ // spelling. Otherwise "bool" will be turned into "_Bool".
+ const Type *TP = T.getTypePtrOrNull();
+ if (TP && TP->isBuiltinType() && T->getAs<TypedefType>() == nullptr)
+ return clang_getTypeSpelling(CT);
+
+ CXTranslationUnit TU = GetTU(CT);
+ ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
+ PrintingPolicy Policy(Ctx.getPrintingPolicy());
+ Policy.SuppressScope = false;
+ Policy.AnonymousTagLocations = false;
+ Policy.PolishForDeclaration = true;
+ std::string name = TypeName::getFullyQualifiedName(T, Ctx, Policy, /*WithGlobalNsPrefix=*/true);
+ return cxstring::createDup(name.c_str());
+}
+
CXType clang_getTypedefDeclUnderlyingType(CXCursor C) {
using namespace cxcursor;
CXTranslationUnit TU = cxcursor::getCursorTU(C);
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:36:14.531346336 +0100
@@ -303,6 +303,7 @@ LLVM_13 {
clang_getFileName;
clang_getFileTime;
clang_getFileUniqueID;
+ clang_getFullyQualifiedTypeName;
clang_getFunctionTypeCallingConv;
clang_getIBOutletCollectionType;
clang_getIncludedFile;
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)
@@ -1852,13 +1859,16 @@ class Cursor(Structure):
for descendant in child.walk_preorder():
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."""
@@ -3073,18 +3091,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 -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/clang/cindex.py.orig spack-src-new/clang/bindings/python/clang/cindex.py.orig
--- spack-src/clang/bindings/python/clang/cindex.py.orig 2025-02-03 18:51:19.639119257 +0100
+++ spack-src-new/clang/bindings/python/clang/cindex.py.orig 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)
@@ -1852,13 +1859,16 @@ class Cursor(Structure):
for descendant in child.walk_preorder():
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."""
@@ -3081,18 +3091,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):
"""
@@ -3970,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 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,9 +203,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;
}
@@ -713,10 +714,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 +729,7 @@ bool CursorVisitor::VisitClassTemplateSp
break;
case TSK_ExplicitSpecialization:
+ // Always visit body of explicit specializations
ShouldVisitBody = true;
break;
}
@@ -945,7 +950,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) {
@@ -956,6 +985,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) {
@@ -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: *;
};
...@@ -395,20 +395,27 @@ class Llvm(CMakePackage, CudaPackage): ...@@ -395,20 +395,27 @@ class Llvm(CMakePackage, CudaPackage):
"bindings generator") "bindings generator")
conflicts("@:8", when="+visionary") conflicts("@:8", when="+visionary")
conflicts("@13:", when="+visionary") conflicts("@14:", when="+visionary")
patch('llvm9-0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch', when='@9.0.0:12.0.999 +visionary', level=2) patch('llvm9-0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch', when='@9:12 +visionary', level=2)
# 0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch from above # 0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch from above
patch('llvm11-0002-libclang-Add-support-for-obtaining-fully-qualified-n.patch', when='@11.0.0:11.0.999 +visionary', level=2) patch('llvm11-0002-libclang-Add-support-for-obtaining-fully-qualified-n.patch', when='@11 +visionary', level=2)
patch('llvm11-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch', when='@11.0.0:11.0.999 +visionary', level=2) patch('llvm11-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch', when='@11 +visionary', level=2)
patch('llvm11-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch', when='@11.0.0:11.0.999 +visionary', level=2) patch('llvm11-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch', when='@11 +visionary', level=2)
patch('llvm11-0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch', when='@11.0.0:12.0.999 +visionary', level=2) patch('llvm11-0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch', when='@11: +visionary', level=2)
# 0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch from above # 0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch from above
patch('llvm11_1-0002-libclang-Add-support-for-obtaining-fully-qualified-n.patch', when='@11.1.0:12.0.999 +visionary', level=2) patch('llvm11_1-0002-libclang-Add-support-for-obtaining-fully-qualified-n.patch', when='@11.1:12.0 +visionary', level=2)
patch('llvm11_1-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch', when='@11.1.0:12.0.999 +visionary', level=2) patch('llvm11_1-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch', when='@11.1:12.0 +visionary', level=2)
patch('llvm11_1-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch', when='@11.1.0:12.0.999 +visionary', level=2) patch('llvm11_1-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch', when='@11.1:12.0 +visionary', level=2)
# 0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch from above
patch('llvm13-0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch', when='@13: +visionary', level=1)
patch('llvm13-0002-libclang-Add-support-for-obtaining-fully-qualified-n.patch', when='@13:15 +visionary', level=1)
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
# 0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch from above # 0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch from above
# disable check for member `mode` size in `struct ipc_perm`; newer glibc changed width # disable check for member `mode` size in `struct ipc_perm`; newer glibc changed width
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment