Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit f9c61eb

Browse files
committed
[libclang] evalute compound statement cursors before trying to evaluate
the cursor like a declaration This change fixes 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. rdar://38888477 Differential Revision: https://reviews.llvm.org/D49051 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336590 91177308-0d34-0410-b5e6-96231b3b80d8 (cherry picked from commit 0b6fe14)
1 parent 7728262 commit f9c61eb

File tree

2 files changed

+54
-13
lines changed

2 files changed

+54
-13
lines changed

tools/libclang/CIndex.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3879,6 +3879,19 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) {
38793879
}
38803880

38813881
CXEvalResult clang_Cursor_Evaluate(CXCursor C) {
3882+
if (clang_getCursorKind(C) == CXCursor_CompoundStmt) {
3883+
const CompoundStmt *compoundStmt = cast<CompoundStmt>(getCursorStmt(C));
3884+
Expr *expr = nullptr;
3885+
for (auto *bodyIterator : compoundStmt->body()) {
3886+
if ((expr = dyn_cast<Expr>(bodyIterator))) {
3887+
break;
3888+
}
3889+
}
3890+
if (expr)
3891+
return const_cast<CXEvalResult>(
3892+
reinterpret_cast<const void *>(evaluateExpr(expr, C)));
3893+
}
3894+
38823895
const Decl *D = getCursorDecl(C);
38833896
if (D) {
38843897
const Expr *expr = nullptr;
@@ -3892,19 +3905,6 @@ CXEvalResult clang_Cursor_Evaluate(CXCursor C) {
38923905
evaluateExpr(const_cast<Expr *>(expr), C)));
38933906
return nullptr;
38943907
}
3895-
3896-
const CompoundStmt *compoundStmt = dyn_cast_or_null<CompoundStmt>(getCursorStmt(C));
3897-
if (compoundStmt) {
3898-
Expr *expr = nullptr;
3899-
for (auto *bodyIterator : compoundStmt->body()) {
3900-
if ((expr = dyn_cast<Expr>(bodyIterator))) {
3901-
break;
3902-
}
3903-
}
3904-
if (expr)
3905-
return const_cast<CXEvalResult>(
3906-
reinterpret_cast<const void *>(evaluateExpr(expr, C)));
3907-
}
39083908
return nullptr;
39093909
}
39103910

unittests/libclang/LibclangTest.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,47 @@ TEST_F(LibclangParseTest, AllSkippedRanges) {
461461
clang_disposeSourceRangeList(Ranges);
462462
}
463463

464+
TEST_F(LibclangParseTest, EvaluateChildExpression) {
465+
std::string Main = "main.m";
466+
WriteFile(Main, "#define kFOO @\"foo\"\n"
467+
"void foobar(void) {\n"
468+
" {kFOO;}\n"
469+
"}\n");
470+
ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr,
471+
0, TUFlags);
472+
473+
CXCursor C = clang_getTranslationUnitCursor(ClangTU);
474+
clang_visitChildren(
475+
C,
476+
[](CXCursor cursor, CXCursor parent,
477+
CXClientData client_data) -> CXChildVisitResult {
478+
if (clang_getCursorKind(cursor) == CXCursor_FunctionDecl) {
479+
int numberedStmt = 0;
480+
clang_visitChildren(
481+
cursor,
482+
[](CXCursor cursor, CXCursor parent,
483+
CXClientData client_data) -> CXChildVisitResult {
484+
int &numberedStmt = *((int *)client_data);
485+
if (clang_getCursorKind(cursor) == CXCursor_CompoundStmt) {
486+
if (numberedStmt) {
487+
CXEvalResult RE = clang_Cursor_Evaluate(cursor);
488+
EXPECT_NE(RE, nullptr);
489+
EXPECT_EQ(clang_EvalResult_getKind(RE),
490+
CXEval_ObjCStrLiteral);
491+
return CXChildVisit_Break;
492+
}
493+
numberedStmt++;
494+
}
495+
return CXChildVisit_Recurse;
496+
},
497+
&numberedStmt);
498+
EXPECT_EQ(numberedStmt, 1);
499+
}
500+
return CXChildVisit_Continue;
501+
},
502+
nullptr);
503+
}
504+
464505
class LibclangReparseTest : public LibclangParseTest {
465506
public:
466507
void DisplayDiagnostics() {

0 commit comments

Comments
 (0)