diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-04-10 20:39:37 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-04-10 20:39:37 +0000 |
commit | 0a0428e96c6f1e8bef7a481a9eb69a6f6df38951 (patch) | |
tree | 1bc2ebbf5fdbdea6f8d302d8e6d5318def494ffd | |
parent | 6a1284ac1707273ff474bfc6968b72e847191ba6 (diff) |
Implement serialization/deserialization of LangOptions in the PCH
file. When de-serializing LangOptions, we check that the
currently-provided language options are consistent with the options
used to compile the PCH file. If they are not, we emit a diagnostic
and ignore the PCH file.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68820 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticFrontendKinds.td | 85 | ||||
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 14 | ||||
-rw-r--r-- | include/clang/Frontend/PCHReader.h | 14 | ||||
-rw-r--r-- | include/clang/Frontend/PCHWriter.h | 1 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 162 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 70 |
6 files changed, 316 insertions, 30 deletions
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index e4e12fd98e..47a873148d 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -22,4 +22,89 @@ def note_fixit_failed : Note< def note_fixit_unfixed_error : Note<"FIX-IT detected an error it cannot fix">; def warn_fixit_no_changes : Note< "FIX-IT detected errors it could not fix; no output will be generated">; + +// PCH reader +def note_ignoring_pch : Note< + "ignoring precompiled header '%0'">; +def warn_pch_c99 : Error< + "C99 support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; +def warn_pch_cplusplus : Error< + "C++ support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; +def warn_pch_cplusplus0x : Error< + "C++0x support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; +def warn_pch_objective_c : Error< + "Objective-C support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; +def warn_pch_objective_c2 : Error< + "Objective-C 2.0 support was %select{disabled|enabled}0 in PCH file but " + "is currently %select{disabled|enabled}1">; +def warn_pch_nonfragile_abi : Error< + "PCH file was compiled with the %select{32-bit|non-fragile}0 Objective-C " + "ABI but the %select{32-bit|non-fragile}1 Objective-C ABI is selected">; +def warn_pch_extensions : Warning< + "extensions were %select{enabled|disabled}0 in PCH file but are " + "currently %select{enabled|disabled}1">; +def warn_pch_gnu_extensions : Warning< + "GNU extensions were %select{disabled|enabled}0 in PCH file but are " + "currently %select{disabled|enabled}1">; +def warn_pch_microsoft_extensions : Warning< + "Microsoft extensions were %select{disabled|enabled}0 in PCH file but are " + "currently %select{disabled|enabled}1">; +def warn_pch_heinous_extensions : Warning< + "heinous extensions were %select{disabled|enabled}0 in PCH file but are " + "currently %select{disabled|enabled}1">; +def warn_pch_lax_vector_conversions : Warning< + "lax vector conversions were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; +def warn_pch_exceptions : Warning< + "exceptions were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; +def warn_pch_objc_runtime : Warning< + "PCH file was compiled with the %select{NeXT|GNU}0 runtime but the " + "%select{NeXT|GNU}1 runtime is selected">; +def warn_pch_freestanding : Warning< + "PCH file was compiled with a %select{hosted|freestanding}0 " + "implementation but a %select{hosted|freestanding}1 implementation " + "is selected">; +def warn_pch_builtins : Warning< + "PCH file was compiled with builtins %select{enabled|disabled}0 but " + "builtins are currently %select{enabled|disabled}1">; +def warn_pch_thread_safe_statics : Warning< + "PCH file was compiled %select{without|with}0 thread-safe statics but" + "thread-safe statics are currently %select{disabled|enabled}1">; +def warn_pch_blocks : Warning< + "blocks were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; +def warn_pch_math_errno : Warning< + "math functions %select{do not respect|respect}0 'errno' in PCH " + "file but they are currently set to %select{not respect|respect}1 " + "'errno'">; +def warn_pch_overflow_checking : Warning< + "signed integer overflow checking was %select{disabled|enabled}0 in PCH " + "file but is currently %select{disabled|enabled}1">; +def warn_pch_optimize : Warning< + "the macro '__OPTIMIZE__' was %select{not defined|defined}0 in " + "the PCH file but is currently %select{undefined|defined}1">; +def warn_pch_optimize_size : Warning< + "the macro '__OPTIMIZE_SIZE__' was %select{not defined|defined}0 in " + "the PCH file but is currently %select{undefined|defined}1">; +def warn_pch_static : Warning< + "the PCH file was compiled %select{dynamic|static}0 but the " + "current translation unit is being compiled as %select{dynamic|static}1">; +def warn_pch_pic_level : Warning< + "PCH file was compiled with PIC level %0, but the current translation " + "unit will be compiled with PIC level %1">; +def warn_pch_gnu_inline : Warning< + "PCH file was compiled with %select{C99|GNU|}0 inline semantics but " + "%select{C99|GNU}1 inline semantics are currently selected">; +def warn_pch_no_inline : Warning< + "the macro '__NO_INLINE__' was %select{not defined|defined}0 in " + "the PCH file but is currently %select{undefined|defined}1">; +def warn_pch_gc_mode : Warning< + "the PCH file was built with %select{no||hybrid}0 garbage collection but " + "the current translation unit will compiled with %select{no||hybrid}1 " + "garbage collection">; } diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 4e66d2938d..624c5e4875 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -48,10 +48,6 @@ namespace clang { /// full PCH block. PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, - /// \brief The block containing information about the language - /// options used to build this precompiled header. - LANGUAGE_OPTIONS_BLOCK_ID, - /// \brief The block containing information about the source /// manager. SOURCE_MANAGER_BLOCK_ID, @@ -96,7 +92,15 @@ namespace clang { /// record, after subtracting one to account for the use of /// declaration ID 0 for a NULL declaration pointer. Index 0 is /// reserved for the translation unit declaration. - DECL_OFFSET = 2 + DECL_OFFSET = 2, + + /// \brief Record code for the language options table. + /// + /// The record with this code contains the contents of the + /// LangOptions structure. We serialize the entire contents of + /// the structure, and let the reader decide which options are + /// actually important to check. + LANGUAGE_OPTIONS = 3 }; /// \brief Record types used within a source manager block. diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 52354e3eb3..498d5fffeb 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -13,10 +13,11 @@ #ifndef LLVM_CLANG_FRONTEND_PCH_READER_H #define LLVM_CLANG_FRONTEND_PCH_READER_H +#include "clang/Frontend/PCHBitCodes.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Type.h" -#include "clang/Frontend/PCHBitCodes.h" +#include "clang/Basic/Diagnostic.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" @@ -59,6 +60,9 @@ class PCHReader : public ExternalASTSource { /// \brief The bitstream reader from which we'll read the PCH file. llvm::BitstreamReader Stream; + /// \brief The file name of the PCH file. + std::string FileName; + /// \brief The memory buffer that stores the data associated with /// this PCH file. llvm::OwningPtr<llvm::MemoryBuffer> Buffer; @@ -99,9 +103,12 @@ class PCHReader : public ExternalASTSource { /// DeclContext. DeclContextOffsetsMap DeclContextOffsets; - bool ReadPCHBlock(); + enum PCHReadResult { Success, Failure, IgnorePCH }; + + PCHReadResult ReadPCHBlock(); bool ReadSourceManagerBlock(); + bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record); QualType ReadTypeRecord(uint64_t Offset); void LoadedDecl(unsigned Index, Decl *D); Decl *ReadDeclRecord(uint64_t Offset, unsigned Index); @@ -165,6 +172,9 @@ public: /// \brief Print some statistics about PCH usage. virtual void PrintStats(); + /// \brief Report a diagnostic. + DiagnosticBuilder Diag(unsigned DiagID); + const IdentifierInfo *GetIdentifierInfo(const RecordData &Record, unsigned &Idx); DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 41aa91ddf1..df5175159d 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -76,6 +76,7 @@ class PCHWriter { /// \brief The type ID that will be assigned to the next new type. pch::TypeID NextTypeID; + void WriteLanguageOptions(const LangOptions &LangOpts); void WriteSourceManagerBlock(SourceManager &SourceMgr); void WritePreprocessor(const Preprocessor &PP); void WriteType(const Type *T); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 0e5b6ee8aa..a00fee27fb 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// #include "clang/Frontend/PCHReader.h" -#include "clang/Frontend/PCHBitCodes.h" +#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/Type.h" @@ -192,18 +192,22 @@ bool PCHReader::ReadSourceManagerBlock() { } } -bool PCHReader::ReadPCHBlock() { - if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) - return Error("Malformed block record"); +PCHReader::PCHReadResult PCHReader::ReadPCHBlock() { + if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { + Error("Malformed block record"); + return Failure; + } // Read all of the records and blocks for the PCH file. RecordData Record; while (!Stream.AtEndOfStream()) { unsigned Code = Stream.ReadCode(); if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) - return Error("Error at end of module block"); - return false; + if (Stream.ReadBlockEnd()) { + Error("Error at end of module block"); + return Failure; + } + return Success; } if (Code == llvm::bitc::ENTER_SUBBLOCK) { @@ -211,13 +215,17 @@ bool PCHReader::ReadPCHBlock() { case pch::DECLS_BLOCK_ID: // Skip decls block (lazily loaded) case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded) default: // Skip unknown content. - if (Stream.SkipBlock()) - return Error("Malformed block record"); + if (Stream.SkipBlock()) { + Error("Malformed block record"); + return Failure; + } break; case pch::SOURCE_MANAGER_BLOCK_ID: - if (ReadSourceManagerBlock()) - return Error("Malformed source manager block"); + if (ReadSourceManagerBlock()) { + Error("Malformed source manager block"); + return Failure; + } break; } continue; @@ -235,27 +243,40 @@ bool PCHReader::ReadPCHBlock() { break; case pch::TYPE_OFFSET: - if (!TypeOffsets.empty()) - return Error("Duplicate TYPE_OFFSET record in PCH file"); + if (!TypeOffsets.empty()) { + Error("Duplicate TYPE_OFFSET record in PCH file"); + return Failure; + } TypeOffsets.swap(Record); TypeAlreadyLoaded.resize(TypeOffsets.size(), false); break; case pch::DECL_OFFSET: - if (!DeclOffsets.empty()) - return Error("Duplicate DECL_OFFSET record in PCH file"); + if (!DeclOffsets.empty()) { + Error("Duplicate DECL_OFFSET record in PCH file"); + return Failure; + } DeclOffsets.swap(Record); DeclAlreadyLoaded.resize(DeclOffsets.size(), false); break; + + case pch::LANGUAGE_OPTIONS: + if (ParseLanguageOptions(Record)) + return IgnorePCH; + break; } } - return Error("Premature end of bitstream"); + Error("Premature end of bitstream"); + return Failure; } PCHReader::~PCHReader() { } bool PCHReader::ReadPCH(const std::string &FileName) { + // Set the PCH file name. + this->FileName = FileName; + // Open the PCH file. std::string ErrStr; Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr)); @@ -290,8 +311,20 @@ bool PCHReader::ReadPCH(const std::string &FileName) { return Error("Malformed BlockInfoBlock"); break; case pch::PCH_BLOCK_ID: - if (ReadPCHBlock()) + switch (ReadPCHBlock()) { + case Success: + break; + + case Failure: return true; + + case IgnorePCH: + if (Stream.SkipBlock()) { + Error("Malformed block record"); + return true; + } + return false; + } break; default: if (Stream.SkipBlock()) @@ -306,6 +339,95 @@ bool PCHReader::ReadPCH(const std::string &FileName) { return false; } +/// \brief Parse the record that corresponds to a LangOptions data +/// structure. +/// +/// This routine compares the language options used to generate the +/// PCH file against the language options set for the current +/// compilation. For each option, we classify differences between the +/// two compiler states as either "benign" or "important". Benign +/// differences don't matter, and we accept them without complaint +/// (and without modifying the language options). Differences between +/// the states for important options cause the PCH file to be +/// unusable, so we emit a warning and return true to indicate that +/// there was an error. +/// +/// \returns true if the PCH file is unacceptable, false otherwise. +bool PCHReader::ParseLanguageOptions( + const llvm::SmallVectorImpl<uint64_t> &Record) { + const LangOptions &LangOpts = Context.getLangOptions(); +#define PARSE_LANGOPT_BENIGN(Option) ++Idx +#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \ + if (Record[Idx] != LangOpts.Option) { \ + Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \ + Diag(diag::note_ignoring_pch) << FileName; \ + return true; \ + } \ + ++Idx + + unsigned Idx = 0; + PARSE_LANGOPT_BENIGN(Trigraphs); + PARSE_LANGOPT_BENIGN(BCPLComment); + PARSE_LANGOPT_BENIGN(DollarIdents); + PARSE_LANGOPT_BENIGN(AsmPreprocessor); + PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions); + PARSE_LANGOPT_BENIGN(ImplicitInt); + PARSE_LANGOPT_BENIGN(Digraphs); + PARSE_LANGOPT_BENIGN(HexFloats); + PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99); + PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions); + PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus); + PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x); + PARSE_LANGOPT_IMPORTANT(NoExtensions, diag::warn_pch_extensions); + PARSE_LANGOPT_BENIGN(CXXOperatorName); + PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c); + PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2); + PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi); + PARSE_LANGOPT_BENIGN(PascalStrings); + PARSE_LANGOPT_BENIGN(Boolean); + PARSE_LANGOPT_BENIGN(WritableStrings); + PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, + diag::warn_pch_lax_vector_conversions); + PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions); + PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime); + PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding); + PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins); + PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics, + diag::warn_pch_thread_safe_statics); + PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks); + PARSE_LANGOPT_BENIGN(EmitAllDecls); + PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno); + PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking); + PARSE_LANGOPT_IMPORTANT(HeinousExtensions, + diag::warn_pch_heinous_extensions); + // FIXME: Most of the options below are benign if the macro wasn't + // used. Unfortunately, this means that a PCH compiled without + // optimization can't be used with optimization turned on, even + // though the only thing that changes is whether __OPTIMIZE__ was + // defined... but if __OPTIMIZE__ never showed up in the header, it + // doesn't matter. We could consider making this some special kind + // of check. + PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize); + PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size); + PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static); + PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level); + PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline); + PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline); + if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) { + Diag(diag::warn_pch_gc_mode) + << (unsigned)Record[Idx] << LangOpts.getGCMode(); + Diag(diag::note_ignoring_pch) << FileName; + return true; + } + ++Idx; + PARSE_LANGOPT_BENIGN(getVisibilityMode()); + PARSE_LANGOPT_BENIGN(InstantiationDepth); +#undef PARSE_LANGOPT_IRRELEVANT +#undef PARSE_LANGOPT_BENIGN + + return false; +} + /// \brief Read and return the type at the given offset. /// /// This routine actually reads the record corresponding to the type @@ -619,3 +741,9 @@ PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { // Required to silence GCC warning return DeclarationName(); } + +DiagnosticBuilder PCHReader::Diag(unsigned DiagID) { + return PP.getDiagnostics().Report(FullSourceLoc(SourceLocation(), + Context.getSourceManager()), + DiagID); +} diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 6f4492bc8c..6feb726b42 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -328,6 +328,67 @@ void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, // PCHWriter Implementation //===----------------------------------------------------------------------===// +void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { + RecordData Record; + Record.push_back(LangOpts.Trigraphs); + Record.push_back(LangOpts.BCPLComment); // BCPL-style '//' comments. + Record.push_back(LangOpts.DollarIdents); // '$' allowed in identifiers. + Record.push_back(LangOpts.AsmPreprocessor); // Preprocessor in asm mode. + Record.push_back(LangOpts.GNUMode); // True in gnu99 mode false in c99 mode (etc) + Record.push_back(LangOpts.ImplicitInt); // C89 implicit 'int'. + Record.push_back(LangOpts.Digraphs); // C94, C99 and C++ + Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants. + Record.push_back(LangOpts.C99); // C99 Support + Record.push_back(LangOpts.Microsoft); // Microsoft extensions. + Record.push_back(LangOpts.CPlusPlus); // C++ Support + Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support + Record.push_back(LangOpts.NoExtensions); // All extensions are disabled, strict mode. + Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords. + + Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled. + Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled. + Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C modern abi enabled + + Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings + Record.push_back(LangOpts.Boolean); // Allow bool/true/false + Record.push_back(LangOpts.WritableStrings); // Allow writable strings + Record.push_back(LangOpts.LaxVectorConversions); + Record.push_back(LangOpts.Exceptions); // Support exception handling. + + Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime. + Record.push_back(LangOpts.Freestanding); // Freestanding implementation + Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin) + + Record.push_back(LangOpts.ThreadsafeStatics); // Whether static initializers are protected + // by locks. + Record.push_back(LangOpts.Blocks); // block extension to C + Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if + // they are unused. + Record.push_back(LangOpts.MathErrno); // Math functions must respect errno + // (modulo the platform support). + + Record.push_back(LangOpts.OverflowChecking); // Extension to call a handler function when + // signed integer arithmetic overflows. + + Record.push_back(LangOpts.HeinousExtensions); // Extensions that we really don't like and + // may be ripped out at any time. + + Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined. + Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be + // defined. + Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as + // opposed to __DYNAMIC__). + Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero. + + Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be + // used (instead of C99 semantics). + Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined. + Record.push_back(LangOpts.getGCMode()); + Record.push_back(LangOpts.getVisibilityMode()); + Record.push_back(LangOpts.InstantiationDepth); + S.EmitRecord(pch::LANGUAGE_OPTIONS, Record); +} + //===----------------------------------------------------------------------===// // Source Manager Serialization //===----------------------------------------------------------------------===// @@ -625,9 +686,6 @@ void PCHWriter::WriteTypesBlock(ASTContext &Context) { // Exit the types block S.ExitBlock(); - - // Write the type offsets record - S.EmitRecord(pch::TYPE_OFFSET, TypeOffsets); } /// \brief Write the block containing all of the declaration IDs @@ -740,9 +798,6 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) { // Exit the declarations block S.ExitBlock(); - - // Write the declaration offsets record - S.EmitRecord(pch::DECL_OFFSET, DeclOffsets); } PCHWriter::PCHWriter(llvm::BitstreamWriter &S) @@ -761,10 +816,13 @@ void PCHWriter::WritePCH(ASTContext &Context, const Preprocessor &PP) { // Write the remaining PCH contents. S.EnterSubblock(pch::PCH_BLOCK_ID, 2); + WriteLanguageOptions(Context.getLangOptions()); WriteSourceManagerBlock(Context.getSourceManager()); WritePreprocessor(PP); WriteTypesBlock(Context); WriteDeclsBlock(Context); + S.EmitRecord(pch::TYPE_OFFSET, TypeOffsets); + S.EmitRecord(pch::DECL_OFFSET, DeclOffsets); S.ExitBlock(); } |