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

Reply via email to