summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorJonathan Coe <jbcoe@me.com>2017-06-27 22:54:56 +0000
committerJonathan Coe <jbcoe@me.com>2017-06-27 22:54:56 +0000
commit0a5b03b659d03392f43aed3003989a7a3fcbab62 (patch)
treeabc9d40cf7f5a41b7d4b4b1c8db8cc65f56e7605 /clang
parent6f75e2dd48ca7ce22ca7e97684729259ce5ebe57 (diff)
downloadbcm5719-llvm-0a5b03b659d03392f43aed3003989a7a3fcbab62.tar.gz
bcm5719-llvm-0a5b03b659d03392f43aed3003989a7a3fcbab62.zip
[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 llvm-svn: 306483
Diffstat (limited to 'clang')
-rw-r--r--clang/bindings/python/clang/cindex.py44
-rw-r--r--clang/bindings/python/tests/test_exception_specification_kind.py27
-rw-r--r--clang/include/clang-c/Index.h69
-rw-r--r--clang/test/Index/get-cursor.cpp17
-rw-r--r--clang/tools/c-index-test/c-index-test.c31
-rw-r--r--clang/tools/libclang/CXType.cpp18
-rw-r--r--clang/tools/libclang/libclang.exports2
7 files changed, 205 insertions, 3 deletions
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 8440b0aabe0..5e70bde770f 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1367,6 +1367,30 @@ TemplateArgumentKind.DECLARATION = TemplateArgumentKind(2)
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."""
diff --git a/clang/bindings/python/tests/test_exception_specification_kind.py b/clang/bindings/python/tests/test_exception_specification_kind.py
new file mode 100644
index 00000000000..543d47f7db9
--- /dev/null
+++ b/clang/bindings/python/tests/test_exception_specification_kind.py
@@ -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
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 4241e43a969..f404e6d72ec 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -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_getFunctionTypeCallingConv(CXType T);
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_isFunctionTypeVariadic(CXType T);
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.
*/
diff --git a/clang/test/Index/get-cursor.cpp b/clang/test/Index/get-cursor.cpp
index 27f75938fed..8aa12d5bc31 100644
--- a/clang/test/Index/get-cursor.cpp
+++ b/clang/test/Index/get-cursor.cpp
@@ -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 long val) { return int(val); }
// 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 long val) { return int(val); }
// 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])
+
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index d25ae117a68..1e925569dd9 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -809,6 +809,37 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
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;
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index df9aa656b5d..5875459734a 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -684,6 +684,24 @@ CXType clang_getCursorResultType(CXCursor C) {
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())
diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports
index 187d4749ebc..e78899e4c75 100644
--- a/clang/tools/libclang/libclang.exports
+++ b/clang/tools/libclang/libclang.exports
@@ -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
OpenPOWER on IntegriCloud