Run all functional logic of clang_annotateTokens() within a CrashRecoveryContext. Fixes <rdar://problem/9121698>.

llvm-svn: 127919
This commit is contained in:
Ted Kremenek 2011-03-18 22:51:30 +00:00
parent 54140eb568
commit 21c7e6e298
1 changed files with 189 additions and 172 deletions

View File

@ -4566,38 +4566,31 @@ static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
return static_cast<AnnotateTokensWorker*>(client_data)->Visit(cursor, parent);
}
// This gets run a separate thread to avoid stack blowout.
static void runAnnotateTokensWorker(void *UserData) {
((AnnotateTokensWorker*)UserData)->AnnotateTokens();
namespace {
struct clang_annotateTokens_Data {
CXTranslationUnit TU;
ASTUnit *CXXUnit;
CXToken *Tokens;
unsigned NumTokens;
CXCursor *Cursors;
};
}
extern "C" {
void clang_annotateTokens(CXTranslationUnit TU,
CXToken *Tokens, unsigned NumTokens,
CXCursor *Cursors) {
if (NumTokens == 0 || !Tokens || !Cursors)
return;
// Any token we don't specifically annotate will have a NULL cursor.
CXCursor C = clang_getNullCursor();
for (unsigned I = 0; I != NumTokens; ++I)
Cursors[I] = C;
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
if (!CXXUnit)
return;
ASTUnit::ConcurrencyCheck Check(*CXXUnit);
// This gets run a separate thread to avoid stack blowout.
static void clang_annotateTokensImpl(void *UserData) {
CXTranslationUnit TU = ((clang_annotateTokens_Data*)UserData)->TU;
ASTUnit *CXXUnit = ((clang_annotateTokens_Data*)UserData)->CXXUnit;
CXToken *Tokens = ((clang_annotateTokens_Data*)UserData)->Tokens;
const unsigned NumTokens = ((clang_annotateTokens_Data*)UserData)->NumTokens;
CXCursor *Cursors = ((clang_annotateTokens_Data*)UserData)->Cursors;
// Determine the region of interest, which contains all of the tokens.
SourceRange RegionOfInterest;
RegionOfInterest.setBegin(cxloc::translateSourceLocation(
clang_getTokenLocation(TU, Tokens[0])));
RegionOfInterest.setEnd(cxloc::translateSourceLocation(
clang_getTokenLocation(TU,
Tokens[NumTokens - 1])));
RegionOfInterest.setBegin(
cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
RegionOfInterest.setEnd(
cxloc::translateSourceLocation(clang_getTokenLocation(TU,
Tokens[NumTokens-1])));
// A mapping from the source locations found when re-lexing or traversing the
// region of interest to the corresponding cursors.
@ -4637,7 +4630,7 @@ void clang_annotateTokens(CXTranslationUnit TU,
//
// FIXME: Some simple tests here could identify macro definitions and
// #undefs, to provide specific cursor kinds for those.
std::vector<SourceLocation> Locations;
llvm::SmallVector<SourceLocation, 32> Locations;
do {
Locations.push_back(Tok.getLocation());
Lex.LexFromRawLexer(Tok);
@ -4645,8 +4638,8 @@ void clang_annotateTokens(CXTranslationUnit TU,
using namespace cxcursor;
CXCursor Cursor
= MakePreprocessingDirectiveCursor(SourceRange(Locations.front(),
Locations.back()),
= MakePreprocessingDirectiveCursor(SourceRange(Locations.front(),
Locations.back()),
TU);
for (unsigned I = 0, N = Locations.size(); I != N; ++I) {
Annotated[Locations[I].getRawEncoding()] = Cursor;
@ -4668,17 +4661,12 @@ void clang_annotateTokens(CXTranslationUnit TU,
AnnotateTokensWorker W(Annotated, Tokens, Cursors, NumTokens,
TU, RegionOfInterest);
// Run the worker within a CrashRecoveryContext.
// FIXME: We use a ridiculous stack size here because the data-recursion
// algorithm uses a large stack frame than the non-data recursive version,
// and AnnotationTokensWorker currently transforms the data-recursion
// algorithm back into a traditional recursion by explicitly calling
// VisitChildren(). We will need to remove this explicit recursive call.
llvm::CrashRecoveryContext CRC;
if (!RunSafely(CRC, runAnnotateTokensWorker, &W,
GetSafetyThreadStackSize() * 2)) {
fprintf(stderr, "libclang: crash detected while annotating tokens\n");
}
W.AnnotateTokens();
// If we ran into any entities that involve context-sensitive keywords,
// take another pass through the tokens to mark them as such.
@ -4690,19 +4678,19 @@ void clang_annotateTokens(CXTranslationUnit TU,
if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) {
IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
if (ObjCPropertyDecl *Property
= dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {
= dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {
if (Property->getPropertyAttributesAsWritten() != 0 &&
llvm::StringSwitch<bool>(II->getName())
.Case("readonly", true)
.Case("assign", true)
.Case("readwrite", true)
.Case("retain", true)
.Case("copy", true)
.Case("nonatomic", true)
.Case("atomic", true)
.Case("getter", true)
.Case("setter", true)
.Default(false))
.Case("readonly", true)
.Case("assign", true)
.Case("readwrite", true)
.Case("retain", true)
.Case("copy", true)
.Case("nonatomic", true)
.Case("atomic", true)
.Case("getter", true)
.Case("setter", true)
.Default(false))
Tokens[I].int_data[0] = CXToken_Keyword;
}
continue;
@ -4712,13 +4700,13 @@ void clang_annotateTokens(CXTranslationUnit TU,
Cursors[I].kind == CXCursor_ObjCClassMethodDecl) {
IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
if (llvm::StringSwitch<bool>(II->getName())
.Case("in", true)
.Case("out", true)
.Case("inout", true)
.Case("oneway", true)
.Case("bycopy", true)
.Case("byref", true)
.Default(false))
.Case("in", true)
.Case("out", true)
.Case("inout", true)
.Case("oneway", true)
.Case("bycopy", true)
.Case("byref", true)
.Default(false))
Tokens[I].int_data[0] = CXToken_Keyword;
continue;
}
@ -4726,14 +4714,14 @@ void clang_annotateTokens(CXTranslationUnit TU,
if (Cursors[I].kind == CXCursor_CXXMethod) {
IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
if (CXXMethodDecl *Method
= dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(Cursors[I]))) {
= dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(Cursors[I]))) {
if ((Method->hasAttr<FinalAttr>() ||
Method->hasAttr<OverrideAttr>()) &&
Method->getLocation().getRawEncoding() != Tokens[I].int_data[1] &&
llvm::StringSwitch<bool>(II->getName())
.Case("final", true)
.Case("override", true)
.Default(false))
.Case("final", true)
.Case("override", true)
.Default(false))
Tokens[I].int_data[0] = CXToken_Keyword;
}
continue;
@ -4753,7 +4741,7 @@ void clang_annotateTokens(CXTranslationUnit TU,
Record->getIdentifier() != II)
Tokens[I].int_data[0] = CXToken_Keyword;
} else if (ClassTemplateDecl *ClassTemplate
= dyn_cast_or_null<ClassTemplateDecl>(D)) {
= dyn_cast_or_null<ClassTemplateDecl>(D)) {
CXXRecordDecl *Record = ClassTemplate->getTemplatedDecl();
if ((Record->hasAttr<FinalAttr>()) &&
Record->getIdentifier() != II)
@ -4765,6 +4753,35 @@ void clang_annotateTokens(CXTranslationUnit TU,
}
}
}
extern "C" {
void clang_annotateTokens(CXTranslationUnit TU,
CXToken *Tokens, unsigned NumTokens,
CXCursor *Cursors) {
if (NumTokens == 0 || !Tokens || !Cursors)
return;
// Any token we don't specifically annotate will have a NULL cursor.
CXCursor C = clang_getNullCursor();
for (unsigned I = 0; I != NumTokens; ++I)
Cursors[I] = C;
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
if (!CXXUnit)
return;
ASTUnit::ConcurrencyCheck Check(*CXXUnit);
clang_annotateTokens_Data data = { TU, CXXUnit, Tokens, NumTokens, Cursors };
llvm::CrashRecoveryContext CRC;
if (!RunSafely(CRC, clang_annotateTokensImpl, &data,
GetSafetyThreadStackSize() * 2)) {
fprintf(stderr, "libclang: crash detected while annotating tokens\n");
}
}
} // end: extern "C"
//===----------------------------------------------------------------------===//