Skip to content
Snippets Groups Projects
Commit 24f2ddba authored by Athanasios Karmas's avatar Athanasios Karmas
Browse files

Merge branch 'brainscales_update_llvm' into 'master'

Fix(meta-brainscales): Unpin llvm

See merge request akarmas/ebrains-spack-builds!10
parents 24fefe75 14231548
No related branches found
No related tags found
No related merge requests found
......@@ -42,7 +42,7 @@ class Genpybind(WafPackage):
version('visions', branch='master', git='https://github.com/electronicvisions/genpybind')
depends_on(
'llvm+clang+python+visionary@5.0.0:5.999.999,7.0.0:7.999.999,9.0.0:9.999.999',
'llvm+clang+python+visionary@5.0.0:',
type=('build', 'link', 'run'))
depends_on('binutils', type='build')
depends_on('python@2.7:', type=('build', 'run'))
......
From e673a5527dd2df322884eb2498736483df05957d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Johann=20Kl=C3=A4hn?= <johann@jklaehn.de>
Date: Fri, 3 Nov 2017 11:17:59 +0100
Subject: [PATCH 2/5] [libclang] Add support for obtaining fully qualified
names of types
This patch allows retrieving the fully qualified names of types
through libclang and clang.cindex (Python).
---
clang/bindings/python/clang/cindex.py | 13 +++++++++++
.../python/tests/cindex/test_cursor.py | 8 +++++++
clang/include/clang-c/Index.h | 10 ++++++++-
clang/tools/libclang/CMakeLists.txt | 1 +
clang/tools/libclang/CXType.cpp | 22 +++++++++++++++++++
clang/tools/libclang/libclang.exports | 1 +
6 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/tools/clang/bindings/python/clang/cindex.py b/tools/clang/bindings/python/clang/cindex.py
index 8e5a9fe0068..c309f7017b2 100644
--- a/tools/clang/bindings/python/clang/cindex.py
+++ b/tools/clang/bindings/python/clang/cindex.py
@@ -2427,6 +2427,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 = [
_CXString,
_CXString.from_result),
+ ("clang_getFullyQualifiedTypeName",
+ [Type],
+ _CXString,
+ _CXString.from_result),
+
("clang_hashCursor",
[Cursor],
c_uint),
diff --git a/tools/clang/bindings/python/tests/cindex/test_cursor.py b/tools/clang/bindings/python/tests/cindex/test_cursor.py
index ef875e97247..6a53c7205df 100644
--- a/tools/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/tools/clang/bindings/python/tests/cindex/test_cursor.py
@@ -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 --git a/tools/clang/include/clang-c/Index.h b/tools/clang/include/clang-c/Index.h
index 74badac740b..b0c62fe948e 100644
--- a/tools/clang/include/clang-c/Index.h
+++ b/tools/clang/include/clang-c/Index.h
@@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 61
+#define CINDEX_VERSION_MINOR 62
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -3389,6 +3389,14 @@ CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C);
*/
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.
*
diff --git a/tools/clang/tools/libclang/CMakeLists.txt b/tools/clang/tools/libclang/CMakeLists.txt
index 613ead1a36b..a583fa206d1 100644
--- a/tools/clang/tools/libclang/CMakeLists.txt
+++ b/tools/clang/tools/libclang/CMakeLists.txt
@@ -43,6 +43,7 @@ set(LIBS
clangSema
clangSerialization
clangTooling
+ clangToolingCore
)
if (CLANG_ENABLE_ARCMT)
diff --git a/tools/clang/tools/libclang/CXType.cpp b/tools/clang/tools/libclang/CXType.cpp
index acecf87d0cd..afdeb467769 100644
--- a/tools/clang/tools/libclang/CXType.cpp
+++ b/tools/clang/tools/libclang/CXType.cpp
@@ -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"
@@ -302,6 +303,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 --git a/tools/clang/tools/libclang/libclang.exports b/tools/clang/tools/libclang/libclang.exports
index 3c76090d64f..6e860e7263e 100644
--- a/tools/clang/tools/libclang/libclang.exports
+++ b/tools/clang/tools/libclang/libclang.exports
@@ -241,6 +241,7 @@ clang_getFileLocation
clang_getFileName
clang_getFileTime
clang_getFileUniqueID
+clang_getFullyQualifiedTypeName
clang_getFunctionTypeCallingConv
clang_getIBOutletCollectionType
clang_getIncludedFile
--
2.23.0
From 075a7a3e667fe3d923de6d7a6929e61922c8b139 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Johann=20Kl=C3=A4hn?= <johann@jklaehn.de>
Date: Fri, 3 Nov 2017 21:19:51 +0100
Subject: [PATCH 3/5] [libclang] Add option to keep whitespace when tokenizing
Introduces new `clang_tokenizeRange` function which accepts options to control
tokenization behavior. `clang_tokenize` is kept for backwards compatibility.
---
clang/bindings/python/clang/cindex.py | 31 ++++++++++++++----
.../python/tests/cindex/test_cursor.py | 9 ++++++
clang/include/clang-c/Index.h | 32 +++++++++++++++++--
clang/tools/libclang/CIndex.cpp | 15 +++++++--
clang/tools/libclang/libclang.exports | 1 +
5 files changed, 75 insertions(+), 13 deletions(-)
diff --git a/tools/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index c309f7017b2..1589acc9e7e 100644
--- a/tools/clang/bindings/python/clang/cindex.py
+++ b/tools/clang/bindings/python/clang/cindex.py
@@ -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."""
@@ -3080,18 +3090,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):
"""
@@ -3969,6 +3982,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 --git a/tools/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py
index 6a53c7205df..0965c1f4ae1 100644
--- a/tools/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/tools/clang/bindings/python/tests/cindex/test_cursor.py
@@ -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
@@ -488,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 --git a/tools/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index b0c62fe948e..84ed03b8920 100644
--- a/tools/clang/include/clang-c/Index.h
+++ b/tools/clang/include/clang-c/Index.h
@@ -32,7 +32,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) \
@@ -4969,6 +4969,28 @@ CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit,
*/
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.
@@ -4985,9 +5007,13 @@ CINDEX_LINKAGE CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken);
* \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 --git a/tools/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 1dc961f58a2..3a283e76ed8 100644
--- a/tools/clang/tools/libclang/CIndex.cpp
+++ b/tools/clang/tools/libclang/CIndex.cpp
@@ -6670,7 +6670,7 @@ CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {
}
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());
@@ -6692,6 +6692,9 @@ static void getTokens(ASTUnit *CXXUnit, SourceRange Range,
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;
@@ -6765,7 +6768,7 @@ CXToken *clang_getToken(CXTranslationUnit TU, CXSourceLocation Location) {
SourceLocation End = 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;
@@ -6913,6 +6913,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)
@@ -6804,7 +6813,7 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
return;
SmallVector<CXToken, 32> CXTokens;
- getTokens(CXXUnit, R, CXTokens);
+ getTokens(CXXUnit, R, CXTokens, options);
if (CXTokens.empty())
return;
diff --git a/tools/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports
index 6e860e7263e..6af6c0ca3e8 100644
--- a/tools/clang/tools/libclang/libclang.exports
+++ b/tools/clang/tools/libclang/libclang.exports
@@ -338,6 +338,7 @@ clang_suspendTranslationUnit
clang_sortCodeCompletionResults
clang_toggleCrashRecovery
clang_tokenize
+clang_tokenizeRange
clang_CompilationDatabase_fromDirectory
clang_CompilationDatabase_dispose
clang_CompilationDatabase_getCompileCommands
--
2.23.0
From d10d66b8e762c1dd1329d5920f9ef952cf4f6940 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Johann=20Kl=C3=A4hn?= <johann.klaehn@kip.uni-heidelberg.de>
Date: Mon, 17 Jul 2017 12:25:49 +0200
Subject: [PATCH 4/5] [libclang] WIP: Allow visiting of implicit declarations
and template instantiations
---
clang/bindings/python/clang/cindex.py | 45 +++++--
.../python/tests/cindex/test_cursor.py | 33 ++++++
clang/include/clang-c/Index.h | 33 +++++-
clang/tools/libclang/CIndex.cpp | 112 ++++++++++++++++--
clang/tools/libclang/CursorVisitor.h | 12 +-
clang/tools/libclang/libclang.exports | 2 +
6 files changed, 220 insertions(+), 17 deletions(-)
diff --git a/tools/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 1589acc9e7e..b023be6cdc8 100644
--- a/tools/clang/bindings/python/clang/cindex.py
+++ b/tools/clang/bindings/python/clang/cindex.py
@@ -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):
@@ -3927,6 +3950,10 @@ functionList = [
[Type],
bool),
+ ("clang_isImplicit",
+ [Cursor],
+ bool),
+
("clang_isInvalid",
[CursorKind],
bool),
@@ -3990,6 +4017,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 --git a/tools/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py
index 0965c1f4ae1..d061f37c25c 100644
--- a/tools/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/tools/clang/bindings/python/tests/cindex/test_cursor.py
@@ -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 --git a/tools/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 84ed03b8920..57acbcba143 100644
--- a/tools/clang/include/clang-c/Index.h
+++ b/tools/clang/include/clang-c/Index.h
@@ -32,7 +32,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) \
@@ -2775,6 +2775,11 @@ CINDEX_LINKAGE unsigned clang_isPreprocessing(enum CXCursorKind);
*/
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.
*/
@@ -4199,6 +4204,32 @@ CINDEX_LINKAGE unsigned clang_visitChildrenWithBlock(CXCursor parent,
# 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 --git a/tools/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 3a283e76ed8..7ee6b704647 100644
--- a/tools/clang/tools/libclang/CIndex.cpp
+++ b/tools/clang/tools/libclang/CIndex.cpp
@@ -196,9 +196,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;
}
@@ -706,10 +706,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;
@@ -715,6 +719,7 @@ bool CursorVisitor::VisitClassTemplateSpecializationDecl(
break;
case TSK_ExplicitSpecialization:
+ // Always visit body of explicit specializations
ShouldVisitBody = true;
break;
}
@@ -938,7 +941,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) {
@@ -949,6 +976,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) {
@@ -4426,6 +4488,24 @@ unsigned clang_visitChildrenWithBlock(CXCursor parent,
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();
@@ -5909,6 +5970,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 --git a/tools/clang/tools/libclang/CursorVisitor.h b/clang/tools/libclang/CursorVisitor.h
index b0afa5a0b59..94f4596d5fa 100644
--- a/tools/clang/tools/libclang/CursorVisitor.h
+++ b/tools/clang/tools/libclang/CursorVisitor.h
@@ -95,6 +95,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 +152,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 --git a/tools/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports
index 6af6c0ca3e8..d17eb83187d 100644
--- a/tools/clang/tools/libclang/libclang.exports
+++ b/tools/clang/tools/libclang/libclang.exports
@@ -313,6 +313,7 @@ clang_isInvalidDeclaration
clang_isExpression
clang_isFileMultipleIncludeGuarded
clang_isFunctionTypeVariadic
+clang_isImplicit
clang_isInvalid
clang_isPODType
clang_isPreprocessing
@@ -354,6 +355,7 @@ clang_CompileCommand_getNumArgs
clang_CompileCommand_getArg
clang_visitChildren
clang_visitChildrenWithBlock
+clang_visitChildrenWithOptions
clang_ModuleMapDescriptor_create
clang_ModuleMapDescriptor_dispose
clang_ModuleMapDescriptor_setFrameworkModuleName
--
2.23.0
......@@ -174,17 +174,23 @@ class Llvm(CMakePackage, CudaPackage):
patch('llvm7-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch', when='@7.0:7.999 +visionary', level=2)
patch('llvm7-0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch', when='@7.0:7.999 +visionary', level=2)
patch('llvm9-0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch', when='@9.0:10.999 +visionary', level=2)
patch('llvm9-0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch', when='@9.0.0:12.0.999 +visionary', level=2)
patch('llvm9-0002-libclang-Add-support-for-obtaining-fully-qualified-n.patch', when='@9.0:10.999 +visionary', level=2)
patch('llvm9-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch', when='@9.0:10.999 +visionary', level=2)
patch('llvm9-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch', when='@9.0:10.999 +visionary', level=2)
patch('llvm9-0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch', when='@9.0:10.999 +visionary', level=2)
patch('llvm9-0001-Tooling-Fully-qualify-template-parameters-of-nested-.patch', when='@11.0:11.999 +visionary', level=2)
patch('llvm11-0002-libclang-Add-support-for-obtaining-fully-qualified-n.patch', when='@11.0:11.999 +visionary', level=2)
patch('llvm11-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch', when='@11.0:11.999 +visionary', level=2)
patch('llvm11-0004-libclang-WIP-Allow-visiting-of-implicit-declarations.patch', when='@11.0:11.999 +visionary', level=2)
patch('llvm11-0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch', when='@11.0:11.999 +visionary', level=2)
# 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-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.patch', when='@11.0.0:11.0.999 +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-0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch', when='@11.0.0:12.0.999 +visionary', level=2)
# 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-0003-libclang-Add-option-to-keep-whitespace-when-tokenizi.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.0:12.0.999 +visionary', level=2)
# 0005-libclang-WIP-Fix-get_tokens-in-macro-expansion.patch from above
# Build dependency
depends_on("cmake@3.4.3:", type="build")
......
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