r306483 - [libclang] Support for querying the exception specification type through libclang

Jonathan Coe via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 27 15:54:56 PDT 2017


Author: jbcoe
Date: Tue Jun 27 15:54:56 2017
New Revision: 306483

URL: http://llvm.org/viewvc/llvm-project?rev=306483&view=rev
Log:
[libclang] Support for querying the exception specification type through libclang

Summary: This patch exposes the exception specification type (noexcept,
etc.) of a C++ function through libclang and Python clang.cindex.

Reviewers: rsmith, aaron.ballman

Reviewed By: aaron.ballman

Subscribers: jbcoe, cfe-commits

Differential Revision: https://reviews.llvm.org/D34091

Patch by Andrew Bennieston

Added:
    cfe/trunk/bindings/python/tests/test_exception_specification_kind.py
Modified:
    cfe/trunk/bindings/python/clang/cindex.py
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/test/Index/get-cursor.cpp
    cfe/trunk/tools/c-index-test/c-index-test.c
    cfe/trunk/tools/libclang/CXType.cpp
    cfe/trunk/tools/libclang/libclang.exports

Modified: cfe/trunk/bindings/python/clang/cindex.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/clang/cindex.py?rev=306483&r1=306482&r2=306483&view=diff
==============================================================================
--- cfe/trunk/bindings/python/clang/cindex.py (original)
+++ cfe/trunk/bindings/python/clang/cindex.py Tue Jun 27 15:54:56 2017
@@ -1367,6 +1367,30 @@ TemplateArgumentKind.DECLARATION = Templ
 TemplateArgumentKind.NULLPTR = TemplateArgumentKind(3)
 TemplateArgumentKind.INTEGRAL = TemplateArgumentKind(4)
 
+### Exception Specification Kinds ###
+class ExceptionSpecificationKind(BaseEnumeration):
+    """
+    An ExceptionSpecificationKind describes the kind of exception specification
+    that a function has.
+    """
+
+    # The required BaseEnumeration declarations.
+    _kinds = []
+    _name_map = None
+
+    def __repr__(self):
+        return 'ExceptionSpecificationKind.{}'.format(self.name)
+
+ExceptionSpecificationKind.NONE = ExceptionSpecificationKind(0)
+ExceptionSpecificationKind.DYNAMIC_NONE = ExceptionSpecificationKind(1)
+ExceptionSpecificationKind.DYNAMIC = ExceptionSpecificationKind(2)
+ExceptionSpecificationKind.MS_ANY = ExceptionSpecificationKind(3)
+ExceptionSpecificationKind.BASIC_NOEXCEPT = ExceptionSpecificationKind(4)
+ExceptionSpecificationKind.COMPUTED_NOEXCEPT = ExceptionSpecificationKind(5)
+ExceptionSpecificationKind.UNEVALUATED = ExceptionSpecificationKind(6)
+ExceptionSpecificationKind.UNINSTANTIATED = ExceptionSpecificationKind(7)
+ExceptionSpecificationKind.UNPARSED = ExceptionSpecificationKind(8)
+
 ### Cursors ###
 
 class Cursor(Structure):
@@ -1587,6 +1611,18 @@ class Cursor(Structure):
         return self._result_type
 
     @property
+    def exception_specification_kind(self):
+        '''
+        Retrieve the exception specification kind, which is one of the values
+        from the ExceptionSpecificationKind enumeration.
+        '''
+        if not hasattr(self, '_exception_specification_kind'):
+            exc_kind = conf.lib.clang_getCursorExceptionSpecificationType(self)
+            self._exception_specification_kind = ExceptionSpecificationKind.from_id(exc_kind)
+
+        return self._exception_specification_kind
+
+    @property
     def underlying_typedef_type(self):
         """Return the underlying type of a typedef declaration.
 
@@ -2254,6 +2290,14 @@ class Type(Structure):
                             callbacks['fields_visit'](visitor), fields)
         return iter(fields)
 
+    def get_exception_specification_kind(self):
+        """
+        Return the kind of the exception specification; a value from
+        the ExceptionSpecificationKind enumeration.
+        """
+        return ExceptionSpecificationKind.from_id(
+                conf.lib.clang.getExceptionSpecificationType(self))
+
     @property
     def spelling(self):
         """Retrieve the spelling of this Type."""

Added: cfe/trunk/bindings/python/tests/test_exception_specification_kind.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/tests/test_exception_specification_kind.py?rev=306483&view=auto
==============================================================================
--- cfe/trunk/bindings/python/tests/test_exception_specification_kind.py (added)
+++ cfe/trunk/bindings/python/tests/test_exception_specification_kind.py Tue Jun 27 15:54:56 2017
@@ -0,0 +1,27 @@
+import clang.cindex
+from clang.cindex import ExceptionSpecificationKind
+from .util import get_tu
+
+
+def find_function_declarations(node, declarations=[]):
+    if node.kind == clang.cindex.CursorKind.FUNCTION_DECL:
+        declarations.append((node.spelling, node.exception_specification_kind))
+    for child in node.get_children():
+        declarations = find_function_declarations(child, declarations)
+    return declarations
+
+
+def test_exception_specification_kind():
+    source = """int square1(int x);
+                int square2(int x) noexcept;
+                int square3(int x) noexcept(noexcept(x * x));"""
+
+    tu = get_tu(source, lang='cpp', flags=['-std=c++14'])
+
+    declarations = find_function_declarations(tu.cursor)
+    expected = [
+        ('square1', ExceptionSpecificationKind.NONE),
+        ('square2', ExceptionSpecificationKind.BASIC_NOEXCEPT),
+        ('square3', ExceptionSpecificationKind.COMPUTED_NOEXCEPT)
+    ]
+    assert declarations == expected

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=306483&r1=306482&r2=306483&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Tue Jun 27 15:54:56 2017
@@ -171,7 +171,60 @@ typedef struct CXVersion {
    */
   int Subminor;
 } CXVersion;
-  
+
+/**
+ * \brief Describes the exception specification of a cursor.
+ *
+ * A negative value indicates that the cursor is not a function declaration.
+ */
+enum CXCursor_ExceptionSpecificationKind {
+
+  /**
+   * \brief The cursor has no exception specification.
+   */
+  CXCursor_ExceptionSpecificationKind_None,
+
+  /**
+   * \brief The cursor has exception specification throw()
+   */
+  CXCursor_ExceptionSpecificationKind_DynamicNone,
+
+  /**
+   * \brief The cursor has exception specification throw(T1, T2)
+   */
+  CXCursor_ExceptionSpecificationKind_Dynamic,
+
+  /**
+   * \brief The cursor has exception specification throw(...).
+   */
+  CXCursor_ExceptionSpecificationKind_MSAny,
+
+  /**
+   * \brief The cursor has exception specification basic noexcept.
+   */
+  CXCursor_ExceptionSpecificationKind_BasicNoexcept,
+
+  /**
+   * \brief The cursor has exception specification computed noexcept.
+   */
+  CXCursor_ExceptionSpecificationKind_ComputedNoexcept,
+
+  /**
+   * \brief The exception specification has not yet been evaluated.
+   */
+  CXCursor_ExceptionSpecificationKind_Unevaluated,
+
+  /**
+   * \brief The exception specification has not yet been instantiated.
+   */
+  CXCursor_ExceptionSpecificationKind_Uninstantiated,
+
+  /**
+   * \brief The exception specification has not been parsed yet.
+   */
+  CXCursor_ExceptionSpecificationKind_Unparsed
+};
+
 /**
  * \brief Provides a shared context for creating translation units.
  *
@@ -3471,6 +3524,13 @@ CINDEX_LINKAGE enum CXCallingConv clang_
 CINDEX_LINKAGE CXType clang_getResultType(CXType T);
 
 /**
+ * \brief Retrieve the exception specification type associated with a function type.
+ *
+ * If a non-function type is passed in, an error code of -1 is returned.
+ */
+CINDEX_LINKAGE int clang_getExceptionSpecificationType(CXType T);
+
+/**
  * \brief Retrieve the number of non-variadic parameters associated with a
  * function type.
  *
@@ -3499,6 +3559,13 @@ CINDEX_LINKAGE unsigned clang_isFunction
 CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C);
 
 /**
+ * \brief Retrieve the exception specification type associated with a given cursor.
+ *
+ * This only returns a valid result if the cursor refers to a function or method.
+ */
+CINDEX_LINKAGE int clang_getCursorExceptionSpecificationType(CXCursor C);
+
+/**
  * \brief Return 1 if the CXType is a POD (plain old data) type, and 0
  *  otherwise.
  */

Modified: cfe/trunk/test/Index/get-cursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/get-cursor.cpp?rev=306483&r1=306482&r2=306483&view=diff
==============================================================================
--- cfe/trunk/test/Index/get-cursor.cpp (original)
+++ cfe/trunk/test/Index/get-cursor.cpp Tue Jun 27 15:54:56 2017
@@ -145,6 +145,13 @@ void test(TestColl coll) {
 
 const int operator""_toint(unsigned long long val) { return int(val); }
 
+// noexcept specifications
+void f_noexcept() noexcept;
+template <class T> void f_computed_noexcept(T t) noexcept(noexcept(t+t));
+void f_dynamic_noexcept_none() throw();
+void f_dynamic_noexcept() throw(int);
+void f_dynamic_noexcept_any() throw(...);
+
 // RUN: c-index-test -cursor-at=%s:6:4 %s | FileCheck -check-prefix=CHECK-COMPLETION-1 %s
 // CHECK-COMPLETION-1: CXXConstructor=X:6:3
 // CHECK-COMPLETION-1-NEXT: Completion string: {TypedText X}{LeftParen (}{Placeholder int}{Comma , }{Placeholder int}{RightParen )}
@@ -209,11 +216,11 @@ const int operator""_toint(unsigned long
 // RUN: c-index-test -cursor-at=%s:66:23 %s | FileCheck -check-prefix=CHECK-TEMPLSPEC %s
 // CHECK-TEMPLSPEC: 66:23 ClassDecl=TC:66:23 (Definition) [Specialization of TC:59:7] Extent=[66:1 - 66:31] Spelling=TC ([66:23 - 66:25])
 
-// RUN: c-index-test -cursor-at=%s:69:3 -cursor-at=%s:70:11 -cursor-at=%s:73:6 -cursor-at=%s:74:6 -cursor-at=%s:77:8 -cursor-at=%s:78:8 -cursor-at=%s:79:8 -cursor-at=%s:80:8 -cursor-at=%s:81:8 -cursor-at=%s:82:8 -cursor-at=%s:85:6 -cursor-at=%s:86:6 -cursor-at=%s:87:6 -cursor-at=%s:88:6 -cursor-at=%s:91:5 -cursor-at=%s:92:5 -cursor-at=%s:93:5 -cursor-at=%s:94:5 -cursor-at=%s:95:5 -cursor-at=%s:96:5 -cursor-at=%s:97:5 -cursor-at=%s:98:5 -cursor-at=%s:100:5 -cursor-at=%s:101:5 -cursor-at=%s:104:6 -cursor-at=%s:105:6 -cursor-at=%s:106:6 -cursor-at=%s:107:6 -cursor-at=%s:108:6 -cursor-at=%s:109:6 -cursor-at=%s:110:6 -cursor-at=%s:111:6 -cursor-at=%s:113:6 -cursor-at=%s:114:6 -cursor-at=%s:117:8 -cursor-at=%s:118:8 -cursor-at=%s:120:8 -cursor-at=%s:121:8 -cursor-at=%s:122:8 -cursor-at=%s:123:8 -cursor-at=%s:124:8 -cursor-at=%s:125:8 -cursor-at=%s:128:6 -cursor-at=%s:129:6 -cursor-at=%s:130:6 -cursor-at=%s:132:3 -cursor-at=%s:146:15 -std=c++11 %s | FileCheck -check-prefix=CHECK-SPELLING %s
+// RUN: c-index-test -cursor-at=%s:69:3 -cursor-at=%s:70:11 -cursor-at=%s:73:6 -cursor-at=%s:74:6 -cursor-at=%s:77:8 -cursor-at=%s:78:8 -cursor-at=%s:79:8 -cursor-at=%s:80:8 -cursor-at=%s:81:8 -cursor-at=%s:82:8 -cursor-at=%s:85:6 -cursor-at=%s:86:6 -cursor-at=%s:87:6 -cursor-at=%s:88:6 -cursor-at=%s:91:5 -cursor-at=%s:92:5 -cursor-at=%s:93:5 -cursor-at=%s:94:5 -cursor-at=%s:95:5 -cursor-at=%s:96:5 -cursor-at=%s:97:5 -cursor-at=%s:98:5 -cursor-at=%s:100:5 -cursor-at=%s:101:5 -cursor-at=%s:104:6 -cursor-at=%s:105:6 -cursor-at=%s:106:6 -cursor-at=%s:107:6 -cursor-at=%s:108:6 -cursor-at=%s:109:6 -cursor-at=%s:110:6 -cursor-at=%s:111:6 -cursor-at=%s:113:6 -cursor-at=%s:114:6 -cursor-at=%s:117:8 -cursor-at=%s:118:8 -cursor-at=%s:120:8 -cursor-at=%s:121:8 -cursor-at=%s:122:8 -cursor-at=%s:123:8 -cursor-at=%s:124:8 -cursor-at=%s:125:8 -cursor-at=%s:128:6 -cursor-at=%s:129:6 -cursor-at=%s:130:6 -cursor-at=%s:132:3 -cursor-at=%s:146:15 -cursor-at=%s:149:6 -cursor-at=%s:150:25 -cursor-at=%s:151:6 -cursor-at=%s:152:6 -cursor-at=%s:153:6 -std=c++11 %s | FileCheck -check-prefix=CHECK-SPELLING %s
 // CHECK-SPELLING: 69:3 CXXConstructor=A:69:3 (default constructor) Extent=[69:3 - 69:6] Spelling=A ([69:3 - 69:4])
 // CHECK-SPELLING: 70:11 CXXDestructor=~A:70:11 (virtual) Extent=[70:3 - 70:15] Spelling=~A ([70:11 - 70:13])
 // CHECK-SPELLING: 73:6 CXXMethod=operator=:73:6 Extent=[73:3 - 73:25] Spelling=operator= ([73:6 - 73:15])
-// CHECK-SPELLING: 74:6 CXXMethod=operator=:74:6 Extent=[74:3 - 74:29] Spelling=operator= ([74:6 - 74:15])
+// CHECK-SPELLING: 74:6 CXXMethod=operator=:74:6 (noexcept) Extent=[74:3 - 74:29] Spelling=operator= ([74:6 - 74:15])
 // CHECK-SPELLING: 77:8 CXXMethod=operator+:77:8 (const) Extent=[77:3 - 77:25] Spelling=operator+ ([77:8 - 77:17])
 // CHECK-SPELLING: 78:8 CXXMethod=operator-:78:8 (const) Extent=[78:3 - 78:25] Spelling=operator- ([78:8 - 78:17])
 // CHECK-SPELLING: 79:8 CXXMethod=operator~:79:8 (const) Extent=[79:3 - 79:25] Spelling=operator~ ([79:8 - 79:17])
@@ -257,8 +264,14 @@ const int operator""_toint(unsigned long
 // CHECK-SPELLING: 130:6 CXXMethod=operator():130:6 (const) Extent=[130:3 - 130:37] Spelling=operator() ([130:6 - 130:16])
 // CHECK-SPELLING: 132:12 CXXConversion=operator bool:132:12 (const) Extent=[132:3 - 132:33] Spelling=operator bool ([132:12 - 132:25])
 // CHECK-SPELLING: 146:11 FunctionDecl=operator""_toint:146:11 (Definition) Extent=[146:1 - 146:72] Spelling=operator""_toint ([146:11 - 146:27])
+// CHECK-SPELLING: 149:6 FunctionDecl=f_noexcept:149:6 (noexcept) Extent=[149:1 - 149:27] Spelling=f_noexcept ([149:6 - 149:16])
+// CHECK-SPELLING: 150:25 FunctionTemplate=f_computed_noexcept:150:25 (computed-noexcept) Extent=[150:1 - 150:73] Spelling=f_computed_noexcept ([150:25 - 150:44])
+// CHECK-SPELLING: 151:6 FunctionDecl=f_dynamic_noexcept_none:151:6 (noexcept dynamic none) Extent=[151:1 - 151:39] Spelling=f_dynamic_noexcept_none ([151:6 - 151:29])
+// CHECK-SPELLING: 152:6 FunctionDecl=f_dynamic_noexcept:152:6 (noexcept dynamic) Extent=[152:1 - 152:37] Spelling=f_dynamic_noexcept ([152:6 - 152:24])
+// CHECK-SPELLING: 153:6 FunctionDecl=f_dynamic_noexcept_any:153:6 (noexcept dynamic any) Extent=[153:1 - 153:41] Spelling=f_dynamic_noexcept_any ([153:6 - 153:28])
 
 // RUN: c-index-test -cursor-at=%s:141:13 -cursor-at=%s:141:18 -cursor-at=%s:142:11 -std=c++11 %s | FileCheck -check-prefix=CHECK-FORRANGE %s
 // CHECK-FORRANGE: 141:13 VarDecl=lv:141:13 (Definition) Extent=[141:8 - 141:17] Spelling=lv ([141:13 - 141:15])
 // CHECK-FORRANGE: 141:18 DeclRefExpr=coll:140:20 Extent=[141:18 - 141:22] Spelling=coll ([141:18 - 141:22])
 // CHECK-FORRANGE: 142:11 DeclRefExpr=lv:141:13 Extent=[142:11 - 142:13] Spelling=lv ([142:11 - 142:13])
+

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=306483&r1=306482&r2=306483&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Tue Jun 27 15:54:56 2017
@@ -809,6 +809,37 @@ static void PrintCursor(CXCursor Cursor,
     if (clang_Cursor_isObjCOptional(Cursor))
       printf(" (@optional)");
 
+    switch (clang_getCursorExceptionSpecificationType(Cursor))
+    {
+      case CXCursor_ExceptionSpecificationKind_None:
+        break;
+
+      case CXCursor_ExceptionSpecificationKind_DynamicNone:
+        printf(" (noexcept dynamic none)");
+        break;
+
+      case CXCursor_ExceptionSpecificationKind_Dynamic:
+        printf(" (noexcept dynamic)");
+        break;
+
+      case CXCursor_ExceptionSpecificationKind_MSAny:
+        printf(" (noexcept dynamic any)");
+        break;
+
+      case CXCursor_ExceptionSpecificationKind_BasicNoexcept:
+        printf(" (noexcept)");
+        break;
+
+      case CXCursor_ExceptionSpecificationKind_ComputedNoexcept:
+        printf(" (computed-noexcept)");
+        break;
+
+      case CXCursor_ExceptionSpecificationKind_Unevaluated:
+      case CXCursor_ExceptionSpecificationKind_Uninstantiated:
+      case CXCursor_ExceptionSpecificationKind_Unparsed:
+        break;
+    }
+
     {
       CXString language;
       CXString definedIn;

Modified: cfe/trunk/tools/libclang/CXType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXType.cpp?rev=306483&r1=306482&r2=306483&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXType.cpp (original)
+++ cfe/trunk/tools/libclang/CXType.cpp Tue Jun 27 15:54:56 2017
@@ -684,6 +684,24 @@ CXType clang_getCursorResultType(CXCurso
   return MakeCXType(QualType(), cxcursor::getCursorTU(C));
 }
 
+int clang_getExceptionSpecificationType(CXType X) {
+  QualType T = GetQualType(X);
+  if (T.isNull())
+    return -1;
+
+  if (const auto *FD = T->getAs<FunctionProtoType>())
+    return static_cast<int>(FD->getExceptionSpecType());
+
+  return -1;
+}
+
+int clang_getCursorExceptionSpecificationType(CXCursor C) {
+  if (clang_isDeclaration(C.kind))
+    return clang_getExceptionSpecificationType(clang_getCursorType(C));
+
+  return -1;
+}
+
 unsigned clang_isPODType(CXType X) {
   QualType T = GetQualType(X);
   if (T.isNull())

Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=306483&r1=306482&r2=306483&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Tue Jun 27 15:54:56 2017
@@ -175,6 +175,7 @@ clang_getCursorCompletionString
 clang_getCursorDefinition
 clang_getCursorDisplayName
 clang_getCursorExtent
+clang_getCursorExceptionSpecificationType
 clang_getCursorKind
 clang_getCursorKindSpelling
 clang_getCursorLanguage
@@ -210,6 +211,7 @@ clang_getElementType
 clang_getEnumConstantDeclUnsignedValue
 clang_getEnumConstantDeclValue
 clang_getEnumDeclIntegerType
+clang_getExceptionSpecificationType
 clang_getFieldDeclBitWidth
 clang_getExpansionLocation
 clang_getFile




More information about the cfe-commits mailing list