Index: include/clang/Frontend/ASTUnit.h =================================================================== --- include/clang/Frontend/ASTUnit.h +++ include/clang/Frontend/ASTUnit.h @@ -787,7 +787,8 @@ bool UserFilesAreVolatile = false, bool ForSerialization = false, llvm::Optional ModuleFormat = llvm::None, std::unique_ptr *ErrAST = nullptr, - IntrusiveRefCntPtr VFS = nullptr); + IntrusiveRefCntPtr VFS = nullptr, + bool AvoidTrapOnBuiltinDebugCrash = false); /// \brief Reparse the source files using the same command-line options that /// were originally used to produce this translation unit. Index: include/clang/Lex/PreprocessorOptions.h =================================================================== --- include/clang/Lex/PreprocessorOptions.h +++ include/clang/Lex/PreprocessorOptions.h @@ -155,6 +155,13 @@ /// build it again. std::shared_ptr FailedModules; + /// Whether the compiler should avoid trapping when it encounters a + /// __debug parser_crash pragma. + bool AvoidTrapOnParserCrashPragma = false; + + /// True if the compiler has seen the __debug parser_crash pragma. + bool SeenParserCrashPragma = false; + public: PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} Index: lib/Frontend/ASTUnit.cpp =================================================================== --- lib/Frontend/ASTUnit.cpp +++ lib/Frontend/ASTUnit.cpp @@ -1649,7 +1649,8 @@ bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies, bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization, llvm::Optional ModuleFormat, std::unique_ptr *ErrAST, - IntrusiveRefCntPtr VFS) { + IntrusiveRefCntPtr VFS, + bool AvoidTrapOnBuiltinDebugCrash) { assert(Diags.get() && "no DiagnosticsEngine was provided"); SmallVector StoredDiagnostics; @@ -1676,6 +1677,7 @@ PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; PPOpts.SingleFileParseMode = SingleFileParse; + PPOpts.AvoidTrapOnParserCrashPragma = AvoidTrapOnBuiltinDebugCrash; // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -19,6 +19,7 @@ #include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" @@ -5649,8 +5650,12 @@ Diag(PP.getLocForEndOfToken(D.getEllipsisLoc()), diag::ext_abstract_pack_declarator_parens); } else { - if (Tok.getKind() == tok::annot_pragma_parser_crash) - LLVM_BUILTIN_TRAP; + if (Tok.getKind() == tok::annot_pragma_parser_crash) { + if (!PP.getPreprocessorOpts().AvoidTrapOnParserCrashPragma) + LLVM_BUILTIN_TRAP; + else + PP.getPreprocessorOpts().SeenParserCrashPragma = true; + } if (Tok.is(tok::l_square)) return ParseMisplacedBracketDeclarator(D); if (D.getContext() == Declarator::MemberContext) { Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -37,6 +37,7 @@ #include "clang/Lex/Lexer.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Serialization/SerializationDiagnostic.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" @@ -3453,8 +3454,8 @@ TUKind, CacheCodeCompletionResults, IncludeBriefCommentsInCodeCompletion, /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, SingleFileParse, /*UserFilesAreVolatile=*/true, ForSerialization, - CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(), - &ErrUnit)); + CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(), &ErrUnit, + /*VFS=*/nullptr, /*AvoidTrapOnBuiltinDebugCrash=*/true)); // Early failures in LoadFromCommandLine may return with ErrUnit unset. if (!Unit && !ErrUnit) @@ -3469,15 +3470,17 @@ if (isASTReadError(Unit ? Unit.get() : ErrUnit.get())) return CXError_ASTReadError; + bool Crash = + Unit->getPreprocessor().getPreprocessorOpts().SeenParserCrashPragma; *out_TU = MakeCXTranslationUnit(CXXIdx, std::move(Unit)); if (CXTranslationUnitImpl *TU = *out_TU) { TU->ParsingOptions = options; TU->Arguments.reserve(Args->size()); for (const char *Arg : *Args) TU->Arguments.push_back(Arg); - return CXError_Success; + return Crash ? CXError_Crashed : CXError_Success; } - return CXError_Failure; + return Crash ? CXError_Crashed : CXError_Failure; } CXTranslationUnit Index: unittests/libclang/LibclangTest.cpp =================================================================== --- unittests/libclang/LibclangTest.cpp +++ unittests/libclang/LibclangTest.cpp @@ -572,3 +572,15 @@ EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU)); DisplayDiagnostics(); } + +TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv_Crash) { + std::string Filename = "test.cc"; + WriteFile(Filename, "# pragma clang __debug parser_crash\n"); + + const char *Argv[] = {"clang"}; + + EXPECT_EQ(CXError_Crashed, + clang_parseTranslationUnit2FullArgv(Index, Filename.c_str(), Argv, + sizeof(Argv) / sizeof(Argv[0]), + nullptr, 0, TUFlags, &ClangTU)); +}