From: Argyrios Kyrtzidis Date: Wed, 28 Mar 2012 02:17:59 +0000 (+0000) Subject: [libclang] For clang_saveTranslationUnit, if the AST to save has invalid nodes X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=142bcb59c012504360881e8f744d9d4a8d92c2ac;p=clang [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 --- 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(UserData); + + STUI->result = static_cast(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(TU->TUData)->Save(FileName); - if (getenv("LIBCLANG_RESOURCE_USAGE")) + + ASTUnit *CXXUnit = static_cast(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) {