[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.

llvm-svn: 153560
This commit is contained in:
Argyrios Kyrtzidis 2012-03-28 02:17:59 +00:00
parent f981060503
commit 9d3ffffec0
1 changed files with 52 additions and 5 deletions

View File

@ -2648,15 +2648,62 @@ unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {
return CXSaveTranslationUnit_None; 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, int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
unsigned options) { unsigned options) {
if (!TU) if (!TU)
return CXSaveError_InvalidTU; return CXSaveError_InvalidTU;
CXSaveError result = static_cast<ASTUnit *>(TU->TUData)->Save(FileName); ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
if (getenv("LIBCLANG_RESOURCE_USAGE")) 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); PrintLibclangResourceUsage(TU);
return result; }
return STUI.result;
} }
void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) { void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {