From e570ede5d1f88e95003ecde3b528c139123faacb Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Mon, 7 Apr 2014 14:59:13 +0000 Subject: [PATCH] libclang: add clang_CXXMethod_isConst API that allows to determine if a C++ member function or member function template is declared 'const' Patch by Kevin Funk with testcase updates by me. llvm-svn: 205714 --- clang/include/clang-c/Index.h | 6 ++++ clang/test/Index/load-classes.cpp | 30 ++++++++++++++++--- .../test/Index/recursive-cxx-member-calls.cpp | 18 +++++------ clang/tools/c-index-test/c-index-test.c | 2 ++ clang/tools/libclang/CIndex.cpp | 10 +++++++ clang/tools/libclang/libclang.exports | 1 + 6 files changed, 54 insertions(+), 13 deletions(-) diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 7eff0a4216a7..386e0ffc315b 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -4192,6 +4192,12 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C); */ CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C); +/** + * \brief Determine if a C++ member function or member function template is + * declared 'const'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(CXCursor C); + /** * \brief Given a cursor that represents a template, determine * the cursor kind of the specializations would be generated by instantiating diff --git a/clang/test/Index/load-classes.cpp b/clang/test/Index/load-classes.cpp index 9790d9e6f41d..3b66be5398af 100644 --- a/clang/test/Index/load-classes.cpp +++ b/clang/test/Index/load-classes.cpp @@ -7,13 +7,24 @@ protected: ~X(); private: operator X*(); + + void constMemberFunction() const; + template + void constMemberFunctionTemplate() const; + + static void staticMemberFunction(); + template + static void staticMemberFunctionTemplate(); + + virtual void virtualMemberFunction(); + virtual void pureVirtualMemberFunction() = 0; }; X::X(int value) { } // RUN: c-index-test -test-load-source all %s | FileCheck %s -// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 10:2] +// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 21:2] // CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 Extent=[4:3 - 4:15] [access=public] // FIXME: missing TypeRef in the constructor name // CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14] @@ -21,10 +32,21 @@ X::X(int value) { // FIXME: missing TypeRef in the constructor name // CHECK: load-classes.cpp:5:14: ParmDecl=x:5:14 (Definition) Extent=[5:5 - 5:15] // CHECK: load-classes.cpp:5:11: TypeRef=struct X:3:8 Extent=[5:11 - 5:12] +// CHECK: load-classes.cpp:6:1: CXXAccessSpecifier=:6:1 (Definition) Extent=[6:1 - 6:11] [access=protected] // CHECK: load-classes.cpp:7:3: CXXDestructor=~X:7:3 Extent=[7:3 - 7:7] [access=protected] // FIXME: missing TypeRef in the destructor name +// CHECK: load-classes.cpp:8:1: CXXAccessSpecifier=:8:1 (Definition) Extent=[8:1 - 8:9] [access=private] // CHECK: load-classes.cpp:9:3: CXXConversion=operator X *:9:3 Extent=[9:3 - 9:16] [access=private] // CHECK: load-classes.cpp:9:12: TypeRef=struct X:3:8 Extent=[9:12 - 9:13] -// CHECK: load-classes.cpp:12:4: CXXConstructor=X:12:4 (Definition) Extent=[12:1 - 13:2] [access=public] -// CHECK: load-classes.cpp:12:1: TypeRef=struct X:3:8 Extent=[12:1 - 12:2] -// CHECK: load-classes.cpp:12:10: ParmDecl=value:12:10 (Definition) Extent=[12:6 - 12:15] +// CHECK: load-classes.cpp:11:8: CXXMethod=constMemberFunction:11:8 (const) Extent=[11:3 - 11:35] [access=private] +// CHECK: load-classes.cpp:13:8: FunctionTemplate=constMemberFunctionTemplate:13:8 (const) Extent=[12:3 - 13:43] [access=private] +// CHECK: load-classes.cpp:12:21: TemplateTypeParameter=T:12:21 (Definition) Extent=[12:12 - 12:22] [access=public] +// CHECK: load-classes.cpp:15:15: CXXMethod=staticMemberFunction:15:15 (static) Extent=[15:3 - 15:37] [access=private] +// CHECK: load-classes.cpp:17:15: FunctionTemplate=staticMemberFunctionTemplate:17:15 (static) Extent=[16:3 - 17:45] [access=private] +// CHECK: load-classes.cpp:16:21: TemplateTypeParameter=T:16:21 (Definition) Extent=[16:12 - 16:22] [access=public] +// CHECK: load-classes.cpp:19:16: CXXMethod=virtualMemberFunction:19:16 (virtual) Extent=[19:3 - 19:39] [access=private] +// CHECK: load-classes.cpp:20:16: CXXMethod=pureVirtualMemberFunction:20:16 (virtual) (pure) Extent=[20:3 - 20:47] [access=private] +// CHECK: load-classes.cpp:23:4: CXXConstructor=X:23:4 (Definition) Extent=[23:1 - 24:2] [access=public] +// CHECK: load-classes.cpp:23:1: TypeRef=struct X:3:8 Extent=[23:1 - 23:2] +// CHECK: load-classes.cpp:23:10: ParmDecl=value:23:10 (Definition) Extent=[23:6 - 23:15] +// CHECK: load-classes.cpp:23:17: CompoundStmt= Extent=[23:17 - 24:2] diff --git a/clang/test/Index/recursive-cxx-member-calls.cpp b/clang/test/Index/recursive-cxx-member-calls.cpp index ab30d43905f9..34a56529548f 100644 --- a/clang/test/Index/recursive-cxx-member-calls.cpp +++ b/clang/test/Index/recursive-cxx-member-calls.cpp @@ -1680,17 +1680,17 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) { // CHECK: 49:60: MemberRef=Length:44:10 Extent=[49:60 - 49:66] // CHECK: 49:67: DeclRefExpr=length:49:38 Extent=[49:67 - 49:73] // CHECK: 49:75: CompoundStmt= Extent=[49:75 - 49:77] -// CHECK: 50:12: CXXMethod=end:50:12 (Definition) Extent=[50:3 - 50:40] +// CHECK: 50:12: CXXMethod=end:50:12 (Definition) (const) Extent=[50:3 - 50:40] [access=public] // CHECK: 50:3: TypeRef=iterator:40:23 Extent=[50:3 - 50:11] // CHECK: 50:24: CompoundStmt= Extent=[50:24 - 50:40] // CHECK: 50:26: ReturnStmt= Extent=[50:26 - 50:37] // CHECK: 50:33: MemberRefExpr=Data:43:15 Extent=[50:33 - 50:37] -// CHECK: 51:10: CXXMethod=size:51:10 (Definition) Extent=[51:3 - 51:41] +// CHECK: 51:10: CXXMethod=size:51:10 (Definition) (const) Extent=[51:3 - 51:41] [access=public] // CHECK: 51:3: TypeRef=size_t:2:25 Extent=[51:3 - 51:9] // CHECK: 51:23: CompoundStmt= Extent=[51:23 - 51:41] // CHECK: 51:25: ReturnStmt= Extent=[51:25 - 51:38] // CHECK: 51:32: MemberRefExpr=Length:44:10 Extent=[51:32 - 51:38] -// CHECK: 52:8: CXXMethod=startswith:52:8 (Definition) Extent=[52:3 - 55:4] +// CHECK: 52:8: CXXMethod=startswith:52:8 (Definition) (const) Extent=[52:3 - 55:4] [access=public] // CHECK: 52:29: ParmDecl=Prefix:52:29 (Definition) Extent=[52:19 - 52:35] // CHECK: 52:19: TypeRef=class llvm::StringRef:38:7 Extent=[52:19 - 52:28] // CHECK: 52:43: CompoundStmt= Extent=[52:43 - 55:4] @@ -1713,7 +1713,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) { // CHECK: 54:44: MemberRefExpr=Length:44:10 SingleRefName=[54:44 - 54:50] RefName=[54:44 - 54:50] Extent=[54:37 - 54:50] // CHECK: 54:37: DeclRefExpr=Prefix:52:29 Extent=[54:37 - 54:43] // CHECK: 54:55: IntegerLiteral= Extent=[54:55 - 54:56] -// CHECK: 56:8: CXXMethod=endswith:56:8 (Definition) Extent=[56:3 - 59:4] +// CHECK: 56:8: CXXMethod=endswith:56:8 (Definition) (const) Extent=[56:3 - 59:4] [access=public] // CHECK: 56:27: ParmDecl=Suffix:56:27 (Definition) Extent=[56:17 - 56:33] // CHECK: 56:17: TypeRef=class llvm::StringRef:38:7 Extent=[56:17 - 56:26] // CHECK: 56:41: CompoundStmt= Extent=[56:41 - 59:4] @@ -1740,7 +1740,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) { // CHECK: 58:57: MemberRefExpr=Length:44:10 SingleRefName=[58:57 - 58:63] RefName=[58:57 - 58:63] Extent=[58:50 - 58:63] // CHECK: 58:50: DeclRefExpr=Suffix:56:27 Extent=[58:50 - 58:56] // CHECK: 58:68: IntegerLiteral= Extent=[58:68 - 58:69] -// CHECK: 60:13: CXXMethod=substr:60:13 (Definition) Extent=[60:3 - 62:4] +// CHECK: 60:13: CXXMethod=substr:60:13 (Definition) (const) Extent=[60:3 - 62:4] [access=public] // CHECK: 60:3: TypeRef=class llvm::StringRef:38:7 Extent=[60:3 - 60:12] // CHECK: 60:27: ParmDecl=Start:60:27 (Definition) Extent=[60:20 - 60:32] // CHECK: 60:20: TypeRef=size_t:2:25 Extent=[60:20 - 60:26] @@ -1769,7 +1769,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) { // CHECK: 66:7: ClassDecl=IdentifierInfo:66:7 (Definition) Extent=[66:1 - 80:2] // CHECK: 67:1: CXXAccessSpecifier=:67:1 (Definition) Extent=[67:1 - 67:8] // CHECK: 67:8: CXXConstructor=IdentifierInfo:67:8 Extent=[67:8 - 67:24] -// CHECK: 68:15: CXXMethod=getNameStart:68:15 (Definition) Extent=[68:3 - 71:4] +// CHECK: 68:15: CXXMethod=getNameStart:68:15 (Definition) (const) Extent=[68:3 - 71:4] [access=public] // CHECK: 68:36: CompoundStmt= Extent=[68:36 - 71:4] // CHECK: 69:5: DeclStmt= Extent=[69:5 - 69:65] // CHECK: 69:54: TypedefDecl=actualtype:69:54 (Definition) Extent=[69:5 - 69:64] @@ -1781,7 +1781,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) { // CHECK: 70:13: CStyleCastExpr= Extent=[70:13 - 70:38] // CHECK: 70:20: TypeRef=actualtype:69:54 Extent=[70:20 - 70:30] // CHECK: 70:34: CXXThisExpr= Extent=[70:34 - 70:38] -// CHECK: 72:12: CXXMethod=getLength:72:12 (Definition) Extent=[72:3 - 76:4] +// CHECK: 72:12: CXXMethod=getLength:72:12 (Definition) (const) Extent=[72:3 - 76:4] [access=public] // CHECK: 72:30: CompoundStmt= Extent=[72:30 - 76:4] // CHECK: 73:5: DeclStmt= Extent=[73:5 - 73:65] // CHECK: 73:54: TypedefDecl=actualtype:73:54 (Definition) Extent=[73:5 - 73:64] @@ -1820,7 +1820,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) { // CHECK: 75:55: IntegerLiteral= Extent=[75:55 - 75:56] // CHECK: 75:61: UnexposedExpr= Extent=[75:61 - 75:62] // CHECK: 75:61: IntegerLiteral= Extent=[75:61 - 75:62] -// CHECK: 77:19: CXXMethod=getName:77:19 (Definition) Extent=[77:3 - 79:4] +// CHECK: 77:19: CXXMethod=getName:77:19 (Definition) (const) Extent=[77:3 - 79:4] [access=public] // CHECK: 77:35: CompoundStmt= Extent=[77:35 - 79:4] // CHECK: 78:5: ReturnStmt= Extent=[78:5 - 78:56] // CHECK: 78:12: CallExpr= Extent=[78:12 - 78:56] @@ -1858,7 +1858,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) { // CHECK: 90:5: ReturnStmt= Extent=[90:5 - 90:17] // CHECK: 90:12: UnaryOperator= Extent=[90:12 - 90:17] // CHECK: 90:13: CXXThisExpr= Extent=[90:13 - 90:17] -// CHECK: 92:5: CXXMethod=Default:92:5 (Definition) Extent=[92:3 - 94:4] +// CHECK: 92:5: CXXMethod=Default:92:5 (Definition) (const) Extent=[92:3 - 94:4] [access=public] // CHECK: 92:23: ParmDecl=Value:92:23 (Definition) Extent=[92:13 - 92:28] // CHECK: 92:36: CompoundStmt= Extent=[92:36 - 94:4] // CHECK: 93:5: ReturnStmt= Extent=[93:5 - 93:17] diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index f6b5510292b9..6a48196a45ca 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -768,6 +768,8 @@ static void PrintCursor(CXCursor Cursor, printf(" (static)"); if (clang_CXXMethod_isVirtual(Cursor)) printf(" (virtual)"); + if (clang_CXXMethod_isConst(Cursor)) + printf(" (const)"); if (clang_CXXMethod_isPureVirtual(Cursor)) printf(" (pure)"); if (clang_Cursor_isVariadic(Cursor)) diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 04797a98d360..50e7c682048a 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -6403,6 +6403,16 @@ unsigned clang_CXXMethod_isPureVirtual(CXCursor C) { return (Method && Method->isVirtual() && Method->isPure()) ? 1 : 0; } +unsigned clang_CXXMethod_isConst(CXCursor C) { + if (!clang_isDeclaration(C.kind)) + return 0; + + const Decl *D = cxcursor::getCursorDecl(C); + const CXXMethodDecl *Method = + D ? dyn_cast_or_null(D->getAsFunction()) : 0; + return (Method && (Method->getTypeQualifiers() & Qualifiers::Const)) ? 1 : 0; +} + unsigned clang_CXXMethod_isStatic(CXCursor C) { if (!clang_isDeclaration(C.kind)) return 0; diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index 37b6159bd0f9..df8d85c01f46 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -2,6 +2,7 @@ clang_CXCursorSet_contains clang_CXCursorSet_insert clang_CXIndex_getGlobalOptions clang_CXIndex_setGlobalOptions +clang_CXXMethod_isConst clang_CXXMethod_isPureVirtual clang_CXXMethod_isStatic clang_CXXMethod_isVirtual