arphaman created this revision.
arphaman added a reviewer: benlangmuir.
Herald added a subscriber: JDevlieghere.
This patch allows libclang to report a parser crash that's caused by `#pragma
clang __debug parser_crash` without using the `LLVM_BUILTIN_TRAP`. Instead a
new flag in PPOpts is used to let libclang know that a simulated crash has
occurred. This flag allows clients to test that libclang can report a parser
crash (CXError_Crash) when libclang is ran under a debugger that breaks on
`LLVM_BUILTIN_TRAP`.
Repository:
rC Clang
https://reviews.llvm.org/D41526
Files:
include/clang/Frontend/ASTUnit.h
include/clang/Lex/PreprocessorOptions.h
lib/Frontend/ASTUnit.cpp
lib/Parse/ParseDecl.cpp
tools/libclang/CIndex.cpp
unittests/libclang/LibclangTest.cpp
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));
+}
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: 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: 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<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ bool AvoidTrapOnBuiltinDebugCrash) {
assert(Diags.get() && "no DiagnosticsEngine was provided");
SmallVector<StoredDiagnostic, 4> 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: 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<FailedModulesSet> 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: 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<StringRef> ModuleFormat = llvm::None,
std::unique_ptr<ASTUnit> *ErrAST = nullptr,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
+ IntrusiveRefCntPtr<vfs::FileSystem> 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.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits