aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Korous <jkorous@apple.com>2020-09-01 16:29:36 -0700
committerJan Korous <jkorous@apple.com>2020-09-04 13:38:47 -0700
commit052f83890349822a606c916b2fee501bc087652b (patch)
tree52775cf346293957695a5f2d3bd36ddc659cdba1
parent398ba37230431b6ab263cf91bf4c03e4f2c7acb8 (diff)
downloadllvm-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.h20
-rw-r--r--clang/tools/libclang/CIndex.cpp36
-rw-r--r--clang/tools/libclang/libclang.exports3
-rw-r--r--clang/unittests/libclang/LibclangTest.cpp106
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);
+}