From: Douglas Gregor Date: Wed, 22 Sep 2010 21:22:29 +0000 (+0000) Subject: Implement libclang API functions for retrieving the lexical and X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2be5bc9ad3981347a000742f81b91ab3080f1214;p=clang Implement libclang API functions for retrieving the lexical and semantic parents of the given cursor. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114587 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 7358b55d1d..ab7674a794 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -1351,6 +1351,73 @@ CINDEX_LINKAGE enum CXLanguageKind { */ CINDEX_LINKAGE enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor); + +/** + * \brief Determine the semantic parent of the given cursor. + * + * The semantic parent of a cursor is the cursor that semantically contains + * the given \p cursor. For many declarations, the lexical and semantic parents + * are equivalent (the lexical parent is returned by + * \c clang_getCursorLexicalParent()). They diverge when declarations or + * definitions are provided out-of-line. For example: + * + * \code + * class C { + * void f(); + * }; + * + * void C::f() { } + * \endcode + * + * In the out-of-line definition of \c C::f, the semantic parent is the + * the class \c C, of which this function is a member. The lexical parent is + * the place where the declaration actually occurs in the source code; in this + * case, the definition occurs in the translation unit. In general, the + * lexical parent for a given entity can change without affecting the semantics + * of the program, and the lexical parent of different declarations of the + * same entity may be different. Changing the semantic parent of a declaration, + * on the other hand, can have a major impact on semantics, and redeclarations + * of a particular entity should all have the same semantic context. + * + * In the example above, both declarations of \c C::f have \c C as their + * semantic context, while the lexical context of the first \c C::f is \c C + * and the lexical context of the second \c C::f is the translation unit. + */ +CINDEX_LINKAGE CXCursor clang_getCursorSemanticParent(CXCursor cursor); + +/** + * \brief Determine the lexical parent of the given cursor. + * + * The lexical parent of a cursor is the cursor in which the given \p cursor + * was actually written. For many declarations, the lexical and semantic parents + * are equivalent (the semantic parent is returned by + * \c clang_getCursorSemanticParent()). They diverge when declarations or + * definitions are provided out-of-line. For example: + * + * \code + * class C { + * void f(); + * }; + * + * void C::f() { } + * \endcode + * + * In the out-of-line definition of \c C::f, the semantic parent is the + * the class \c C, of which this function is a member. The lexical parent is + * the place where the declaration actually occurs in the source code; in this + * case, the definition occurs in the translation unit. In general, the + * lexical parent for a given entity can change without affecting the semantics + * of the program, and the lexical parent of different declarations of the + * same entity may be different. Changing the semantic parent of a declaration, + * on the other hand, can have a major impact on semantics, and redeclarations + * of a particular entity should all have the same semantic context. + * + * In the example above, both declarations of \c C::f have \c C as their + * semantic context, while the lexical context of the first \c C::f is \c C + * and the lexical context of the second \c C::f is the translation unit. + */ +CINDEX_LINKAGE CXCursor clang_getCursorLexicalParent(CXCursor cursor); + /** * @} */ diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index c0cecffd01..6d6938a158 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -4018,6 +4018,36 @@ CXLanguageKind clang_getCursorLanguage(CXCursor cursor) { return CXLanguage_Invalid; } + +CXCursor clang_getCursorSemanticParent(CXCursor cursor) { + if (clang_isDeclaration(cursor.kind)) { + if (Decl *D = getCursorDecl(cursor)) { + DeclContext *DC = D->getDeclContext(); + return MakeCXCursor(cast(DC), getCursorASTUnit(cursor)); + } + } + + if (clang_isStatement(cursor.kind) || clang_isExpression(cursor.kind)) { + if (Decl *D = getCursorDecl(cursor)) + return MakeCXCursor(D, getCursorASTUnit(cursor)); + } + + return clang_getNullCursor(); +} + +CXCursor clang_getCursorLexicalParent(CXCursor cursor) { + if (clang_isDeclaration(cursor.kind)) { + if (Decl *D = getCursorDecl(cursor)) { + DeclContext *DC = D->getLexicalDeclContext(); + return MakeCXCursor(cast(DC), getCursorASTUnit(cursor)); + } + } + + // FIXME: Note that we can't easily compute the lexical context of a + // statement or expression, so we return nothing. + return clang_getNullCursor(); +} + } // end: extern "C" diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports index 6b30da4d2b..da1a6eefc6 100644 --- a/tools/libclang/libclang.darwin.exports +++ b/tools/libclang/libclang.darwin.exports @@ -45,10 +45,12 @@ _clang_getCursorExtent _clang_getCursorKind _clang_getCursorKindSpelling _clang_getCursorLanguage +_clang_getCursorLexicalParent _clang_getCursorLinkage _clang_getCursorLocation _clang_getCursorReferenced _clang_getCursorResultType +_clang_getCursorSemanticParent _clang_getCursorSpelling _clang_getCursorType _clang_getCursorUSR diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 798ec32218..511c85d26f 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -45,10 +45,12 @@ clang_getCursorExtent clang_getCursorKind clang_getCursorKindSpelling clang_getCursorLanguage +clang_getCursorLexicalParent clang_getCursorLinkage clang_getCursorLocation clang_getCursorReferenced clang_getCursorResultType +clang_getCursorSemanticParent clang_getCursorSpelling clang_getCursorType clang_getCursorUSR