Here are four patches improving libclang in various ways for use in
xdress (http://xdress.org). In order, they add
1. Python support for clang_formatDiagnostic.
2. Access to public / private / protected specifiers.
3. Template argument access (as new cursor types).
4. A clang_Cursor_getDefaultArgument function.
They've all been tested inside xdress, but the patches themselves do
not include tests. Since questions about this stuff to cfe-dev were
ignored, I want to make sure these patches will be looked at before I
do potentially unnecessary work.
Caveat: llvm trunk does not build for me due to these errors:
llvm-build: error: invalid native target: 'x86_64' (not in project)
Therefore, these patches were written, built, and tested again
release_33 plus several cherry-picked libclang commits. It's possible
they don't compile against the trunk.
Any ideas what would have caused this build breakage since release_33?
Thanks,
Geoffrey
From cdd978d232636b8cb249b37291fcab6dbfc52b49 Mon Sep 17 00:00:00 2001
From: Geoffrey Irving <[email protected]>
Date: Thu, 31 Oct 2013 15:07:18 -0700
Subject: [PATCH 1/4] [libclang/python] Expose clang_formatDiagnostic to python
---
bindings/python/clang/cindex.py | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index c103c70..8339e2b 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -382,6 +382,12 @@ class Diagnostic(object):
return conf.lib.clang_getCString(disable)
+ def format(self, options=None):
+ """Format the diagnostic according to the given options."""
+ if options is None:
+ options = conf.lib.clang_defaultDiagnosticDisplayOptions()
+ return conf.lib.clang_formatDiagnostic(self, options)
+
def __repr__(self):
return "<Diagnostic severity %r, location %r, spelling %r>" % (
self.severity, self.location, self.spelling)
@@ -2949,6 +2955,15 @@ functionList = [
_CXString,
_CXString.from_result),
+ ("clang_formatDiagnostic",
+ [Diagnostic, c_uint],
+ _CXString,
+ _CXString.from_result),
+
+ ("clang_defaultDiagnosticDisplayOptions",
+ [],
+ c_uint),
+
("clang_getElementType",
[Type],
Type,
--
1.8.4.1.559.gdb9bdfb
From c2316c6cc6e83b70e79ad0cf6ae6cbd6af9ac053 Mon Sep 17 00:00:00 2001
From: Geoffrey Irving <[email protected]>
Date: Thu, 31 Oct 2013 15:08:26 -0700
Subject: [PATCH 2/4] [libclang/python] Expose access specifiers
(public/private/protected)
---
bindings/python/clang/cindex.py | 45 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index 8339e2b..4c71203 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -501,6 +501,43 @@ class TokenKind(object):
TokenKind._value_map[value] = kind
setattr(TokenKind, name, kind)
+class AccessKind(object):
+ """Describes a specific type of an access specifier."""
+
+ # The unique kind objects, indexed by id
+ _kinds = []
+ _name_map = None
+
+ def __init__(self, value):
+ if value >= len(AccessKind._kinds):
+ AccessKind._kinds += [None] * (value - len(AccessKind._kinds) + 1)
+ if AccessKind._kinds[value] is not None:
+ raise ValueError,'AccessKind already loaded'
+ self.value = value
+ AccessKind._kinds[value] = self
+ AccessKind._name_map = None
+
+ @property
+ def name(self):
+ """Get the enumeration name of this cursor kind."""
+ if self._name_map is None:
+ self._name_map = {}
+ for key,value in AccessKind.__dict__.items():
+ if isinstance(value,AccessKind):
+ self._name_map[value] = key
+ return self._name_map[self]
+
+ @staticmethod
+ def from_id(id):
+ if id >= len(AccessKind._kinds) or AccessKind._kinds[id] is None:
+ raise ValueError,'Unknown access kind %d' % id
+ return AccessKind._kinds[id]
+
+AccessKind.INVALID = AccessKind(0)
+AccessKind.PUBLIC = AccessKind(1)
+AccessKind.PROTECTED = AccessKind(2)
+AccessKind.PRIVATE = AccessKind(3)
+
### Cursor Kinds ###
class CursorKind(object):
@@ -1304,6 +1341,14 @@ class Cursor(Structure):
return self._objc_type_encoding
@property
+ def access(self):
+ """Return the AccessKind of an access specifier."""
+ if not hasattr(self, '_access'):
+ self._access = AccessKind.from_id(conf.lib.clang_getCXXAccessSpecifier(self))
+
+ return self._access
+
+ @property
def hash(self):
"""Returns a hash of the cursor as an int."""
if not hasattr(self, '_hash'):
--
1.8.4.1.559.gdb9bdfb
From d87637b655eae302bf648daea70b878ccd53915f Mon Sep 17 00:00:00 2001
From: Geoffrey Irving <[email protected]>
Date: Sun, 3 Nov 2013 12:06:30 -0800
Subject: [PATCH 3/4] [libclang] Add template argument support
---
bindings/python/clang/cindex.py | 38 +++++++++++++++++++---
include/clang-c/Index.h | 36 ++++++++++++++++++++-
tools/libclang/CIndex.cpp | 38 +++++++++++++++++++++-
tools/libclang/CXCursor.cpp | 70 +++++++++++++++++++++++++++++++++++++++++
tools/libclang/CXCursor.h | 5 +++
tools/libclang/CXType.cpp | 5 +++
tools/libclang/libclang.exports | 3 ++
7 files changed, 189 insertions(+), 6 deletions(-)
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index 4c71203..7104b8d 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -1136,6 +1136,18 @@ CursorKind.INCLUSION_DIRECTIVE = CursorKind(503)
# A module import declaration.
CursorKind.MODULE_IMPORT_DECL = CursorKind(600)
+###
+# Template arguments
+CursorKind.NULL_TEMPLATE_ARG = CursorKind(700)
+CursorKind.TYPE_TEMPLATE_ARG = CursorKind(701)
+CursorKind.DECLARATION_TEMPLATE_ARG = CursorKind(702)
+CursorKind.NULL_PTR_TEMPLATE_ARG = CursorKind(703)
+CursorKind.INTEGRAL_TEMPLATE_ARG = CursorKind(704)
+CursorKind.TEMPLATE_TEMPLATE_ARG = CursorKind(705)
+CursorKind.TEMPLATE_EXPANSION_TEMPLATE_ARG = CursorKind(706)
+CursorKind.EXPRESSION_TEMPLATE_ARG = CursorKind(707)
+CursorKind.PACK_TEMPLATE_ARG = CursorKind(708)
+
### Cursors ###
class Cursor(Structure):
@@ -1202,10 +1214,6 @@ class Cursor(Structure):
@property
def spelling(self):
"""Return the spelling of the entity pointed at by the cursor."""
- if not self.kind.is_declaration():
- # FIXME: clang_getCursorSpelling should be fixed to not assert on
- # this, for consistency with clang_getCursorUSR.
- return None
if not hasattr(self, '_spelling'):
self._spelling = conf.lib.clang_getCursorSpelling(self)
@@ -1406,6 +1414,19 @@ class Cursor(Structure):
for i in range(0, num_args):
yield conf.lib.clang_Cursor_getArgument(self, i)
+ def has_template_args(self):
+ """Is this cursor a declaration with template arguments?
+ Note: returns True for templatized classes with zero arguments."""
+ return conf.lib.clang_Cursor_getNumTemplateArgs(self) >= 0
+
+ def get_template_args(self):
+ """Return an iterator for accessing the template arguments of this cursor."""
+ num = conf.lib.clang_Cursor_getNumTemplateArgs(self)
+ if num < 0:
+ raise ValueError("Cursor has no notion of template arguments")
+ for i in range(num):
+ yield conf.lib.clang_Cursor_getTemplateArg(self, i)
+
def get_children(self):
"""Return an iterator for accessing the children of this cursor."""
@@ -3275,6 +3296,15 @@ functionList = [
Cursor,
Cursor.from_result),
+ ("clang_Cursor_getNumTemplateArgs",
+ [Cursor],
+ c_int),
+
+ ("clang_Cursor_getTemplateArg",
+ [Cursor, c_uint],
+ Cursor,
+ Cursor.from_result),
+
("clang_Cursor_isBitField",
[Cursor],
bool),
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index cd130e3..dd28407 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -2113,7 +2113,20 @@ enum CXCursorKind {
*/
CXCursor_ModuleImportDecl = 600,
CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
- CXCursor_LastExtraDecl = CXCursor_ModuleImportDecl
+ CXCursor_LastExtraDecl = CXCursor_ModuleImportDecl,
+
+ /* Template arguments */
+ CXCursor_NullTemplateArg = 700,
+ CXCursor_TypeTemplateArg = 701,
+ CXCursor_DeclarationTemplateArg = 702,
+ CXCursor_NullPtrTemplateArg = 703,
+ CXCursor_IntegralTemplateArg = 704,
+ CXCursor_TemplateTemplateArg = 705,
+ CXCursor_TemplateExpansionTemplateArg = 706,
+ CXCursor_ExpressionTemplateArg = 707,
+ CXCursor_PackTemplateArg = 708,
+ CXCursor_FirstTemplateArg = CXCursor_NullTemplateArg,
+ CXCursor_LastTemplateArg = CXCursor_PackTemplateArg
};
/**
@@ -2234,6 +2247,12 @@ CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind);
* element, such as a preprocessor directive or macro instantiation.
*/
CINDEX_LINKAGE unsigned clang_isPreprocessing(enum CXCursorKind);
+
+/***
+ * \brief Determine whether the given cursor represents a template
+ * argument.
+ */
+CINDEX_LINKAGE unsigned clang_isTemplateArg(enum CXCursorKind);
/***
* \brief Determine whether the given cursor represents a currently
@@ -2788,6 +2807,21 @@ CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C);
CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i);
/**
+ * \brief Count the template arguments of a declaration
+ *
+ * For other cursors, -1 is returned.
+ */
+CINDEX_LINKAGE int clang_Cursor_getNumTemplateArgs(CXCursor C);
+
+/**
+ * \brief Retrieve one template argument of a declaration
+ *
+ * If the cursor has the wrong type, or the index is out of range, and invalid
+ * cursor is returned.
+ */
+CINDEX_LINKAGE CXCursor clang_Cursor_getTemplateArg(CXCursor C, unsigned i);
+
+/**
* \brief Determine whether two CXTypes represent the same type.
*
* \returns non-zero if the CXTypes represent the same type and
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index c30f937..9f2e067 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -538,6 +538,12 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
A->getInterfaceLoc()->getTypeLoc().getLocStart(), TU));
}
+ // For now template arguments have no children.
+ // This should possibly change to account for general
+ // expression, parameter packs, etc.
+ if (clang_isTemplateArg(Cursor.kind))
+ return false;
+
// If pointing inside a macro definition, check if the token is an identifier
// that was ever defined as a macro. In such a case, create a "pseudo" macro
// expansion cursor for that token.
@@ -3357,6 +3363,14 @@ CXString clang_getCursorSpelling(CXCursor C) {
return cxstring::createRef("packed");
}
+ if (clang_isTemplateArg(C.kind)) {
+ SmallString<64> Str;
+ llvm::raw_svector_ostream OS(Str);
+ const PrintingPolicy Policy = getCursorContext(C).getPrintingPolicy();
+ getCursorTemplateArg(C)->print(Policy,OS);
+ return cxstring::createDup(OS.str());
+ }
+
return cxstring::createEmpty();
}
@@ -3826,6 +3840,24 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("ModuleImport");
case CXCursor_OMPParallelDirective:
return cxstring::createRef("OMPParallelDirective");
+ case CXCursor_NullTemplateArg:
+ return cxstring::createRef("NullTemplateArg");
+ case CXCursor_TypeTemplateArg:
+ return cxstring::createRef("TypeTemplateArg");
+ case CXCursor_DeclarationTemplateArg:
+ return cxstring::createRef("DeclarationTemplateArg");
+ case CXCursor_NullPtrTemplateArg:
+ return cxstring::createRef("NullPtrTemplateArg");
+ case CXCursor_IntegralTemplateArg:
+ return cxstring::createRef("IntegralTemplateArg");
+ case CXCursor_TemplateTemplateArg:
+ return cxstring::createRef("TemplateTemplateArg");
+ case CXCursor_TemplateExpansionTemplateArg:
+ return cxstring::createRef("TemplateExpansionTemplateArg");
+ case CXCursor_ExpressionTemplateArg:
+ return cxstring::createRef("ExpressionTemplateArg");
+ case CXCursor_PackTemplateArg:
+ return cxstring::createRef("PackTemplateArg");
}
llvm_unreachable("Unhandled CXCursorKind");
@@ -4061,7 +4093,11 @@ unsigned clang_isTranslationUnit(enum CXCursorKind K) {
unsigned clang_isPreprocessing(enum CXCursorKind K) {
return K >= CXCursor_FirstPreprocessing && K <= CXCursor_LastPreprocessing;
}
-
+
+unsigned clang_isTemplateArg(enum CXCursorKind K) {
+ return K >= CXCursor_FirstTemplateArg && K <= CXCursor_LastTemplateArg;
+}
+
unsigned clang_isUnexposed(enum CXCursorKind K) {
switch (K) {
case CXCursor_UnexposedDecl:
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index c75c061..537e4de 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -518,6 +518,34 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
return C;
}
+static CXCursorKind GetCursorKind(const TemplateArgument *A) {
+ assert(A && "Invalid arguments!");
+ switch (A->getKind()) {
+ #define TACase(Kind) \
+ case TemplateArgument::Kind: \
+ return CXCursor_##Kind##TemplateArg;
+ TACase(Null)
+ TACase(Type)
+ TACase(Declaration)
+ TACase(NullPtr)
+ TACase(Integral)
+ TACase(Template)
+ TACase(TemplateExpansion)
+ TACase(Expression)
+ TACase(Pack)
+ }
+
+ llvm_unreachable("Invalid TemplateArgument::Kind");
+}
+
+CXCursor cxcursor::MakeCXCursor(const TemplateArgument* A,
+ const Decl* Parent,
+ CXTranslationUnit TU) {
+ assert(A && Parent && TU && "Invalid arguments!");
+ CXCursor C = { GetCursorKind(A), 0, { Parent, A, TU } };
+ return C;
+}
+
CXCursor cxcursor::MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
SourceLocation Loc,
CXTranslationUnit TU) {
@@ -818,6 +846,10 @@ const Decl *cxcursor::getCursorParentDecl(CXCursor Cursor) {
return static_cast<const Decl *>(Cursor.data[0]);
}
+const TemplateArgument *cxcursor::getCursorTemplateArg(CXCursor Cursor) {
+ return static_cast<const TemplateArgument *>(Cursor.data[1]);
+}
+
ASTContext &cxcursor::getCursorContext(CXCursor Cursor) {
return getCursorASTUnit(Cursor)->getASTContext();
}
@@ -1005,6 +1037,44 @@ CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i) {
return clang_getNullCursor();
}
+// Return the number of template arguments and a pointer to the first.
+// On failure, -1 is returned. Logic borrowed from TypePrinter::printTag
+static int getTemplateArgs(const Decl *D, const TemplateArgument **args) {
+ const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(D);
+ if (!Spec)
+ return -1;
+ if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
+ const TemplateSpecializationType *TST =
+ cast<TemplateSpecializationType>(TAW->getType());
+ *args = TST->getArgs();
+ return TST->getNumArgs();
+ } else {
+ const TemplateArgumentList &TA = Spec->getTemplateArgs();
+ *args = TA.data();
+ return TA.size();
+ }
+}
+
+int clang_Cursor_getNumTemplateArgs(CXCursor C) {
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return -1;
+ const TemplateArgument *args;
+ return getTemplateArgs(D,&args);
+}
+
+CXCursor clang_Cursor_getTemplateArg(CXCursor C, unsigned i) {
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullCursor();
+ const TemplateArgument *args;
+ const int count = getTemplateArgs(D,&args);
+ if (count < 0 || i >= unsigned(count))
+ return clang_getNullCursor();
+ return MakeCXCursor(args+i, D, getCursorTU(C));
+}
+
} // end: extern "C"
//===----------------------------------------------------------------------===//
diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h
index 957d519..dc3a9c7 100644
--- a/tools/libclang/CXCursor.h
+++ b/tools/libclang/CXCursor.h
@@ -43,6 +43,7 @@ class TemplateName;
class TypeDecl;
class VarDecl;
class IdentifierInfo;
+class TemplateArgument;
namespace cxcursor {
@@ -56,6 +57,9 @@ CXCursor MakeCXCursor(const clang::Decl *D, CXTranslationUnit TU,
CXCursor MakeCXCursor(const clang::Stmt *S, const clang::Decl *Parent,
CXTranslationUnit TU,
SourceRange RegionOfInterest = SourceRange());
+CXCursor MakeCXCursor(const clang::TemplateArgument* A,
+ const clang::Decl* Parent,
+ CXTranslationUnit TU);
CXCursor MakeCXCursorInvalid(CXCursorKind K, CXTranslationUnit TU = 0);
/// \brief Create an Objective-C superclass reference at the given location.
@@ -246,6 +250,7 @@ const Expr *getCursorExpr(CXCursor Cursor);
const Stmt *getCursorStmt(CXCursor Cursor);
const Attr *getCursorAttr(CXCursor Cursor);
const Decl *getCursorParentDecl(CXCursor Cursor);
+const TemplateArgument *getCursorTemplateArg(CXCursor Cursor);
ASTContext &getCursorContext(CXCursor Cursor);
ASTUnit *getCursorASTUnit(CXCursor Cursor);
diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp
index 1e2cb18..12dc145 100644
--- a/tools/libclang/CXType.cpp
+++ b/tools/libclang/CXType.cpp
@@ -214,6 +214,11 @@ CXType clang_getCursorType(CXCursor C) {
return MakeCXType(QualType(), TU);
}
+ if (C.kind == CXCursor_TypeTemplateArg) {
+ const TemplateArgument *TA = getCursorTemplateArg(C);
+ return MakeCXType(TA->getAsType(), TU);
+ }
+
return MakeCXType(QualType(), TU);
}
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 9bf26c9..2cba0fb 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -11,11 +11,13 @@ clang_Cursor_getCommentRange
clang_Cursor_getParsedComment
clang_Cursor_getRawCommentText
clang_Cursor_getNumArguments
+clang_Cursor_getNumTemplateArgs
clang_Cursor_getObjCDeclQualifiers
clang_Cursor_getObjCPropertyAttributes
clang_Cursor_getObjCSelectorIndex
clang_Cursor_getSpellingNameRange
clang_Cursor_getTranslationUnit
+clang_Cursor_getTemplateArg
clang_Cursor_getReceiverType
clang_Cursor_isBitField
clang_Cursor_isDynamicCall
@@ -251,6 +253,7 @@ clang_isPreprocessing
clang_isReference
clang_isRestrictQualifiedType
clang_isStatement
+clang_isTemplateArg
clang_isTranslationUnit
clang_isUnexposed
clang_isVirtualBase
--
1.8.4.1.559.gdb9bdfb
From 72879373f65e6eb08a94dcb4d74a5ff13532db2f Mon Sep 17 00:00:00 2001
From: Geoffrey Irving <[email protected]>
Date: Sun, 3 Nov 2013 14:53:37 -0800
Subject: [PATCH 4/4] [libclang] Add clang_Cursor_getDefaultArgument
This information is often reachable via children, but parameter
declarations can have expression children even if they have no
default arguments (Base<int,3> var). A dedicated accessor is much
cleaner.
---
bindings/python/clang/cindex.py | 10 ++++++++++
include/clang-c/Index.h | 9 +++++++++
tools/libclang/CIndex.cpp | 24 ++++++++++++++++++++++++
tools/libclang/libclang.exports | 1 +
4 files changed, 44 insertions(+)
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index 7104b8d..c588e74 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -1408,6 +1408,11 @@ class Cursor(Structure):
"""Returns the raw comment text associated with that Cursor"""
return conf.lib.clang_Cursor_getRawCommentText(self)
+ @property
+ def default_argument(self):
+ """The default argument of a parameter declaration, or None"""
+ return conf.lib.clang_Cursor_getDefaultArgument(self)
+
def get_arguments(self):
"""Return an iterator for accessing the arguments of this cursor."""
num_args = conf.lib.clang_Cursor_getNumArguments(self)
@@ -3319,6 +3324,11 @@ functionList = [
_CXString,
_CXString.from_result),
+ ("clang_Cursor_getDefaultArgument",
+ [Cursor],
+ Cursor,
+ Cursor.from_result),
+
("clang_Type_getAlignOf",
[Type],
c_longlong),
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index dd28407..b78f6dd 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -3526,6 +3526,15 @@ CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
CINDEX_LINKAGE CXComment clang_Cursor_getParsedComment(CXCursor C);
/**
+ * \brief Retrieve the default argument of a parameter declaration.
+ *
+ * If no default exists, an invalid cursor is returned. Unfortunately,
+ * this function also cannot return default type arguments for template
+ * parameters, since these cannot be converted to a cursor.
+ */
+CINDEX_LINKAGE CXCursor clang_Cursor_getDefaultArgument(CXCursor C);
+
+/**
* @}
*/
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 9f2e067..797d5cc 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -6225,6 +6225,30 @@ CXComment clang_Cursor_getParsedComment(CXCursor C) {
return cxcomment::createCXComment(FC, getCursorTU(C));
}
+CXCursor clang_Cursor_getDefaultArgument(CXCursor C) {
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = getCursorDecl(C);
+ if (const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D)) {
+ if (const Expr *E = PD->getDefaultArg())
+ return MakeCXCursor(E, D, getCursorTU(C));
+ } else if (const NonTypeTemplateParmDecl *PD = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+ if (const Expr *E = PD->getDefaultArgument())
+ return MakeCXCursor(E, D, getCursorTU(C));
+ } else if (const TemplateTemplateParmDecl *PD = dyn_cast<TemplateTemplateParmDecl>(D)) {
+ if (PD->hasDefaultArgument()) {
+ const TemplateArgument &TA = PD->getDefaultArgument().getArgument();
+ return MakeCXCursor(&TA, D, getCursorTU(C));
+ }
+ } /*
+ else if (const TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(D)) {
+ // FIXME: Since types can't be converted to cursors, we can't return a useful result.
+ } */
+ }
+
+ // If the cursor has the wrong type, or has the right type but lacks a default, return invalid.
+ return clang_getNullCursor();
+}
+
CXModule clang_Cursor_getModule(CXCursor C) {
if (C.kind == CXCursor_ModuleImportDecl) {
if (const ImportDecl *ImportD =
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 2cba0fb..4d5a713 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -8,6 +8,7 @@ clang_CXXMethod_isVirtual
clang_Cursor_getArgument
clang_Cursor_getBriefCommentText
clang_Cursor_getCommentRange
+clang_Cursor_getDefaultArgument
clang_Cursor_getParsedComment
clang_Cursor_getRawCommentText
clang_Cursor_getNumArguments
--
1.8.4.1.559.gdb9bdfb
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits