Skip to content

Commit

Permalink
[libclang] Recommit r336590 with a fix for the memory leak in the test
Browse files Browse the repository at this point in the history
The original commit had a memory leak in the test has a leak as it doesn't
dispose of the evaluated cursor result.

This also contains the follow-up NFC refactoring commit r336591.

rdar://45893054

Original commit message:

[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

llvm-svn: 350666
  • Loading branch information
hyp committed Jan 8, 2019
1 parent b6d674f commit 65317e1
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 24 deletions.
47 changes: 23 additions & 24 deletions clang/tools/libclang/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3902,36 +3902,35 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) {
return nullptr;
}

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 (expr)
return const_cast<CXEvalResult>(reinterpret_cast<const void *>(
evaluateExpr(const_cast<Expr *>(expr), C)));
static const Expr *evaluateDeclExpr(const Decl *D) {
if (!D)
return nullptr;
}
if (auto *Var = dyn_cast<VarDecl>(D))
return Var->getInit();
else if (auto *Field = dyn_cast<FieldDecl>(D))
return Field->getInClassInitializer();
return nullptr;
}

const CompoundStmt *compoundStmt = dyn_cast_or_null<CompoundStmt>(getCursorStmt(C));
if (compoundStmt) {
Expr *expr = nullptr;
for (auto *bodyIterator : compoundStmt->body()) {
if ((expr = dyn_cast<Expr>(bodyIterator))) {
break;
}
}
if (expr)
return const_cast<CXEvalResult>(
reinterpret_cast<const void *>(evaluateExpr(expr, C)));
static const Expr *evaluateCompoundStmtExpr(const CompoundStmt *CS) {
assert(CS && "invalid compound statement");
for (auto *bodyIterator : CS->body()) {
if (const auto *E = dyn_cast<Expr>(bodyIterator))
return E;
}
return nullptr;
}

CXEvalResult clang_Cursor_Evaluate(CXCursor C) {
if (const Expr *E =
clang_getCursorKind(C) == CXCursor_CompoundStmt
? evaluateCompoundStmtExpr(cast<CompoundStmt>(getCursorStmt(C)))
: evaluateDeclExpr(getCursorDecl(C)))
return const_cast<CXEvalResult>(
reinterpret_cast<const void *>(evaluateExpr(const_cast<Expr *>(E), C)));
return nullptr;
}

unsigned clang_Cursor_hasAttrs(CXCursor C) {
const Decl *D = getCursorDecl(C);
if (!D) {
Expand Down
42 changes: 42 additions & 0 deletions clang/unittests/libclang/LibclangTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,48 @@ TEST_F(LibclangParseTest, AllSkippedRanges) {
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);
clang_EvalResult_dispose(RE);
return CXChildVisit_Break;
}
numberedStmt++;
}
return CXChildVisit_Recurse;
},
&numberedStmt);
EXPECT_EQ(numberedStmt, 1);
}
return CXChildVisit_Continue;
},
nullptr);
}

class LibclangReparseTest : public LibclangParseTest {
public:
void DisplayDiagnostics() {
Expand Down

0 comments on commit 65317e1

Please sign in to comment.