From: Ted Kremenek Date: Fri, 18 Mar 2011 22:51:30 +0000 (+0000) Subject: Run all functional logic of clang_annotateTokens() within a CrashRecoveryContext... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6628a614c504263ae539462f049d523dd07ac1ba;p=clang Run all functional logic of clang_annotateTokens() within a CrashRecoveryContext. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127919 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 8d5c701d47..88b3d76e91 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -4566,43 +4566,36 @@ static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor, return static_cast(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(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. AnnotateTokensData Annotated; - + // Relex the tokens within the source range to look for preprocessing // directives. SourceManager &SourceMgr = CXXUnit->getSourceManager(); @@ -4610,7 +4603,7 @@ void clang_annotateTokens(CXTranslationUnit TU, = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin()); std::pair EndLocInfo = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd()); - + llvm::StringRef Buffer; bool Invalid = false; if (BeginLocInfo.first == EndLocInfo.first && @@ -4621,13 +4614,13 @@ void clang_annotateTokens(CXTranslationUnit TU, Buffer.begin(), Buffer.data() + BeginLocInfo.second, Buffer.end()); Lex.SetCommentRetentionState(true); - + // Lex tokens in raw mode until we hit the end of the range, to avoid // entering #includes or expanding macros. while (true) { Token Tok; Lex.LexFromRawLexer(Tok); - + reprocess: if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) { // We have found a preprocessing directive. Gobble it up so that we @@ -4637,49 +4630,44 @@ 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 Locations; + llvm::SmallVector Locations; do { Locations.push_back(Tok.getLocation()); Lex.LexFromRawLexer(Tok); } while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof)); - + 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; } - + if (Tok.isAtStartOfLine()) goto reprocess; - + continue; } - + if (Tok.is(tok::eof)) break; } } - + // Annotate all of the source locations in the region of interest that map to // a specific cursor. 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. if (W.hasContextSensitiveKeywords()) { @@ -4690,19 +4678,19 @@ void clang_annotateTokens(CXTranslationUnit TU, if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) { IdentifierInfo *II = static_cast(Tokens[I].ptr_data); if (ObjCPropertyDecl *Property - = dyn_cast_or_null(getCursorDecl(Cursors[I]))) { + = dyn_cast_or_null(getCursorDecl(Cursors[I]))) { if (Property->getPropertyAttributesAsWritten() != 0 && llvm::StringSwitch(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(Tokens[I].ptr_data); if (llvm::StringSwitch(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(Tokens[I].ptr_data); if (CXXMethodDecl *Method - = dyn_cast_or_null(getCursorDecl(Cursors[I]))) { + = dyn_cast_or_null(getCursorDecl(Cursors[I]))) { if ((Method->hasAttr() || Method->hasAttr()) && Method->getLocation().getRawEncoding() != Tokens[I].int_data[1] && llvm::StringSwitch(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,18 +4741,47 @@ void clang_annotateTokens(CXTranslationUnit TU, Record->getIdentifier() != II) Tokens[I].int_data[0] = CXToken_Keyword; } else if (ClassTemplateDecl *ClassTemplate - = dyn_cast_or_null(D)) { + = dyn_cast_or_null(D)) { CXXRecordDecl *Record = ClassTemplate->getTemplatedDecl(); if ((Record->hasAttr()) && Record->getIdentifier() != II) - Tokens[I].int_data[0] = CXToken_Keyword; + Tokens[I].int_data[0] = CXToken_Keyword; } } - continue; + continue; } } } } + +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(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" //===----------------------------------------------------------------------===//