arphaman created this revision. arphaman added a reviewer: dexonsmith. There's a bug in libclang in which it tries to evaluate a statement cursor as a declaration cursor, because that statement still has a pointer to the declaration parent. This patch fixes it.
rdar://38888477 Repository: rC Clang https://reviews.llvm.org/D49051 Files: tools/libclang/CIndex.cpp unittests/libclang/LibclangTest.cpp Index: unittests/libclang/LibclangTest.cpp =================================================================== --- unittests/libclang/LibclangTest.cpp +++ unittests/libclang/LibclangTest.cpp @@ -461,6 +461,47 @@ clang_disposeSourceRangeList(Ranges); } +TEST_F(LibclangParseTest, EvaluateChildExpression) { + std::string Main = "main.m"; + WriteFile(Main, "#define kFOO @\"foo\"\n" + "void foobar(void) {\n" + " {kFOO;}\n" + "}\n"); + 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_FunctionDecl) { + int numberedStmt = 0; + clang_visitChildren( + cursor, + [](CXCursor cursor, CXCursor parent, + CXClientData client_data) -> CXChildVisitResult { + int &numberedStmt = *((int *)client_data); + if (clang_getCursorKind(cursor) == CXCursor_CompoundStmt) { + if (numberedStmt) { + CXEvalResult RE = clang_Cursor_Evaluate(cursor); + EXPECT_NE(RE, nullptr); + EXPECT_EQ(clang_EvalResult_getKind(RE), + CXEval_ObjCStrLiteral); + return CXChildVisit_Break; + } + numberedStmt++; + } + return CXChildVisit_Recurse; + }, + &numberedStmt); + EXPECT_EQ(numberedStmt, 1); + } + return CXChildVisit_Continue; + }, + nullptr); +} + class LibclangReparseTest : public LibclangParseTest { public: void DisplayDiagnostics() { Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -3890,18 +3890,20 @@ } CXEvalResult clang_Cursor_Evaluate(CXCursor C) { - const Decl *D = getCursorDecl(C); - if (D) { - const Expr *expr = nullptr; - if (auto *Var = dyn_cast<VarDecl>(D)) { - expr = Var->getInit(); - } else if (auto *Field = dyn_cast<FieldDecl>(D)) { - expr = Field->getInClassInitializer(); + if (clang_isDeclaration(C.kind)) { + const Decl *D = getCursorDecl(C); + if (D) { + const Expr *expr = nullptr; + if (auto *Var = dyn_cast<VarDecl>(D)) { + expr = Var->getInit(); + } else if (auto *Field = dyn_cast<FieldDecl>(D)) { + expr = Field->getInClassInitializer(); + } + if (expr) + return const_cast<CXEvalResult>(reinterpret_cast<const void *>( + evaluateExpr(const_cast<Expr *>(expr), C))); + return nullptr; } - if (expr) - return const_cast<CXEvalResult>(reinterpret_cast<const void *>( - evaluateExpr(const_cast<Expr *>(expr), C))); - return nullptr; } const CompoundStmt *compoundStmt = dyn_cast_or_null<CompoundStmt>(getCursorStmt(C));
Index: unittests/libclang/LibclangTest.cpp =================================================================== --- unittests/libclang/LibclangTest.cpp +++ unittests/libclang/LibclangTest.cpp @@ -461,6 +461,47 @@ clang_disposeSourceRangeList(Ranges); } +TEST_F(LibclangParseTest, EvaluateChildExpression) { + std::string Main = "main.m"; + WriteFile(Main, "#define kFOO @\"foo\"\n" + "void foobar(void) {\n" + " {kFOO;}\n" + "}\n"); + 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_FunctionDecl) { + int numberedStmt = 0; + clang_visitChildren( + cursor, + [](CXCursor cursor, CXCursor parent, + CXClientData client_data) -> CXChildVisitResult { + int &numberedStmt = *((int *)client_data); + if (clang_getCursorKind(cursor) == CXCursor_CompoundStmt) { + if (numberedStmt) { + CXEvalResult RE = clang_Cursor_Evaluate(cursor); + EXPECT_NE(RE, nullptr); + EXPECT_EQ(clang_EvalResult_getKind(RE), + CXEval_ObjCStrLiteral); + return CXChildVisit_Break; + } + numberedStmt++; + } + return CXChildVisit_Recurse; + }, + &numberedStmt); + EXPECT_EQ(numberedStmt, 1); + } + return CXChildVisit_Continue; + }, + nullptr); +} + class LibclangReparseTest : public LibclangParseTest { public: void DisplayDiagnostics() { Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -3890,18 +3890,20 @@ } CXEvalResult clang_Cursor_Evaluate(CXCursor C) { - const Decl *D = getCursorDecl(C); - if (D) { - const Expr *expr = nullptr; - if (auto *Var = dyn_cast<VarDecl>(D)) { - expr = Var->getInit(); - } else if (auto *Field = dyn_cast<FieldDecl>(D)) { - expr = Field->getInClassInitializer(); + if (clang_isDeclaration(C.kind)) { + const Decl *D = getCursorDecl(C); + if (D) { + const Expr *expr = nullptr; + if (auto *Var = dyn_cast<VarDecl>(D)) { + expr = Var->getInit(); + } else if (auto *Field = dyn_cast<FieldDecl>(D)) { + expr = Field->getInClassInitializer(); + } + if (expr) + return const_cast<CXEvalResult>(reinterpret_cast<const void *>( + evaluateExpr(const_cast<Expr *>(expr), C))); + return nullptr; } - if (expr) - return const_cast<CXEvalResult>(reinterpret_cast<const void *>( - evaluateExpr(const_cast<Expr *>(expr), C))); - return nullptr; } const CompoundStmt *compoundStmt = dyn_cast_or_null<CompoundStmt>(getCursorStmt(C));
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits