]> granicus.if.org Git - clang/commitdiff
Implement -fno-validate-pch at the -cc1 level, which suppresses most
authorDouglas Gregor <dgregor@apple.com>
Tue, 27 Jul 2010 00:27:13 +0000 (00:27 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 27 Jul 2010 00:27:13 +0000 (00:27 +0000)
of the usual consistency checks used to determine when a precompiled
header is incompatible with the translation unit it's being loaded
into.

Enable this option when loading a precompiled preamble, because the
preamble loader will be performing all of this checking itself. Enable
the preamble-based test now that it's working.

This option is also useful for debugging Clang's PCH
(<rdar://problem/7532213>).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109475 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Driver/CC1Options.td
include/clang/Frontend/CompilerInstance.h
include/clang/Frontend/PCHReader.h
include/clang/Frontend/PreprocessorOptions.h
lib/Frontend/ASTUnit.cpp
lib/Frontend/CompilerInstance.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/FrontendAction.cpp
lib/Frontend/PCHReader.cpp
test/Index/preamble.c

index b813fea75c6a80cf6a611eb56a67c7a0e7d4bf4e..cd4b9f75b0bf2a39c08a0c3b140bc1af98962460 100644 (file)
@@ -441,6 +441,8 @@ def fpascal_strings : Flag<"-fpascal-strings">,
   HelpText<"Recognize and construct Pascal-style string literals">;
 def fno_rtti : Flag<"-fno-rtti">,
   HelpText<"Disable generation of rtti information">;
+def fno_validate_pch : Flag<"-fno-validate-pch">,
+  HelpText<"Disable validation of precompiled headers">;
 def fshort_wchar : Flag<"-fshort-wchar">,
   HelpText<"Force wchar_t to be a short unsigned int">;
 def static_define : Flag<"-static-define">,
index 54ce8bfe3ba0c572a0c5df39dd974958030c88fd..89df8f584bf229d0271eab2c04587876c42e4c09 100644 (file)
@@ -502,13 +502,15 @@ public:
 
   /// Create an external AST source to read a PCH file and attach it to the AST
   /// context.
-  void createPCHExternalASTSource(llvm::StringRef Path);
+  void createPCHExternalASTSource(llvm::StringRef Path,
+                                  bool DisablePCHValidation);
 
   /// Create an external AST source to read a PCH file.
   ///
   /// \return - The new object on success, or null on failure.
   static ExternalASTSource *
   createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot,
+                             bool DisablePCHValidation,
                              Preprocessor &PP, ASTContext &Context);
 
   /// Get the PCH reader, if any.
index 17a0cd076f68721a1a14ee003af742deb17c2ed3..49579dc1b17e9c7e4473921e34c4283db63412af 100644 (file)
@@ -409,6 +409,10 @@ private:
   /// precompiled header.
   const char *isysroot;
 
+  /// \brief Whether to disable the normal validation performed on precompiled
+  /// headers when they are loaded.
+  bool DisableValidation;
+      
   /// \brief Mapping from switch-case IDs in the PCH file to
   /// switch-case statements.
   std::map<unsigned, SwitchCase *> SwitchCaseStmts;
@@ -599,7 +603,12 @@ public:
   /// \param isysroot If non-NULL, the system include path specified by the
   /// user. This is only used with relocatable PCH files. If non-NULL,
   /// a relocatable PCH file will use the default path "/".
-  PCHReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0);
+  ///
+  /// \param DisableValidation If true, the PCH reader will suppress most
+  /// of its regular consistency checking, allowing the use of precompiled
+  /// headers that cannot be determined to be compatible.
+  PCHReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0,
+            bool DisableValidation = false);
 
   /// \brief Load the PCH file without using any pre-initialized Preprocessor.
   ///
@@ -618,8 +627,13 @@ public:
   /// \param isysroot If non-NULL, the system include path specified by the
   /// user. This is only used with relocatable PCH files. If non-NULL,
   /// a relocatable PCH file will use the default path "/".
-  PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
-            Diagnostic &Diags, const char *isysroot = 0);
+  ///
+  /// \param DisableValidation If true, the PCH reader will suppress most
+  /// of its regular consistency checking, allowing the use of precompiled
+  /// headers that cannot be determined to be compatible.
+      PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
+            Diagnostic &Diags, const char *isysroot = 0,
+            bool DisableValidation = false);
   ~PCHReader();
 
   /// \brief Load the precompiled header designated by the given file
index f2154955c2269dfb3bd2756397213c62671cccb6..851c1f0108affe3c04514160a3fe49a9caaa1cc9 100644 (file)
@@ -43,6 +43,10 @@ public:
   /// The implicit PCH included at the start of the translation unit, or empty.
   std::string ImplicitPCHInclude;
 
+  /// \brief When true, disables most of the normal validation performed on
+  /// precompiled headers.
+  bool DisablePCHValidation;
+  
   /// \brief If non-zero, the implicit PCH include is actually a precompiled
   /// preamble that covers this number of bytes in the main source file.
   ///
@@ -113,6 +117,7 @@ public:
   
 public:
   PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
+                          DisablePCHValidation(false),
                           PrecompiledPreambleBytes(0, true),
                           RetainRemappedFileBuffers(false) { }
 
index 7ff3cdc5b9a0600eefd3bf210fa48f180ba56cd0..0463db18dc069fea94554915d262cab198e87e26 100644 (file)
@@ -394,6 +394,7 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
     PreprocessorOpts.PrecompiledPreambleBytes.second
                                                     = PreambleEndsAtStartOfLine;
     PreprocessorOpts.ImplicitPCHInclude = PreambleFile.str();
+    PreprocessorOpts.DisablePCHValidation = true;
   }
   
   llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
@@ -415,9 +416,11 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
   Act->EndSourceFile();
 
   // Remove the overridden buffer we used for the preamble.
-  if (OverrideMainBuffer)
+  if (OverrideMainBuffer) {
     PreprocessorOpts.eraseRemappedFile(
                                PreprocessorOpts.remapped_file_buffer_end() - 1);
+    PreprocessorOpts.DisablePCHValidation = true;
+  }
   
   Clang.takeDiagnosticClient();
   
@@ -426,9 +429,11 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
   
 error:
   // Remove the overridden buffer we used for the preamble.
-  if (OverrideMainBuffer)
+  if (OverrideMainBuffer) {
     PreprocessorOpts.eraseRemappedFile(
                                PreprocessorOpts.remapped_file_buffer_end() - 1);
+    PreprocessorOpts.DisablePCHValidation = true;
+  }
   
   Clang.takeSourceManager();
   Clang.takeFileManager();
index 0b1041f84124be90ef9e06bb51afbefc0398b35b..ea295687aa08fc849fa0a8d344dea13857e30107 100644 (file)
@@ -250,9 +250,11 @@ void CompilerInstance::createASTContext() {
 
 // ExternalASTSource
 
-void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
+void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
+                                                  bool DisablePCHValidation) {
   llvm::OwningPtr<ExternalASTSource> Source;
   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
+                                          DisablePCHValidation,
                                           getPreprocessor(), getASTContext()));
   // Remember the PCHReader, but in a non-owning way.
   Reader = static_cast<PCHReader*>(Source.get());
@@ -262,11 +264,13 @@ void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
 ExternalASTSource *
 CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
                                              const std::string &Sysroot,
+                                             bool DisablePCHValidation,
                                              Preprocessor &PP,
                                              ASTContext &Context) {
   llvm::OwningPtr<PCHReader> Reader;
   Reader.reset(new PCHReader(PP, &Context,
-                             Sysroot.empty() ? 0 : Sysroot.c_str()));
+                             Sysroot.empty() ? 0 : Sysroot.c_str(),
+                             DisablePCHValidation));
 
   switch (Reader->ReadPCH(Path)) {
   case PCHReader::Success:
index 68703c22fb4f97a5488e98a761ee55825ff713ef..0ae4739b410cefe559351b01d2e7345e1af6328a 100644 (file)
@@ -1353,7 +1353,8 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
     Opts.TokenCache = Opts.ImplicitPTHInclude;
   Opts.UsePredefines = !Args.hasArg(OPT_undef);
   Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
-  
+  Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
+
   if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
     llvm::StringRef Value(A->getValue(Args));
     size_t Comma = Value.find(',');
index dbbf69c8b12c4cba5afd29aa553cce6e5c3d5ede..9efa8c61db8596a989e46233acd9fae5973c65b9 100644 (file)
@@ -118,7 +118,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
     if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
       assert(hasPCHSupport() && "This action does not have PCH support!");
       CI.createPCHExternalASTSource(
-        CI.getPreprocessorOpts().ImplicitPCHInclude);
+                                CI.getPreprocessorOpts().ImplicitPCHInclude,
+                                CI.getPreprocessorOpts().DisablePCHValidation);
       if (!CI.getASTContext().getExternalSource())
         goto failure;
     }
index f454477c50aba9ad172dfa364a4b28f586d7088d..37e11249f88e9cc87a572f406883bb9a489b3003 100644 (file)
@@ -414,13 +414,14 @@ void PCHValidator::ReadCounter(unsigned Value) {
 //===----------------------------------------------------------------------===//
 
 PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
-                     const char *isysroot)
+                     const char *isysroot, bool DisableValidation)
   : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
     SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
     Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context),
     Consumer(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
     TotalSelectorsInMethodPool(0), SelectorOffsets(0),
-    TotalNumSelectors(0),  isysroot(isysroot), NumStatHits(0), NumStatMisses(0),
+    TotalNumSelectors(0),  isysroot(isysroot), 
+    DisableValidation(DisableValidation), NumStatHits(0), NumStatMisses(0),
     NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0),
     TotalNumStatements(0), NumMacrosRead(0), NumMethodPoolSelectorsRead(0),
     NumMethodPoolMisses(0), TotalNumMacros(0), NumLexicalDeclContextsRead(0),
@@ -430,12 +431,14 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
 }
 
 PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
-                     Diagnostic &Diags, const char *isysroot)
+                     Diagnostic &Diags, const char *isysroot,
+                     bool DisableValidation)
   : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr),
     Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0),
     MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
     TotalSelectorsInMethodPool(0), SelectorOffsets(0),
-    TotalNumSelectors(0), isysroot(isysroot), NumStatHits(0), NumStatMisses(0),
+    TotalNumSelectors(0), isysroot(isysroot), 
+    DisableValidation(DisableValidation), NumStatHits(0), NumStatMisses(0),
     NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0),
     TotalNumStatements(0), NumMacrosRead(0), NumMethodPoolSelectorsRead(0),
     NumMethodPoolMisses(0), TotalNumMacros(0), NumLexicalDeclContextsRead(0),
@@ -1019,14 +1022,15 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
       return Failure;
     }
 
-    if ((off_t)Record[4] != File->getSize()
+    if (!DisableValidation &&
+        ((off_t)Record[4] != File->getSize()
 #if !defined(LLVM_ON_WIN32)
         // In our regression testing, the Windows file system seems to
         // have inconsistent modification times that sometimes
         // erroneously trigger this error-handling path.
-        || (time_t)Record[5] != File->getModificationTime()
+         || (time_t)Record[5] != File->getModificationTime()
 #endif
-        ) {
+        )) {
       Diag(diag::err_fe_pch_file_modified)
         << Filename;
       return Failure;
@@ -1481,7 +1485,7 @@ PCHReader::ReadPCHBlock(PerFileData &F) {
       break;
 
     case pch::METADATA: {
-      if (Record[0] != pch::VERSION_MAJOR) {
+      if (Record[0] != pch::VERSION_MAJOR && !DisableValidation) {
         Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
                                            : diag::warn_pch_version_too_new);
         return IgnorePCH;
@@ -1501,7 +1505,7 @@ PCHReader::ReadPCHBlock(PerFileData &F) {
         Error("CHAINED_METADATA is not first record in block");
         return Failure;
       }
-      if (Record[0] != pch::VERSION_MAJOR) {
+      if (Record[0] != pch::VERSION_MAJOR && !DisableValidation) {
         Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
                                            : diag::warn_pch_version_too_new);
         return IgnorePCH;
@@ -1536,7 +1540,7 @@ PCHReader::ReadPCHBlock(PerFileData &F) {
       break;
 
     case pch::LANGUAGE_OPTIONS:
-      if (ParseLanguageOptions(Record))
+      if (ParseLanguageOptions(Record) && !DisableValidation)
         return IgnorePCH;
       break;
 
@@ -1704,7 +1708,7 @@ PCHReader::ReadPCHBlock(PerFileData &F) {
     case pch::VERSION_CONTROL_BRANCH_REVISION: {
       const std::string &CurBranch = getClangFullRepositoryVersion();
       llvm::StringRef PCHBranch(BlobStart, BlobLen);
-      if (llvm::StringRef(CurBranch) != PCHBranch) {
+      if (llvm::StringRef(CurBranch) != PCHBranch && !DisableValidation) {
         Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch;
         return IgnorePCH;
       }
@@ -1759,7 +1763,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
   }
 
   // Check the predefines buffers.
-  if (CheckPredefinesBuffers())
+  if (!DisableValidation && CheckPredefinesBuffers())
     return IgnorePCH;
 
   if (PP) {
index ad64a43554103c1a15ec97381f7234f944f8cba8..7ab1be5f73e065185906ac0154be9eb8f28cc3ab 100644 (file)
@@ -2,12 +2,7 @@
 #include "preamble.h"
 int wibble(int);
 
-// FIXME: Turn on use of preamble files
-
 // RUN: %clang -x c-header -o %t.pch %S/Inputs/prefix.h
-// RUN: c-index-test -test-load-source-reparse 5 local -I %S/Inputs -include %t %s | FileCheck %s
-
-// CHECK: preamble.h:1:5: FunctionDecl=bar:1:5 Extent=[1:5 - 1:13]
-// CHECK: preamble.h:1:12: ParmDecl=:1:12 (Definition) Extent=[1:9 - 1:13]
+// RUN: CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -I %S/Inputs -include %t %s | FileCheck %s
 // CHECK: preamble.c:3:5: FunctionDecl=wibble:3:5 Extent=[3:5 - 3:16]
 // CHECK: preamble.c:3:15: ParmDecl=:3:15 (Definition) Extent=[3:12 - 3:16]