diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-03-28 02:17:59 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-03-28 02:17:59 +0000 |
commit | 142bcb59c012504360881e8f744d9d4a8d92c2ac (patch) | |
tree | cf5f055e7ef9283b4839432a74cb559e39299648 /tools | |
parent | 82fe6aea407a5a09a6131452ce622087ba83880d (diff) |
[libclang] For clang_saveTranslationUnit, if the AST to save has invalid nodes
due to compiler errors, use a crash recovery thread to do the AST writing for
protection.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153560 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r-- | tools/libclang/CIndex.cpp | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index f15de4b758..b3a29ef105 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -2647,16 +2647,63 @@ CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx, unsigned clang_defaultSaveOptions(CXTranslationUnit TU) { return CXSaveTranslationUnit_None; } - + +namespace { + +struct SaveTranslationUnitInfo { + CXTranslationUnit TU; + const char *FileName; + unsigned options; + CXSaveError result; +}; + +} + +static void clang_saveTranslationUnit_Impl(void *UserData) { + SaveTranslationUnitInfo *STUI = + static_cast<SaveTranslationUnitInfo*>(UserData); + + STUI->result = static_cast<ASTUnit *>(STUI->TU->TUData)->Save(STUI->FileName); +} + int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName, unsigned options) { if (!TU) return CXSaveError_InvalidTU; - - CXSaveError result = static_cast<ASTUnit *>(TU->TUData)->Save(FileName); - if (getenv("LIBCLANG_RESOURCE_USAGE")) + + ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); + ASTUnit::ConcurrencyCheck Check(*CXXUnit); + + SaveTranslationUnitInfo STUI = { TU, FileName, options, CXSaveError_None }; + + if (!CXXUnit->getDiagnostics().hasUnrecoverableErrorOccurred() || + getenv("LIBCLANG_NOTHREADS")) { + clang_saveTranslationUnit_Impl(&STUI); + + if (getenv("LIBCLANG_RESOURCE_USAGE")) + PrintLibclangResourceUsage(TU); + + return STUI.result; + } + + // We have an AST that has invalid nodes due to compiler errors. + // Use a crash recovery thread for protection. + + llvm::CrashRecoveryContext CRC; + + if (!RunSafely(CRC, clang_saveTranslationUnit_Impl, &STUI)) { + fprintf(stderr, "libclang: crash detected during AST saving: {\n"); + fprintf(stderr, " 'filename' : '%s'\n", FileName); + fprintf(stderr, " 'options' : %d,\n", options); + fprintf(stderr, "}\n"); + + return CXSaveError_Unknown; + + } else if (getenv("LIBCLANG_RESOURCE_USAGE")) { PrintLibclangResourceUsage(TU); - return result; + } + + return STUI.result; } void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) { |