From 0c27e4b36bd031fda61a8a457e33221fc2177370 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 11 Apr 2012 19:32:19 +0000 Subject: [PATCH] [libclang] Introduce a couple of functions to make it convenient to get at the parameters (and their types) of a function or objc method cursor. int clang_Cursor_getNumArguments(CXCursor C); CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i); rdar://11201527 llvm-svn: 154523 --- clang/include/clang-c/Index.h | 20 +++++++++++++++-- clang/test/Index/print-typekind.c | 2 +- clang/test/Index/print-typekind.m | 4 ++-- clang/tools/c-index-test/c-index-test.c | 16 ++++++++++++++ clang/tools/libclang/CXCursor.cpp | 29 +++++++++++++++++++++++++ clang/tools/libclang/CXType.cpp | 6 ++--- clang/tools/libclang/libclang.exports | 2 ++ 7 files changed, 71 insertions(+), 8 deletions(-) diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 4568a764e0ec..18316b4d33c1 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2524,6 +2524,22 @@ CINDEX_LINKAGE long long clang_getEnumConstantDeclValue(CXCursor C); */ CINDEX_LINKAGE unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C); +/** + * \brief Retrieve the number of non-variadic arguments associated with a given + * cursor. + * + * If a cursor that is not a function or method is passed in, -1 is returned. + */ +CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C); + +/** + * \brief Retrieve the argument cursor of a function or method. + * + * If a cursor that is not a function or method is passed in or the index + * exceeds the number of arguments, an invalid cursor is returned. + */ +CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i); + /** * \determine Determine whether two CXTypes represent the same type. * @@ -2598,9 +2614,9 @@ CINDEX_LINKAGE CXType clang_getResultType(CXType T); /** * \brief Retrieve the number of non-variadic arguments associated with a function type. * - * If a non-function type is passed in, UINT_MAX is returned. + * If a non-function type is passed in, -1 is returned. */ -CINDEX_LINKAGE unsigned clang_getNumArgTypes(CXType T); +CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); /** * \brief Retrieve the type of an argument of a function type. diff --git a/clang/test/Index/print-typekind.c b/clang/test/Index/print-typekind.c index c6583dbff38b..294aea77ed71 100644 --- a/clang/test/Index/print-typekind.c +++ b/clang/test/Index/print-typekind.c @@ -10,7 +10,7 @@ typedef int ArrayType[5]; // RUN: c-index-test -test-print-typekind %s | FileCheck %s // CHECK: TypedefDecl=FooType:1:13 (Definition) typekind=Typedef [canonical=Int] [isPOD=1] // CHECK: VarDecl=p:2:6 typekind=Pointer [isPOD=1] -// CHECK: FunctionDecl=f:3:6 (Definition) typekind=FunctionProto [canonical=FunctionProto] [result=Pointer] [isPOD=0] +// CHECK: FunctionDecl=f:3:6 (Definition) typekind=FunctionProto [canonical=FunctionProto] [result=Pointer] [args= Pointer Pointer Typedef] [isPOD=0] // CHECK: ParmDecl=p:3:13 (Definition) typekind=Pointer [isPOD=1] // CHECK: ParmDecl=x:3:22 (Definition) typekind=Pointer [isPOD=1] // CHECK: ParmDecl=z:3:33 (Definition) typekind=Typedef [canonical=Int] [isPOD=1] diff --git a/clang/test/Index/print-typekind.m b/clang/test/Index/print-typekind.m index 528919527098..9db192938f44 100644 --- a/clang/test/Index/print-typekind.m +++ b/clang/test/Index/print-typekind.m @@ -1,10 +1,10 @@ @interface Foo @property (readonly) id x; -(int) mymethod; +-(int) mymethod2:(int)x blah:(float)y; @end // RUN: c-index-test -test-print-typekind %s | FileCheck %s // CHECK: ObjCPropertyDecl=x:2:25 typekind=Typedef [canonical=ObjCObjectPointer] // CHECK: ObjCInstanceMethodDecl=mymethod:3:8 typekind=Invalid [result=Int] - - +// CHECK: ObjCInstanceMethodDecl=mymethod2:blah::4:8 typekind=Invalid [result=Int] [args= Int Float] diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index f82d2d2820c3..3dfc732d2bdb 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -663,6 +663,22 @@ static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p, clang_disposeString(RS); } } + /* Print the argument types if they exist. */ + { + int numArgs = clang_Cursor_getNumArguments(cursor); + if (numArgs != -1 && numArgs != 0) { + printf(" [args="); + for (int i = 0; i < numArgs; ++i) { + CXType T = clang_getCursorType(clang_Cursor_getArgument(cursor, i)); + if (T.kind != CXType_Invalid) { + CXString S = clang_getTypeKindSpelling(T.kind); + printf(" %s", clang_getCString(S)); + clang_disposeString(S); + } + } + printf("]"); + } + } /* Print if this is a non-POD type. */ printf(" [isPOD=%d]", clang_isPODType(T)); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 8371a4f273cf..d84cf29098fe 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -1024,6 +1024,35 @@ CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor cursor) { return getCursorTU(cursor); } +int clang_Cursor_getNumArguments(CXCursor C) { + if (clang_isDeclaration(C.kind)) { + Decl *D = cxcursor::getCursorDecl(C); + if (const ObjCMethodDecl *MD = dyn_cast_or_null(D)) + return MD->param_size(); + if (const FunctionDecl *FD = dyn_cast_or_null(D)) + return FD->param_size(); + } + + return -1; +} + +CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i) { + if (clang_isDeclaration(C.kind)) { + Decl *D = cxcursor::getCursorDecl(C); + if (ObjCMethodDecl *MD = dyn_cast_or_null(D)) { + if (i < MD->param_size()) + return cxcursor::MakeCXCursor(MD->param_begin()[i], + cxcursor::getCursorTU(C)); + } else if (FunctionDecl *FD = dyn_cast_or_null(D)) { + if (i < FD->param_size()) + return cxcursor::MakeCXCursor(FD->param_begin()[i], + cxcursor::getCursorTU(C)); + } + } + + return clang_getNullCursor(); +} + } // end: extern "C" //===----------------------------------------------------------------------===// diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index 0d4a5195abec..850fac129ef1 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -455,10 +455,10 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { return CXCallingConv_Invalid; } -unsigned clang_getNumArgTypes(CXType X) { +int clang_getNumArgTypes(CXType X) { QualType T = GetQualType(X); if (T.isNull()) - return UINT_MAX; + return -1; if (const FunctionProtoType *FD = T->getAs()) { return FD->getNumArgs(); @@ -468,7 +468,7 @@ unsigned clang_getNumArgTypes(CXType X) { return 0; } - return UINT_MAX; + return -1; } CXType clang_getArgType(CXType X, unsigned i) { diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index 95cfb025cbaf..07bdece8eb98 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -4,6 +4,8 @@ clang_CXIndex_getGlobalOptions clang_CXIndex_setGlobalOptions clang_CXXMethod_isStatic clang_CXXMethod_isVirtual +clang_Cursor_getArgument +clang_Cursor_getNumArguments clang_Cursor_getSpellingNameRange clang_Cursor_getTranslationUnit clang_Cursor_getObjCSelectorIndex