]> granicus.if.org Git - clang/commitdiff
[libclang] Recommit r336590 with a fix for the memory leak in the test
authorAlex Lorenz <arphaman@gmail.com>
Tue, 8 Jan 2019 22:32:51 +0000 (22:32 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Tue, 8 Jan 2019 22:32:51 +0000 (22:32 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@350666 91177308-0d34-0410-b5e6-96231b3b80d8

tools/libclang/CIndex.cpp
unittests/libclang/LibclangTest.cpp

index bc791954fc718d58e8c32780d86ed2b42251cc29..15b2df84935e4052e7aa4d39f3e9064246efcc46 100644 (file)
@@ -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) {
index 6fddcb2cbf260150aee407db1f5e905f11d9c394..b88b88dac338d564d64774bea5309e6b4cf279b5 100644 (file)
@@ -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() {