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
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to