diff options
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 974 |
1 files changed, 671 insertions, 303 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index a2e8b71..cf93d1c 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -13,24 +13,15 @@ #include "clang/Serialization/ASTWriter.h" #include "ASTCommon.h" -#include "clang/Sema/Sema.h" -#include "clang/Sema/IdentifierResolver.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclContextInternals.h" -#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" -#include "clang/Serialization/ASTReader.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/Lex/HeaderSearch.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemStatCache.h" #include "clang/Basic/OnDiskHashTable.h" @@ -40,8 +31,18 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" #include "clang/Basic/VersionTuple.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/PreprocessingRecord.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "clang/Sema/IdentifierResolver.h" +#include "clang/Sema/Sema.h" +#include "clang/Serialization/ASTReader.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Support/FileSystem.h" @@ -353,7 +354,7 @@ ASTTypeWriter::VisitDependentTemplateSpecializationType( void ASTTypeWriter::VisitPackExpansionType(const PackExpansionType *T) { Writer.AddTypeRef(T->getPattern(), Record); - if (llvm::Optional<unsigned> NumExpansions = T->getNumExpansions()) + if (Optional<unsigned> NumExpansions = T->getNumExpansions()) Record.push_back(*NumExpansions + 1); else Record.push_back(0); @@ -777,6 +778,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(TARGET_OPTIONS); RECORD(ORIGINAL_FILE); RECORD(ORIGINAL_PCH_DIR); + RECORD(ORIGINAL_FILE_ID); RECORD(INPUT_FILE_OFFSETS); RECORD(DIAGNOSTIC_OPTIONS); RECORD(FILE_SYSTEM_OPTIONS); @@ -797,7 +799,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(STATISTICS); RECORD(TENTATIVE_DEFINITIONS); RECORD(UNUSED_FILESCOPED_DECLS); - RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS); + RECORD(LOCALLY_SCOPED_EXTERN_C_DECLS); RECORD(SELECTOR_OFFSETS); RECORD(METHOD_POOL); RECORD(PP_COUNTER_VALUE); @@ -823,6 +825,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(OPENCL_EXTENSIONS); RECORD(DELEGATING_CTORS); RECORD(KNOWN_NAMESPACES); + RECORD(UNDEFINED_BUT_USED); RECORD(MODULE_OFFSET_MAP); RECORD(SOURCE_MANAGER_LINE_TABLE); RECORD(OBJC_CATEGORIES_MAP); @@ -832,7 +835,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(LOCAL_REDECLARATIONS); RECORD(OBJC_CATEGORIES); RECORD(MACRO_OFFSET); - RECORD(MACRO_UPDATES); + RECORD(MACRO_TABLE); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -1020,7 +1023,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, // Imports if (Chain) { serialization::ModuleManager &Mgr = Chain->getModuleManager(); - llvm::SmallVector<char, 128> ModulePaths; + SmallVector<char, 128> ModulePaths; Record.clear(); for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end(); @@ -1030,7 +1033,9 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, continue; Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding - // FIXME: Write import location, once it matters. + AddSourceLocation((*M)->ImportLoc, Record); + Record.push_back((*M)->File->getSize()); + Record.push_back((*M)->File->getModificationTime()); // FIXME: This writes the absolute path for AST files we depend on. const std::string &FileName = (*M)->FileName; Record.push_back(FileName.size()); @@ -1047,12 +1052,24 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ Record.push_back(static_cast<unsigned>(LangOpts.get##Name())); #include "clang/Basic/LangOptions.def" +#define SANITIZER(NAME, ID) Record.push_back(LangOpts.Sanitize.ID); +#include "clang/Basic/Sanitizers.def" Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind()); AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record); Record.push_back(LangOpts.CurrentModule.size()); Record.append(LangOpts.CurrentModule.begin(), LangOpts.CurrentModule.end()); + + // Comment options. + Record.push_back(LangOpts.CommentOpts.BlockCommandNames.size()); + for (CommentOptions::BlockCommandNamesTy::const_iterator + I = LangOpts.CommentOpts.BlockCommandNames.begin(), + IEnd = LangOpts.CommentOpts.BlockCommandNames.end(); + I != IEnd; ++I) { + AddString(*I, Record); + } + Stream.EmitRecord(LANGUAGE_OPTIONS, Record); // Target options. @@ -1108,11 +1125,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I]; AddString(Entry.Path, Record); Record.push_back(static_cast<unsigned>(Entry.Group)); - Record.push_back(Entry.IsUserSupplied); Record.push_back(Entry.IsFramework); Record.push_back(Entry.IgnoreSysRoot); - Record.push_back(Entry.IsInternal); - Record.push_back(Entry.ImplicitExternC); } // System header prefixes. @@ -1180,6 +1194,10 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); } + Record.clear(); + Record.push_back(SM.getMainFileID().getOpaqueValue()); + Stream.EmitRecord(ORIGINAL_FILE_ID, Record); + // Original PCH directory if (!OutputFile.empty() && OutputFile != "-") { BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); @@ -1197,11 +1215,24 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); } - WriteInputFiles(Context.SourceMgr, isysroot); + WriteInputFiles(Context.SourceMgr, + PP.getHeaderSearchInfo().getHeaderSearchOpts(), + isysroot); Stream.ExitBlock(); } -void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { +namespace { + /// \brief An input file. + struct InputFileEntry { + const FileEntry *File; + bool IsSystemFile; + bool BufferOverridden; + }; +} + +void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, + HeaderSearchOptions &HSOpts, + StringRef isysroot) { using namespace llvm; Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); RecordData Record; @@ -1216,8 +1247,9 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name unsigned IFAbbrevCode = Stream.EmitAbbrev(IFAbbrev); - // Write out all of the input files. - std::vector<uint32_t> InputFileOffsets; + // Get all ContentCache objects for files, sorted by whether the file is a + // system one or not. System files go at the back, users files at the front. + std::deque<InputFileEntry> SortedFiles; for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { // Get this source location entry. const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); @@ -1230,28 +1262,67 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { if (!Cache->OrigEntry) continue; + InputFileEntry Entry; + Entry.File = Cache->OrigEntry; + Entry.IsSystemFile = Cache->IsSystemFile; + Entry.BufferOverridden = Cache->BufferOverridden; + if (Cache->IsSystemFile) + SortedFiles.push_back(Entry); + else + SortedFiles.push_front(Entry); + } + + // If we have an isysroot for a Darwin SDK, include its SDKSettings.plist in + // the set of (non-system) input files. This is simple heuristic for + // detecting whether the system headers may have changed, because it is too + // expensive to stat() all of the system headers. + FileManager &FileMgr = SourceMgr.getFileManager(); + if (!HSOpts.Sysroot.empty() && !Chain) { + llvm::SmallString<128> SDKSettingsFileName(HSOpts.Sysroot); + llvm::sys::path::append(SDKSettingsFileName, "SDKSettings.plist"); + if (const FileEntry *SDKSettingsFile = FileMgr.getFile(SDKSettingsFileName)) { + InputFileEntry Entry = { SDKSettingsFile, false, false }; + SortedFiles.push_front(Entry); + } + } + + unsigned UserFilesNum = 0; + // Write out all of the input files. + std::vector<uint32_t> InputFileOffsets; + for (std::deque<InputFileEntry>::iterator + I = SortedFiles.begin(), E = SortedFiles.end(); I != E; ++I) { + const InputFileEntry &Entry = *I; + + uint32_t &InputFileID = InputFileIDs[Entry.File]; + if (InputFileID != 0) + continue; // already recorded this file. + // Record this entry's offset. InputFileOffsets.push_back(Stream.GetCurrentBitNo()); - InputFileIDs[Cache->OrigEntry] = InputFileOffsets.size(); + + InputFileID = InputFileOffsets.size(); + + if (!Entry.IsSystemFile) + ++UserFilesNum; Record.clear(); Record.push_back(INPUT_FILE); Record.push_back(InputFileOffsets.size()); // Emit size/modification time for this file. - Record.push_back(Cache->OrigEntry->getSize()); - Record.push_back(Cache->OrigEntry->getModificationTime()); + Record.push_back(Entry.File->getSize()); + Record.push_back(Entry.File->getModificationTime()); // Whether this file was overridden. - Record.push_back(Cache->BufferOverridden); + Record.push_back(Entry.BufferOverridden); // Turn the file name into an absolute path, if it isn't already. - const char *Filename = Cache->OrigEntry->getName(); + const char *Filename = Entry.File->getName(); SmallString<128> FilePath(Filename); // Ask the file manager to fixup the relative path for us. This will // honor the working directory. - SourceMgr.getFileManager().FixupRelativePath(FilePath); + FileMgr.FixupRelativePath(FilePath); // FIXME: This call to make_absolute shouldn't be necessary, the // call to FixupRelativePath should always return an absolute path. @@ -1262,13 +1333,15 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { Stream.EmitRecordWithBlob(IFAbbrevCode, Record, Filename); } - + Stream.ExitBlock(); // Create input file offsets abbreviation. BitCodeAbbrev *OffsetsAbbrev = new BitCodeAbbrev(); OffsetsAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_OFFSETS)); OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # input files + OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # non-system + // input files OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Array unsigned OffsetsAbbrevCode = Stream.EmitAbbrev(OffsetsAbbrev); @@ -1276,58 +1349,11 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { Record.clear(); Record.push_back(INPUT_FILE_OFFSETS); Record.push_back(InputFileOffsets.size()); + Record.push_back(UserFilesNum); Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, data(InputFileOffsets)); } //===----------------------------------------------------------------------===// -// stat cache Serialization -//===----------------------------------------------------------------------===// - -namespace { -// Trait used for the on-disk hash table of stat cache results. -class ASTStatCacheTrait { -public: - typedef const char * key_type; - typedef key_type key_type_ref; - - typedef struct stat data_type; - typedef const data_type &data_type_ref; - - static unsigned ComputeHash(const char *path) { - return llvm::HashString(path); - } - - std::pair<unsigned,unsigned> - EmitKeyDataLength(raw_ostream& Out, const char *path, - data_type_ref Data) { - unsigned StrLen = strlen(path); - clang::io::Emit16(Out, StrLen); - unsigned DataLen = 4 + 4 + 2 + 8 + 8; - clang::io::Emit8(Out, DataLen); - return std::make_pair(StrLen + 1, DataLen); - } - - void EmitKey(raw_ostream& Out, const char *path, unsigned KeyLen) { - Out.write(path, KeyLen); - } - - void EmitData(raw_ostream &Out, key_type_ref, - data_type_ref Data, unsigned DataLen) { - using namespace clang::io; - uint64_t Start = Out.tell(); (void)Start; - - Emit32(Out, (uint32_t) Data.st_ino); - Emit32(Out, (uint32_t) Data.st_dev); - Emit16(Out, (uint16_t) Data.st_mode); - Emit64(Out, (uint64_t) Data.st_mtime); - Emit64(Out, (uint64_t) Data.st_size); - - assert(Out.tell() - Start == DataLen && "Wrong data length"); - } -}; -} // end anonymous namespace - -//===----------------------------------------------------------------------===// // Source Manager Serialization //===----------------------------------------------------------------------===// @@ -1391,44 +1417,53 @@ namespace { // Trait used for the on-disk hash table of header search information. class HeaderFileInfoTrait { ASTWriter &Writer; + const HeaderSearch &HS; // Keep track of the framework names we've used during serialization. SmallVector<char, 128> FrameworkStringData; llvm::StringMap<unsigned> FrameworkNameOffset; public: - HeaderFileInfoTrait(ASTWriter &Writer) - : Writer(Writer) { } + HeaderFileInfoTrait(ASTWriter &Writer, const HeaderSearch &HS) + : Writer(Writer), HS(HS) { } - typedef const char *key_type; - typedef key_type key_type_ref; + struct key_type { + const FileEntry *FE; + const char *Filename; + }; + typedef const key_type &key_type_ref; typedef HeaderFileInfo data_type; typedef const data_type &data_type_ref; - static unsigned ComputeHash(const char *path) { - // The hash is based only on the filename portion of the key, so that the - // reader can match based on filenames when symlinking or excess path - // elements ("foo/../", "../") change the form of the name. However, - // complete path is still the key. - return llvm::HashString(llvm::sys::path::filename(path)); + static unsigned ComputeHash(key_type_ref key) { + // The hash is based only on size/time of the file, so that the reader can + // match even when symlinking or excess path elements ("foo/../", "../") + // change the form of the name. However, complete path is still the key. + return llvm::hash_combine(key.FE->getSize(), + key.FE->getModificationTime()); } std::pair<unsigned,unsigned> - EmitKeyDataLength(raw_ostream& Out, const char *path, - data_type_ref Data) { - unsigned StrLen = strlen(path); - clang::io::Emit16(Out, StrLen); + EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) { + unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8; + clang::io::Emit16(Out, KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; + if (Data.isModuleHeader) + DataLen += 4; clang::io::Emit8(Out, DataLen); - return std::make_pair(StrLen + 1, DataLen); + return std::make_pair(KeyLen, DataLen); } - void EmitKey(raw_ostream& Out, const char *path, unsigned KeyLen) { - Out.write(path, KeyLen); + void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) { + clang::io::Emit64(Out, key.FE->getSize()); + KeyLen -= 8; + clang::io::Emit64(Out, key.FE->getModificationTime()); + KeyLen -= 8; + Out.write(key.Filename, KeyLen); } - void EmitData(raw_ostream &Out, key_type_ref, + void EmitData(raw_ostream &Out, key_type_ref key, data_type_ref Data, unsigned DataLen) { using namespace clang::io; uint64_t Start = Out.tell(); (void)Start; @@ -1462,7 +1497,12 @@ namespace { Offset = Pos->second; } Emit32(Out, Offset); - + + if (Data.isModuleHeader) { + Module *Mod = HS.findModuleForHeader(key.FE); + Emit32(Out, Writer.getExistingSubmoduleID(Mod)); + } + assert(Out.tell() - Start == DataLen && "Wrong data length"); } @@ -1481,7 +1521,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { if (FilesByUID.size() > HS.header_file_size()) FilesByUID.resize(HS.header_file_size()); - HeaderFileInfoTrait GeneratorTrait(*this); + HeaderFileInfoTrait GeneratorTrait(*this, HS); OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator; SmallVector<const char *, 4> SavedStrings; unsigned NumHeaderSearchEntries = 0; @@ -1507,7 +1547,8 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { SavedStrings.push_back(Filename); } - Generator.insert(Filename, HFI, GeneratorTrait); + HeaderFileInfoTrait::key_type key = { File, Filename }; + Generator.insert(key, HFI, GeneratorTrait); ++NumHeaderSearchEntries; } @@ -1542,7 +1583,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { // Free all of the strings we had to duplicate. for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I) - free((void*)SavedStrings[I]); + free(const_cast<char *>(SavedStrings[I])); } /// \brief Writes the block containing the serialized form of the @@ -1746,14 +1787,67 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Preprocessor Serialization //===----------------------------------------------------------------------===// -static int compareMacroDefinitions(const void *XPtr, const void *YPtr) { - const std::pair<const IdentifierInfo *, MacroInfo *> &X = - *(const std::pair<const IdentifierInfo *, MacroInfo *>*)XPtr; - const std::pair<const IdentifierInfo *, MacroInfo *> &Y = - *(const std::pair<const IdentifierInfo *, MacroInfo *>*)YPtr; +namespace { +class ASTMacroTableTrait { +public: + typedef IdentID key_type; + typedef key_type key_type_ref; + + struct Data { + uint32_t MacroDirectivesOffset; + }; + + typedef Data data_type; + typedef const data_type &data_type_ref; + + static unsigned ComputeHash(IdentID IdID) { + return llvm::hash_value(IdID); + } + + std::pair<unsigned,unsigned> + static EmitKeyDataLength(raw_ostream& Out, + key_type_ref Key, data_type_ref Data) { + unsigned KeyLen = 4; // IdentID. + unsigned DataLen = 4; // MacroDirectivesOffset. + return std::make_pair(KeyLen, DataLen); + } + + static void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { + clang::io::Emit32(Out, Key); + } + + static void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, + unsigned) { + clang::io::Emit32(Out, Data.MacroDirectivesOffset); + } +}; +} // end anonymous namespace + +static int compareMacroDirectives(const void *XPtr, const void *YPtr) { + const std::pair<const IdentifierInfo *, MacroDirective *> &X = + *(const std::pair<const IdentifierInfo *, MacroDirective *>*)XPtr; + const std::pair<const IdentifierInfo *, MacroDirective *> &Y = + *(const std::pair<const IdentifierInfo *, MacroDirective *>*)YPtr; return X.first->getName().compare(Y.first->getName()); } +static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, + const Preprocessor &PP) { + if (MacroInfo *MI = MD->getMacroInfo()) + if (MI->isBuiltinMacro()) + return true; + + if (IsModule) { + SourceLocation Loc = MD->getLocation(); + if (Loc.isInvalid()) + return true; + if (PP.getSourceManager().getFileID(Loc) == PP.getPredefinesFileID()) + return true; + } + + return false; +} + /// \brief Writes the block containing the serialized form of the /// preprocessor. /// @@ -1780,26 +1874,73 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n"); - // Loop over all the macro definitions that are live at the end of the file, + // Loop over all the macro directives that are live at the end of the file, // emitting each to the PP section. - // Construct the list of macro definitions that need to be serialized. - SmallVector<std::pair<const IdentifierInfo *, MacroInfo *>, 2> - MacrosToEmit; - llvm::SmallPtrSet<const IdentifierInfo*, 4> MacroDefinitionsSeen; - for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0), - E = PP.macro_end(Chain == 0); + // Construct the list of macro directives that need to be serialized. + SmallVector<std::pair<const IdentifierInfo *, MacroDirective *>, 2> + MacroDirectives; + for (Preprocessor::macro_iterator + I = PP.macro_begin(/*IncludeExternalMacros=*/false), + E = PP.macro_end(/*IncludeExternalMacros=*/false); I != E; ++I) { - if (!IsModule || I->second->isPublic()) { - MacroDefinitionsSeen.insert(I->first); - MacrosToEmit.push_back(std::make_pair(I->first, I->second)); - } + MacroDirectives.push_back(std::make_pair(I->first, I->second)); } // Sort the set of macro definitions that need to be serialized by the // name of the macro, to provide a stable ordering. - llvm::array_pod_sort(MacrosToEmit.begin(), MacrosToEmit.end(), - &compareMacroDefinitions); + llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(), + &compareMacroDirectives); + + OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator; + + // Emit the macro directives as a list and associate the offset with the + // identifier they belong to. + for (unsigned I = 0, N = MacroDirectives.size(); I != N; ++I) { + const IdentifierInfo *Name = MacroDirectives[I].first; + uint64_t MacroDirectiveOffset = Stream.GetCurrentBitNo(); + MacroDirective *MD = MacroDirectives[I].second; + + // If the macro or identifier need no updates, don't write the macro history + // for this one. + // FIXME: Chain the macro history instead of re-writing it. + if (MD->isFromPCH() && + Name->isFromAST() && !Name->hasChangedSinceDeserialization()) + continue; + + // Emit the macro directives in reverse source order. + for (; MD; MD = MD->getPrevious()) { + if (MD->isHidden()) + continue; + if (shouldIgnoreMacro(MD, IsModule, PP)) + continue; + + AddSourceLocation(MD->getLocation(), Record); + Record.push_back(MD->getKind()); + if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { + MacroID InfoID = getMacroRef(DefMD->getInfo(), Name); + Record.push_back(InfoID); + Record.push_back(DefMD->isImported()); + Record.push_back(DefMD->isAmbiguous()); + + } else if (VisibilityMacroDirective * + VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { + Record.push_back(VisMD->isPublic()); + } + } + if (Record.empty()) + continue; + + Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record); + Record.clear(); + + IdentMacroDirectivesOffsetMap[Name] = MacroDirectiveOffset; + + IdentID NameID = getIdentifierRef(Name); + ASTMacroTableTrait::Data data; + data.MacroDirectivesOffset = MacroDirectiveOffset; + Generator.insert(NameID, data); + } /// \brief Offsets of each of the macros into the bitstream, indexed by /// the local macro ID @@ -1809,95 +1950,107 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { /// defined. std::vector<uint32_t> MacroOffsets; - for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) { - const IdentifierInfo *Name = MacrosToEmit[I].first; + for (unsigned I = 0, N = MacroInfosToEmit.size(); I != N; ++I) { + const IdentifierInfo *Name = MacroInfosToEmit[I].Name; + MacroInfo *MI = MacroInfosToEmit[I].MI; + MacroID ID = MacroInfosToEmit[I].ID; - for (MacroInfo *MI = MacrosToEmit[I].second; MI; - MI = MI->getPreviousDefinition()) { - MacroID ID = getMacroRef(MI); - if (!ID) - continue; + if (ID < FirstMacroID) { + assert(0 && "Loaded MacroInfo entered MacroInfosToEmit ?"); + continue; + } - // Skip macros from a AST file if we're chaining. - if (Chain && MI->isFromAST() && !MI->hasChangedAfterLoad()) - continue; + // Record the local offset of this macro. + unsigned Index = ID - FirstMacroID; + if (Index == MacroOffsets.size()) + MacroOffsets.push_back(Stream.GetCurrentBitNo()); + else { + if (Index > MacroOffsets.size()) + MacroOffsets.resize(Index + 1); - if (ID < FirstMacroID) { - // This will have been dealt with via an update record. - assert(MacroUpdates.count(MI) > 0 && "Missing macro update"); - continue; - } + MacroOffsets[Index] = Stream.GetCurrentBitNo(); + } - // Record the local offset of this macro. - unsigned Index = ID - FirstMacroID; - if (Index == MacroOffsets.size()) - MacroOffsets.push_back(Stream.GetCurrentBitNo()); - else { - if (Index > MacroOffsets.size()) - MacroOffsets.resize(Index + 1); + AddIdentifierRef(Name, Record); + Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc())); + AddSourceLocation(MI->getDefinitionLoc(), Record); + AddSourceLocation(MI->getDefinitionEndLoc(), Record); + Record.push_back(MI->isUsed()); + unsigned Code; + if (MI->isObjectLike()) { + Code = PP_MACRO_OBJECT_LIKE; + } else { + Code = PP_MACRO_FUNCTION_LIKE; - MacroOffsets[Index] = Stream.GetCurrentBitNo(); - } + Record.push_back(MI->isC99Varargs()); + Record.push_back(MI->isGNUVarargs()); + Record.push_back(MI->hasCommaPasting()); + Record.push_back(MI->getNumArgs()); + for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end(); + I != E; ++I) + AddIdentifierRef(*I, Record); + } - AddIdentifierRef(Name, Record); - addMacroRef(MI, Record); - Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc())); - AddSourceLocation(MI->getDefinitionLoc(), Record); - AddSourceLocation(MI->getUndefLoc(), Record); - Record.push_back(MI->isUsed()); - Record.push_back(MI->isPublic()); - AddSourceLocation(MI->getVisibilityLocation(), Record); - unsigned Code; - if (MI->isObjectLike()) { - Code = PP_MACRO_OBJECT_LIKE; - } else { - Code = PP_MACRO_FUNCTION_LIKE; - - Record.push_back(MI->isC99Varargs()); - Record.push_back(MI->isGNUVarargs()); - Record.push_back(MI->getNumArgs()); - for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end(); - I != E; ++I) - AddIdentifierRef(*I, Record); - } + // If we have a detailed preprocessing record, record the macro definition + // ID that corresponds to this macro. + if (PPRec) + Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]); - // If we have a detailed preprocessing record, record the macro definition - // ID that corresponds to this macro. - if (PPRec) - Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]); + Stream.EmitRecord(Code, Record); + Record.clear(); - Stream.EmitRecord(Code, Record); + // Emit the tokens array. + for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { + // Note that we know that the preprocessor does not have any annotation + // tokens in it because they are created by the parser, and thus can't + // be in a macro definition. + const Token &Tok = MI->getReplacementToken(TokNo); + + Record.push_back(Tok.getLocation().getRawEncoding()); + Record.push_back(Tok.getLength()); + + // FIXME: When reading literal tokens, reconstruct the literal pointer + // if it is needed. + AddIdentifierRef(Tok.getIdentifierInfo(), Record); + // FIXME: Should translate token kind to a stable encoding. + Record.push_back(Tok.getKind()); + // FIXME: Should translate token flags to a stable encoding. + Record.push_back(Tok.getFlags()); + + Stream.EmitRecord(PP_TOKEN, Record); Record.clear(); - - // Emit the tokens array. - for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { - // Note that we know that the preprocessor does not have any annotation - // tokens in it because they are created by the parser, and thus can't - // be in a macro definition. - const Token &Tok = MI->getReplacementToken(TokNo); - - Record.push_back(Tok.getLocation().getRawEncoding()); - Record.push_back(Tok.getLength()); - - // FIXME: When reading literal tokens, reconstruct the literal pointer - // if it is needed. - AddIdentifierRef(Tok.getIdentifierInfo(), Record); - // FIXME: Should translate token kind to a stable encoding. - Record.push_back(Tok.getKind()); - // FIXME: Should translate token flags to a stable encoding. - Record.push_back(Tok.getFlags()); - - Stream.EmitRecord(PP_TOKEN, Record); - Record.clear(); - } - ++NumMacros; } + ++NumMacros; } + Stream.ExitBlock(); - // Write the offsets table for macro IDs. + // Create the on-disk hash table in a buffer. + SmallString<4096> MacroTable; + uint32_t BucketOffset; + { + llvm::raw_svector_ostream Out(MacroTable); + // Make sure that no bucket is at offset 0 + clang::io::Emit32(Out, 0); + BucketOffset = Generator.Emit(Out); + } + + // Write the macro table using namespace llvm; BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(MACRO_TABLE)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned MacroTableAbbrev = Stream.EmitAbbrev(Abbrev); + + Record.push_back(MACRO_TABLE); + Record.push_back(BucketOffset); + Stream.EmitRecordWithBlob(MacroTableAbbrev, Record, MacroTable.str()); + Record.clear(); + + // Write the offsets table for macro IDs. + using namespace llvm; + Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID @@ -2019,6 +2172,18 @@ unsigned ASTWriter::getSubmoduleID(Module *Mod) { return SubmoduleIDs[Mod] = NextSubmoduleID++; } +unsigned ASTWriter::getExistingSubmoduleID(Module *Mod) const { + if (!Mod) + return 0; + + llvm::DenseMap<Module *, unsigned>::const_iterator + Known = SubmoduleIDs.find(Mod); + if (Known != SubmoduleIDs.end()) + return Known->second; + + return 0; +} + /// \brief Compute the number of modules within the given tree (including the /// given module). static unsigned getNumberOfModules(Module *Mod) { @@ -2062,6 +2227,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild... + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned DefinitionAbbrev = Stream.EmitAbbrev(Abbrev); @@ -2095,6 +2261,23 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev); + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned LinkLibraryAbbrev = Stream.EmitAbbrev(Abbrev); + + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFIG_MACRO)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name + unsigned ConfigMacroAbbrev = Stream.EmitAbbrev(Abbrev); + + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFLICT)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Other module + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Message + unsigned ConflictAbbrev = Stream.EmitAbbrev(Abbrev); + // Write the submodule metadata block. RecordData Record; Record.push_back(getNumberOfModules(WritingModule)); @@ -2125,6 +2308,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Record.push_back(Mod->InferSubmodules); Record.push_back(Mod->InferExplicitSubmodules); Record.push_back(Mod->InferExportWildcard); + Record.push_back(Mod->ConfigMacrosExhaustive); Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name); // Emit the requirements. @@ -2163,11 +2347,13 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record, Mod->ExcludedHeaders[I]->getName()); } - for (unsigned I = 0, N = Mod->TopHeaders.size(); I != N; ++I) { + ArrayRef<const FileEntry *> + TopHeaders = Mod->getTopHeaders(PP->getFileManager()); + for (unsigned I = 0, N = TopHeaders.size(); I != N; ++I) { Record.clear(); Record.push_back(SUBMODULE_TOPHEADER); Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, - Mod->TopHeaders[I]->getName()); + TopHeaders[I]->getName()); } // Emit the imports. @@ -2197,7 +2383,35 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { } Stream.EmitRecord(SUBMODULE_EXPORTS, Record); } - + + // Emit the link libraries. + for (unsigned I = 0, N = Mod->LinkLibraries.size(); I != N; ++I) { + Record.clear(); + Record.push_back(SUBMODULE_LINK_LIBRARY); + Record.push_back(Mod->LinkLibraries[I].IsFramework); + Stream.EmitRecordWithBlob(LinkLibraryAbbrev, Record, + Mod->LinkLibraries[I].Library); + } + + // Emit the conflicts. + for (unsigned I = 0, N = Mod->Conflicts.size(); I != N; ++I) { + Record.clear(); + Record.push_back(SUBMODULE_CONFLICT); + unsigned OtherID = getSubmoduleID(Mod->Conflicts[I].Other); + assert(OtherID && "Unknown submodule!"); + Record.push_back(OtherID); + Stream.EmitRecordWithBlob(ConflictAbbrev, Record, + Mod->Conflicts[I].Message); + } + + // Emit the configuration macros. + for (unsigned I = 0, N = Mod->ConfigMacros.size(); I != N; ++I) { + Record.clear(); + Record.push_back(SUBMODULE_CONFIG_MACRO); + Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, + Mod->ConfigMacros[I]); + } + // Queue up the submodules of this module. for (Module::submodule_iterator Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); @@ -2230,8 +2444,14 @@ ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) { return getSubmoduleID(OwningMod); } -void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag) { - // FIXME: Make it work properly with modules. +void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, + bool isModule) { + // Make sure set diagnostic pragmas don't affect the translation unit that + // imports the module. + // FIXME: Make diagnostic pragma sections work properly with modules. + if (isModule) + return; + llvm::SmallDenseMap<const DiagnosticsEngine::DiagState *, unsigned, 64> DiagStateIDMap; unsigned CurrID = 0; @@ -2664,7 +2884,7 @@ class ASTIdentifierTableTrait { /// \brief Determines whether this is an "interesting" identifier /// that needs a full IdentifierInfo structure written into the hash /// table. - bool isInterestingIdentifier(IdentifierInfo *II, MacroInfo *&Macro) { + bool isInterestingIdentifier(IdentifierInfo *II, MacroDirective *&Macro) { if (II->isPoisoned() || II->isExtensionToken() || II->getObjCOrBuiltinID() || @@ -2675,16 +2895,101 @@ class ASTIdentifierTableTrait { return hadMacroDefinition(II, Macro); } - bool hadMacroDefinition(IdentifierInfo *II, MacroInfo *&Macro) { + bool hadMacroDefinition(IdentifierInfo *II, MacroDirective *&Macro) { if (!II->hadMacroDefinition()) return false; - if (Macro || (Macro = PP.getMacroInfoHistory(II))) - return !Macro->isBuiltinMacro() && (!IsModule || Macro->isPublic()); + if (Macro || (Macro = PP.getMacroDirectiveHistory(II))) { + if (!IsModule) + return !shouldIgnoreMacro(Macro, IsModule, PP); + SubmoduleID ModID; + if (getFirstPublicSubmoduleMacro(Macro, ModID)) + return true; + } return false; } + DefMacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD, + SubmoduleID &ModID) { + ModID = 0; + if (DefMacroDirective *DefMD = getPublicSubmoduleMacro(MD, ModID)) + if (!shouldIgnoreMacro(DefMD, IsModule, PP)) + return DefMD; + return 0; + } + + DefMacroDirective *getNextPublicSubmoduleMacro(DefMacroDirective *MD, + SubmoduleID &ModID) { + if (DefMacroDirective * + DefMD = getPublicSubmoduleMacro(MD->getPrevious(), ModID)) + if (!shouldIgnoreMacro(DefMD, IsModule, PP)) + return DefMD; + return 0; + } + + /// \brief Traverses the macro directives history and returns the latest + /// macro that is public and not undefined in the same submodule. + /// A macro that is defined in submodule A and undefined in submodule B, + /// will still be considered as defined/exported from submodule A. + DefMacroDirective *getPublicSubmoduleMacro(MacroDirective *MD, + SubmoduleID &ModID) { + if (!MD) + return 0; + + SubmoduleID OrigModID = ModID; + bool isUndefined = false; + Optional<bool> isPublic; + for (; MD; MD = MD->getPrevious()) { + if (MD->isHidden()) + continue; + + SubmoduleID ThisModID = getSubmoduleID(MD); + if (ThisModID == 0) { + isUndefined = false; + isPublic = Optional<bool>(); + continue; + } + if (ThisModID != ModID){ + ModID = ThisModID; + isUndefined = false; + isPublic = Optional<bool>(); + } + // We are looking for a definition in a different submodule than the one + // that we started with. If a submodule has re-definitions of the same + // macro, only the last definition will be used as the "exported" one. + if (ModID == OrigModID) + continue; + + if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { + if (!isUndefined && (!isPublic.hasValue() || isPublic.getValue())) + return DefMD; + continue; + } + + if (isa<UndefMacroDirective>(MD)) { + isUndefined = true; + continue; + } + + VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD); + if (!isPublic.hasValue()) + isPublic = VisMD->isPublic(); + } + + return 0; + } + + SubmoduleID getSubmoduleID(MacroDirective *MD) { + if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) { + MacroInfo *MI = DefMD->getInfo(); + if (unsigned ID = MI->getOwningModuleID()) + return ID; + return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc()); + } + return Writer.inferSubmoduleIDFromLocation(MD->getLocation()); + } + public: typedef IdentifierInfo* key_type; typedef key_type key_type_ref; @@ -2704,17 +3009,21 @@ public: EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { unsigned KeyLen = II->getLength() + 1; unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 - MacroInfo *Macro = 0; + MacroDirective *Macro = 0; if (isInterestingIdentifier(II, Macro)) { DataLen += 2; // 2 bytes for builtin ID DataLen += 2; // 2 bytes for flags if (hadMacroDefinition(II, Macro)) { - for (MacroInfo *M = Macro; M; M = M->getPreviousDefinition()) { - if (Writer.getMacroRef(M) != 0) - DataLen += 4; + DataLen += 4; // MacroDirectives offset. + if (IsModule) { + SubmoduleID ModID; + for (DefMacroDirective * + DefMD = getFirstPublicSubmoduleMacro(Macro, ModID); + DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) { + DataLen += 4; // MacroInfo ID. + } + DataLen += 4; } - - DataLen += 4; } for (IdentifierResolver::iterator D = IdResolver.begin(II), @@ -2740,7 +3049,7 @@ public: void EmitData(raw_ostream& Out, IdentifierInfo* II, IdentID ID, unsigned) { - MacroInfo *Macro = 0; + MacroDirective *Macro = 0; if (!isInterestingIdentifier(II, Macro)) { clang::io::Emit32(Out, ID << 1); return; @@ -2753,6 +3062,7 @@ public: Bits = 0; bool HadMacroDefinition = hadMacroDefinition(II, Macro); Bits = (Bits << 1) | unsigned(HadMacroDefinition); + Bits = (Bits << 1) | unsigned(IsModule); Bits = (Bits << 1) | unsigned(II->isExtensionToken()); Bits = (Bits << 1) | unsigned(II->isPoisoned()); Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); @@ -2760,13 +3070,19 @@ public: clang::io::Emit16(Out, Bits); if (HadMacroDefinition) { - // Write all of the macro IDs associated with this identifier. - for (MacroInfo *M = Macro; M; M = M->getPreviousDefinition()) { - if (MacroID ID = Writer.getMacroRef(M)) - clang::io::Emit32(Out, ID); + clang::io::Emit32(Out, Writer.getMacroDirectivesOffset(II)); + if (IsModule) { + // Write the IDs of macros coming from different submodules. + SubmoduleID ModID; + for (DefMacroDirective * + DefMD = getFirstPublicSubmoduleMacro(Macro, ModID); + DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) { + MacroID InfoID = Writer.getMacroID(DefMD->getInfo()); + assert(InfoID); + clang::io::Emit32(Out, InfoID); + } + clang::io::Emit32(Out, 0); } - - clang::io::Emit32(Out, 0); } // Emit the declaration IDs in reverse order, because the @@ -2820,7 +3136,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, assert(ID->first && "NULL identifier in identifier table"); if (!Chain || !ID->first->isFromAST() || ID->first->hasChangedSinceDeserialization()) - Generator.insert(const_cast<IdentifierInfo *>(ID->first), ID->second, + Generator.insert(const_cast<IdentifierInfo *>(ID->first), ID->second, Trait); } @@ -2857,6 +3173,11 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); +#ifndef NDEBUG + for (unsigned I = 0, N = IdentifierOffsets.size(); I != N; ++I) + assert(IdentifierOffsets[I] && "Missing identifier offset?"); +#endif + RecordData Record; Record.push_back(IDENTIFIER_OFFSET); Record.push_back(IdentifierOffsets.size()); @@ -2936,7 +3257,7 @@ public: clang::io::Emit16(Out, KeyLen); // 2 bytes for num of decls and 4 for each DeclID. - unsigned DataLen = 2 + 4 * (Lookup.second - Lookup.first); + unsigned DataLen = 2 + 4 * Lookup.size(); clang::io::Emit16(Out, DataLen); return std::make_pair(KeyLen, DataLen); @@ -2976,9 +3297,10 @@ public: void EmitData(raw_ostream& Out, key_type_ref, data_type Lookup, unsigned DataLen) { uint64_t Start = Out.tell(); (void)Start; - clang::io::Emit16(Out, Lookup.second - Lookup.first); - for (; Lookup.first != Lookup.second; ++Lookup.first) - clang::io::Emit32(Out, Writer.GetDeclRef(*Lookup.first)); + clang::io::Emit16(Out, Lookup.size()); + for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end(); + I != E; ++I) + clang::io::Emit32(Out, Writer.GetDeclRef(*I)); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } @@ -3002,8 +3324,6 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, // If not in C++, we perform name lookup for the translation unit via the // IdentifierInfo chains, don't bother to build a visible-declarations table. - // FIXME: In C++ we need the visible declarations in order to "see" the - // friend declarations, is there a way to do this without writing the table ? if (DC->isTranslationUnit() && !Context.getLangOpts().CPlusPlus) return 0; @@ -3022,12 +3342,12 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, // Create the on-disk hash table representation. DeclarationName ConversionName; - llvm::SmallVector<NamedDecl *, 4> ConversionDecls; + SmallVector<NamedDecl *, 4> ConversionDecls; for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); D != DEnd; ++D) { DeclarationName Name = D->first; DeclContext::lookup_result Result = D->second.getLookupResult(); - if (Result.first != Result.second) { + if (!Result.empty()) { if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { // Hash all conversion function names to the same name. The actual // type information in conversion function name is not used in the @@ -3036,7 +3356,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, // functions under a single key. if (!ConversionName) ConversionName = Name; - ConversionDecls.append(Result.first, Result.second); + ConversionDecls.append(Result.begin(), Result.end()); continue; } @@ -3095,7 +3415,7 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { DeclContext::lookup_result Result = D->second.getLookupResult(); // For any name that appears in this table, the results are complete, i.e. // they overwrite results from previous PCHs. Merging is always a mess. - if (Result.first != Result.second) + if (!Result.empty()) Generator.insert(Name, Result, Trait); } @@ -3156,20 +3476,32 @@ void ASTWriter::WriteRedeclarations() { LocalRedeclChains.push_back(0); // Placeholder for the size. // Collect the set of local redeclarations of this declaration. - for (Decl *Prev = MostRecent; Prev != First; + for (Decl *Prev = MostRecent; Prev != First; Prev = Prev->getPreviousDecl()) { if (!Prev->isFromASTFile()) { AddDeclRef(Prev, LocalRedeclChains); ++Size; } } + + if (!First->isFromASTFile() && Chain) { + Decl *FirstFromAST = MostRecent; + for (Decl *Prev = MostRecent; Prev; Prev = Prev->getPreviousDecl()) { + if (Prev->isFromASTFile()) + FirstFromAST = Prev; + } + + Chain->MergedDecls[FirstFromAST].push_back(getDeclID(First)); + } + LocalRedeclChains[Offset] = Size; // Reverse the set of local redeclarations, so that we store them in // order (since we found them in reverse order). std::reverse(LocalRedeclChains.end() - Size, LocalRedeclChains.end()); - // Add the mapping from the first ID to the set of local declarations. + // Add the mapping from the first ID from the AST to the set of local + // declarations. LocalRedeclarationsInfo Info = { getDeclID(First), Offset }; LocalRedeclsMap.push_back(Info); @@ -3204,7 +3536,7 @@ void ASTWriter::WriteRedeclarations() { } void ASTWriter::WriteObjCCategories() { - llvm::SmallVector<ObjCCategoriesInfo, 2> CategoriesMap; + SmallVector<ObjCCategoriesInfo, 2> CategoriesMap; RecordData Categories; for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) { @@ -3217,10 +3549,12 @@ void ASTWriter::WriteObjCCategories() { Categories.push_back(0); // Add the categories. - for (ObjCCategoryDecl *Cat = Class->getCategoryList(); - Cat; Cat = Cat->getNextClassCategory(), ++Size) { - assert(getDeclID(Cat) != 0 && "Bogus category"); - AddDeclRef(Cat, Categories); + for (ObjCInterfaceDecl::known_categories_iterator + Cat = Class->known_categories_begin(), + CatEnd = Class->known_categories_end(); + Cat != CatEnd; ++Cat, ++Size) { + assert(getDeclID(*Cat) != 0 && "Bogus category"); + AddDeclRef(*Cat, Categories); } // Update the size. @@ -3300,11 +3634,11 @@ void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { void ASTWriter::AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record) { Record.push_back(Version.getMajor()); - if (llvm::Optional<unsigned> Minor = Version.getMinor()) + if (Optional<unsigned> Minor = Version.getMinor()) Record.push_back(*Minor + 1); else Record.push_back(0); - if (llvm::Optional<unsigned> Subminor = Version.getSubminor()) + if (Optional<unsigned> Subminor = Version.getSubminor()) Record.push_back(*Subminor + 1); else Record.push_back(0); @@ -3405,6 +3739,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Module *WritingModule) { using namespace llvm; + bool isModule = WritingModule != 0; + // Make sure that the AST reader knows to finalize itself. if (Chain) Chain->finalizeForWriting(); @@ -3447,11 +3783,19 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // If there are any out-of-date identifiers, bring them up to date. if (ExternalPreprocessorSource *ExtSource = PP.getExternalSource()) { + // Find out-of-date identifiers. + SmallVector<IdentifierInfo *, 4> OutOfDate; for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), IDEnd = PP.getIdentifierTable().end(); - ID != IDEnd; ++ID) + ID != IDEnd; ++ID) { if (ID->second->isOutOfDate()) - ExtSource->updateOutOfDateIdentifier(*ID->second); + OutOfDate.push_back(ID->second); + } + + // Update the out-of-date identifiers. + for (unsigned I = 0, N = OutOfDate.size(); I != N; ++I) { + ExtSource->updateOutOfDateIdentifier(*OutOfDate[I]); + } } // Build a record containing all of the tentative definitions in this file, in @@ -3462,13 +3806,15 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // Build a record containing all of the file scoped decls in this file. RecordData UnusedFileScopedDecls; - AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls, - UnusedFileScopedDecls); + if (!isModule) + AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls, + UnusedFileScopedDecls); // Build a record containing all of the delegating constructors we still need // to resolve. RecordData DelegatingCtorDecls; - AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); + if (!isModule) + AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); // Write the set of weak, undeclared identifiers. We always write the // entire table, since later PCH files in a PCH chain are only interested in @@ -3485,18 +3831,18 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, } } - // Build a record containing all of the locally-scoped external + // Build a record containing all of the locally-scoped extern "C" // declarations in this header file. Generally, this record will be // empty. - RecordData LocallyScopedExternalDecls; + RecordData LocallyScopedExternCDecls; // FIXME: This is filling in the AST file in densemap order which is // nondeterminstic! for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator - TD = SemaRef.LocallyScopedExternalDecls.begin(), - TDEnd = SemaRef.LocallyScopedExternalDecls.end(); + TD = SemaRef.LocallyScopedExternCDecls.begin(), + TDEnd = SemaRef.LocallyScopedExternCDecls.end(); TD != TDEnd; ++TD) { if (!TD->second->isFromASTFile()) - AddDeclRef(TD->second, LocallyScopedExternalDecls); + AddDeclRef(TD->second, LocallyScopedExternCDecls); } // Build a record containing all of the ext_vector declarations. @@ -3542,7 +3888,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // Build a record containing all of the known namespaces. RecordData KnownNamespaces; - for (llvm::DenseMap<NamespaceDecl*, bool>::iterator + for (llvm::MapVector<NamespaceDecl*, bool>::iterator I = SemaRef.KnownNamespaces.begin(), IEnd = SemaRef.KnownNamespaces.end(); I != IEnd; ++I) { @@ -3550,6 +3896,17 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, AddDeclRef(I->first, KnownNamespaces); } + // Build a record of all used, undefined objects that require definitions. + RecordData UndefinedButUsed; + + SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined; + SemaRef.getUndefinedButUsed(Undefined); + for (SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> >::iterator + I = Undefined.begin(), E = Undefined.end(); I != E; ++I) { + AddDeclRef(I->first, UndefinedButUsed); + AddSourceLocation(I->second, UndefinedButUsed); + } + // Write the control block WriteControlBlock(PP, Context, isysroot, OutputFile); @@ -3557,6 +3914,12 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, RecordData Record; Stream.EnterSubblock(AST_BLOCK_ID, 5); + // This is so that older clang versions, before the introduction + // of the control block, can read and reject the newer PCH format. + Record.clear(); + Record.push_back(VERSION_MAJOR); + Stream.EmitRecord(METADATA_OLD_FORMAT, Record); + // Create a lexical update block containing all of the declarations in the // translation unit that do not come from other AST files. const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); @@ -3686,16 +4049,16 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record, Buffer.data(), Buffer.size()); } - WritePreprocessor(PP, WritingModule != 0); + WritePreprocessor(PP, isModule); WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot); WriteSelectors(SemaRef); WriteReferencedSelectorsPool(SemaRef); - WriteIdentifierTable(PP, SemaRef.IdResolver, WritingModule != 0); + WriteIdentifierTable(PP, SemaRef.IdResolver, isModule); WriteFPPragmaOptions(SemaRef.getFPOptions()); WriteOpenCLExtensions(SemaRef); WriteTypeDeclOffsets(); - WritePragmaDiagnosticMappings(Context.getDiagnostics()); + WritePragmaDiagnosticMappings(Context.getDiagnostics(), isModule); WriteCXXBaseSpecifiersOffsets(); @@ -3722,10 +4085,10 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS, WeakUndeclaredIdentifiers); - // Write the record containing locally-scoped external definitions. - if (!LocallyScopedExternalDecls.empty()) - Stream.EmitRecord(LOCALLY_SCOPED_EXTERNAL_DECLS, - LocallyScopedExternalDecls); + // Write the record containing locally-scoped extern "C" definitions. + if (!LocallyScopedExternCDecls.empty()) + Stream.EmitRecord(LOCALLY_SCOPED_EXTERN_C_DECLS, + LocallyScopedExternCDecls); // Write the record containing ext_vector type names. if (!ExtVectorDecls.empty()) @@ -3758,6 +4121,10 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, // Write the known namespaces. if (!KnownNamespaces.empty()) Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); + + // Write the undefined internal functions and variables, and inline functions. + if (!UndefinedButUsed.empty()) + Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); // Write the visible updates to DeclContexts. for (llvm::SmallPtrSet<const DeclContext *, 16>::iterator @@ -3788,11 +4155,10 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, } } - WriteMacroUpdates(); WriteDeclUpdatesBlocks(); WriteDeclReplacementsBlock(); - WriteMergedDecls(); WriteRedeclarations(); + WriteMergedDecls(); WriteObjCCategories(); // Some simple statistics @@ -3805,21 +4171,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Stream.ExitBlock(); } -void ASTWriter::WriteMacroUpdates() { - if (MacroUpdates.empty()) - return; - - RecordData Record; - for (MacroUpdatesMap::iterator I = MacroUpdates.begin(), - E = MacroUpdates.end(); - I != E; ++I) { - addMacroRef(I->first, Record); - AddSourceLocation(I->second.UndefLoc, Record); - Record.push_back(inferSubmoduleIDFromLocation(I->second.UndefLoc)); - } - Stream.EmitRecord(MACRO_UPDATES, Record); -} - /// \brief Go through the declaration update blocks and resolve declaration /// pointers into declaration IDs. void ASTWriter::ResolveDeclUpdatesBlocks() { @@ -3915,10 +4266,6 @@ void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Recor Record.push_back(getIdentifierRef(II)); } -void ASTWriter::addMacroRef(MacroInfo *MI, RecordDataImpl &Record) { - Record.push_back(getMacroRef(MI)); -} - IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { if (II == 0) return 0; @@ -3929,7 +4276,7 @@ IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { return ID; } -MacroID ASTWriter::getMacroRef(MacroInfo *MI) { +MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) { // Don't emit builtin macros like __LINE__ to the AST file unless they // have been redefined by the header (in which case they are not // isBuiltinMacro). @@ -3937,11 +4284,27 @@ MacroID ASTWriter::getMacroRef(MacroInfo *MI) { return 0; MacroID &ID = MacroIDs[MI]; - if (ID == 0) + if (ID == 0) { ID = NextMacroID++; + MacroInfoToEmitData Info = { Name, MI, ID }; + MacroInfosToEmit.push_back(Info); + } return ID; } +MacroID ASTWriter::getMacroID(MacroInfo *MI) { + if (MI == 0 || MI->isBuiltinMacro()) + return 0; + + assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!"); + return MacroIDs[MI]; +} + +uint64_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) { + assert(IdentMacroDirectivesOffsetMap[Name] && "not set!"); + return IdentMacroDirectivesOffsetMap[Name]; +} + void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) { Record.push_back(getSelectorRef(SelRef)); } @@ -3951,14 +4314,16 @@ SelectorID ASTWriter::getSelectorRef(Selector Sel) { return 0; } - SelectorID &SID = SelectorIDs[Sel]; + SelectorID SID = SelectorIDs[Sel]; if (SID == 0 && Chain) { // This might trigger a ReadSelector callback, which will set the ID for // this selector. Chain->LoadSelector(Sel); + SID = SelectorIDs[Sel]; } if (SID == 0) { SID = NextSelectorID++; + SelectorIDs[Sel] = SID; } return SID; } @@ -4431,7 +4796,7 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg, break; case TemplateArgument::TemplateExpansion: AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record); - if (llvm::Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions()) + if (Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions()) Record.push_back(*NumExpansions + 1); else Record.push_back(0); @@ -4474,9 +4839,9 @@ ASTWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs, void -ASTWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &Record) { +ASTWriter::AddUnresolvedSet(const ASTUnresolvedSet &Set, RecordDataImpl &Record) { Record.push_back(Set.size()); - for (UnresolvedSetImpl::const_iterator + for (ASTUnresolvedSet::const_iterator I = Set.begin(), E = Set.end(); I != E; ++I) { AddDeclRef(I.getDecl(), Record); Record.push_back(I.getAccess()); @@ -4568,11 +4933,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; Record.push_back(Data.IsLambda); Record.push_back(Data.UserDeclaredConstructor); - Record.push_back(Data.UserDeclaredCopyConstructor); - Record.push_back(Data.UserDeclaredMoveConstructor); - Record.push_back(Data.UserDeclaredCopyAssignment); - Record.push_back(Data.UserDeclaredMoveAssignment); - Record.push_back(Data.UserDeclaredDestructor); + Record.push_back(Data.UserDeclaredSpecialMembers); Record.push_back(Data.Aggregate); Record.push_back(Data.PlainOldData); Record.push_back(Data.Empty); @@ -4586,25 +4947,26 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.HasMutableFields); Record.push_back(Data.HasOnlyCMembers); Record.push_back(Data.HasInClassInitializer); - Record.push_back(Data.HasTrivialDefaultConstructor); + Record.push_back(Data.HasUninitializedReferenceMember); + Record.push_back(Data.NeedOverloadResolutionForMoveConstructor); + Record.push_back(Data.NeedOverloadResolutionForMoveAssignment); + Record.push_back(Data.NeedOverloadResolutionForDestructor); + Record.push_back(Data.DefaultedMoveConstructorIsDeleted); + Record.push_back(Data.DefaultedMoveAssignmentIsDeleted); + Record.push_back(Data.DefaultedDestructorIsDeleted); + Record.push_back(Data.HasTrivialSpecialMembers); + Record.push_back(Data.HasIrrelevantDestructor); Record.push_back(Data.HasConstexprNonCopyMoveConstructor); Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr); Record.push_back(Data.HasConstexprDefaultConstructor); - Record.push_back(Data.HasTrivialCopyConstructor); - Record.push_back(Data.HasTrivialMoveConstructor); - Record.push_back(Data.HasTrivialCopyAssignment); - Record.push_back(Data.HasTrivialMoveAssignment); - Record.push_back(Data.HasTrivialDestructor); - Record.push_back(Data.HasIrrelevantDestructor); Record.push_back(Data.HasNonLiteralTypeFieldsOrBases); Record.push_back(Data.ComputedVisibleConversions); Record.push_back(Data.UserProvidedDefaultConstructor); - Record.push_back(Data.DeclaredDefaultConstructor); - Record.push_back(Data.DeclaredCopyConstructor); - Record.push_back(Data.DeclaredMoveConstructor); - Record.push_back(Data.DeclaredCopyAssignment); - Record.push_back(Data.DeclaredMoveAssignment); - Record.push_back(Data.DeclaredDestructor); + Record.push_back(Data.DeclaredSpecialMembers); + Record.push_back(Data.ImplicitCopyConstructorHasConstParam); + Record.push_back(Data.ImplicitCopyAssignmentHasConstParam); + Record.push_back(Data.HasDeclaredCopyConstructorWithConstParam); + Record.push_back(Data.HasDeclaredCopyAssignmentWithConstParam); Record.push_back(Data.FailedImplicitMoveConstructor); Record.push_back(Data.FailedImplicitMoveAssignment); // IsLambda bit is already saved. @@ -4676,11 +5038,17 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { } void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { - IdentifierIDs[II] = ID; + // Always keep the highest ID. See \p TypeRead() for more information. + IdentID &StoredID = IdentifierIDs[II]; + if (ID > StoredID) + StoredID = ID; } void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) { - MacroIDs[MI] = ID; + // Always keep the highest ID. See \p TypeRead() for more information. + MacroID &StoredID = MacroIDs[MI]; + if (ID > StoredID) + StoredID = ID; } void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { @@ -4695,7 +5063,10 @@ void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { } void ASTWriter::SelectorRead(SelectorID ID, Selector S) { - SelectorIDs[S] = ID; + // Always keep the highest ID. See \p TypeRead() for more information. + SelectorID &StoredID = SelectorIDs[S]; + if (ID > StoredID) + StoredID = ID; } void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID, @@ -4709,10 +5080,6 @@ void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { SubmoduleIDs[Mod] = ID; } -void ASTWriter::UndefinedMacro(MacroInfo *MI) { - MacroUpdates[MI].UndefLoc = MI->getUndefLoc(); -} - void ASTWriter::CompletedTagDefinition(const TagDecl *D) { assert(D->isCompleteDefinition()); assert(!WritingAST && "Already writing the AST!"); @@ -4737,6 +5104,7 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { if (!(!D->isFromASTFile() && cast<Decl>(DC)->isFromASTFile())) return; // Not a source decl added to a DeclContext from PCH. + assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!"); AddUpdatedDeclContext(DC); UpdatingVisibleDecls.push_back(D); } |