diff options
author | Jan Korous <jkorous@apple.com> | 2020-09-01 16:29:36 -0700 |
---|---|---|
committer | Jan Korous <jkorous@apple.com> | 2020-09-04 13:38:47 -0700 |
commit | 052f83890349822a606c916b2fee501bc087652b (patch) | |
tree | 52775cf346293957695a5f2d3bd36ddc659cdba1 | |
parent | 398ba37230431b6ab263cf91bf4c03e4f2c7acb8 (diff) | |
download | llvm-052f83890349822a606c916b2fee501bc087652b.zip llvm-052f83890349822a606c916b2fee501bc087652b.tar.gz llvm-052f83890349822a606c916b2fee501bc087652b.tar.bz2 |
[libclang] Expose couple more AST details via cursors
Differential Revision: https://reviews.llvm.org/D86991
-rw-r--r-- | clang/include/clang-c/Index.h | 20 | ||||
-rw-r--r-- | clang/tools/libclang/CIndex.cpp | 36 | ||||
-rw-r--r-- | clang/tools/libclang/libclang.exports | 3 | ||||
-rw-r--r-- | clang/unittests/libclang/LibclangTest.cpp | 106 |
4 files changed, 165 insertions, 0 deletions
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 5fa728d..4838937 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2941,6 +2941,26 @@ CINDEX_LINKAGE void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability); /** + * If cursor refers to a variable declaration and it has initializer returns + * cursor referring to the initializer otherwise return null cursor. + */ +CINDEX_LINKAGE CXCursor clang_Cursor_getVarDeclInitializer(CXCursor cursor); + +/** + * If cursor refers to a variable declaration that has global storage returns 1. + * If cursor refers to a variable declaration that doesn't have global storage + * returns 0. Otherwise returns -1. + */ +CINDEX_LINKAGE int clang_Cursor_hasVarDeclGlobalStorage(CXCursor cursor); + +/** + * If cursor refers to a variable declaration that has external storage + * returns 1. If cursor refers to a variable declaration that doesn't have + * external storage returns 0. Otherwise returns -1. + */ +CINDEX_LINKAGE int clang_Cursor_hasVarDeclExternalStorage(CXCursor cursor); + +/** * Describe the "language" of the entity referred to by a cursor. */ enum CXLanguageKind { diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 683b517..87138cd 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -8851,6 +8851,42 @@ void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) { clang_disposeCXTUResourceUsage(Usage); } +CXCursor clang_Cursor_getVarDeclInitializer(CXCursor cursor) { + const Decl *const D = getCursorDecl(cursor); + if (!D) + return clang_getNullCursor(); + const auto *const VD = dyn_cast<VarDecl>(D); + if (!VD) + return clang_getNullCursor(); + const Expr *const Init = VD->getInit(); + if (!Init) + return clang_getNullCursor(); + + return cxcursor::MakeCXCursor(Init, VD, cxcursor::getCursorTU(cursor)); +} + +int clang_Cursor_hasVarDeclGlobalStorage(CXCursor cursor) { + const Decl *const D = getCursorDecl(cursor); + if (!D) + return -1; + const auto *const VD = dyn_cast<VarDecl>(D); + if (!VD) + return -1; + + return VD->hasGlobalStorage(); +} + +int clang_Cursor_hasVarDeclExternalStorage(CXCursor cursor) { + const Decl *const D = getCursorDecl(cursor); + if (!D) + return -1; + const auto *const VD = dyn_cast<VarDecl>(D); + if (!VD) + return -1; + + return VD->hasExternalStorage(); +} + //===----------------------------------------------------------------------===// // Misc. utility functions. //===----------------------------------------------------------------------===// diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index defbaa9..618f99f 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -382,3 +382,6 @@ clang_PrintingPolicy_setProperty clang_PrintingPolicy_dispose clang_install_aborting_llvm_fatal_error_handler clang_uninstall_llvm_fatal_error_handler +clang_Cursor_getVarDeclInitializer +clang_Cursor_hasVarDeclGlobalStorage +clang_Cursor_hasVarDeclExternalStorage diff --git a/clang/unittests/libclang/LibclangTest.cpp b/clang/unittests/libclang/LibclangTest.cpp index e2e3a8e..27fe10d 100644 --- a/clang/unittests/libclang/LibclangTest.cpp +++ b/clang/unittests/libclang/LibclangTest.cpp @@ -736,3 +736,109 @@ TEST_F(LibclangSerializationTest, TokenKindsAreCorrectAfterLoading) { CheckTokenKinds(); } + +TEST_F(LibclangParseTest, clang_getVarDeclInitializer) { + std::string Main = "main.cpp"; + WriteFile(Main, "int foo() { return 5; }; const int a = foo();"); + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, + 0, TUFlags); + + CXCursor C = clang_getTranslationUnitCursor(ClangTU); + clang_visitChildren( + C, + [](CXCursor cursor, CXCursor parent, + CXClientData client_data) -> CXChildVisitResult { + if (clang_getCursorKind(cursor) == CXCursor_VarDecl) { + const CXCursor Initializer = clang_Cursor_getVarDeclInitializer(cursor); + EXPECT_FALSE(clang_Cursor_isNull(Initializer)); + CXString Spelling = clang_getCursorSpelling(Initializer); + const char* const SpellingCSstr = clang_getCString(Spelling); + EXPECT_TRUE(SpellingCSstr); + EXPECT_EQ(std::string(SpellingCSstr), std::string("foo")); + clang_disposeString(Spelling); + return CXChildVisit_Break; + } + return CXChildVisit_Continue; + }, + nullptr); +} + +TEST_F(LibclangParseTest, clang_hasVarDeclGlobalStorageFalse) { + std::string Main = "main.cpp"; + WriteFile(Main, "void foo() { int a; }"); + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, + 0, TUFlags); + + CXCursor C = clang_getTranslationUnitCursor(ClangTU); + clang_visitChildren( + C, + [](CXCursor cursor, CXCursor parent, + CXClientData client_data) -> CXChildVisitResult { + if (clang_getCursorKind(cursor) == CXCursor_VarDecl) { + EXPECT_FALSE(clang_Cursor_hasVarDeclGlobalStorage(cursor)); + return CXChildVisit_Break; + } + return CXChildVisit_Continue; + }, + nullptr); +} + +TEST_F(LibclangParseTest, clang_Cursor_hasVarDeclGlobalStorageTrue) { + std::string Main = "main.cpp"; + WriteFile(Main, "int a;"); + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, + 0, TUFlags); + + CXCursor C = clang_getTranslationUnitCursor(ClangTU); + clang_visitChildren( + C, + [](CXCursor cursor, CXCursor parent, + CXClientData client_data) -> CXChildVisitResult { + if (clang_getCursorKind(cursor) == CXCursor_VarDecl) { + EXPECT_TRUE(clang_Cursor_hasVarDeclGlobalStorage(cursor)); + return CXChildVisit_Break; + } + return CXChildVisit_Continue; + }, + nullptr); +} + +TEST_F(LibclangParseTest, clang_Cursor_hasVarDeclExternalStorageFalse) { + std::string Main = "main.cpp"; + WriteFile(Main, "int a;"); + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, + 0, TUFlags); + + CXCursor C = clang_getTranslationUnitCursor(ClangTU); + clang_visitChildren( + C, + [](CXCursor cursor, CXCursor parent, + CXClientData client_data) -> CXChildVisitResult { + if (clang_getCursorKind(cursor) == CXCursor_VarDecl) { + EXPECT_FALSE(clang_Cursor_hasVarDeclExternalStorage(cursor)); + return CXChildVisit_Break; + } + return CXChildVisit_Continue; + }, + nullptr); +} + +TEST_F(LibclangParseTest, clang_Cursor_hasVarDeclExternalStorageTrue) { + std::string Main = "main.cpp"; + WriteFile(Main, "extern int a;"); + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, + 0, TUFlags); + + CXCursor C = clang_getTranslationUnitCursor(ClangTU); + clang_visitChildren( + C, + [](CXCursor cursor, CXCursor parent, + CXClientData client_data) -> CXChildVisitResult { + if (clang_getCursorKind(cursor) == CXCursor_VarDecl) { + EXPECT_TRUE(clang_Cursor_hasVarDeclExternalStorage(cursor)); + return CXChildVisit_Break; + } + return CXChildVisit_Continue; + }, + nullptr); +} |