/// The ID numbers for identifiers are consecutive (in order of
/// discovery), starting at 1. An ID of zero refers to a NULL
/// IdentifierInfo.
- llvm::DenseMap<const IdentifierInfo *, serialization::IdentID> IdentifierIDs;
+ llvm::MapVector<const IdentifierInfo *, serialization::IdentID> IdentifierIDs;
/// \brief The first ID number we can use for our own macros.
serialization::MacroID FirstMacroID;
Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
getClangFullRepositoryVersion());
- // Signature
- Record.clear();
- Record.push_back(getSignature());
- Stream.EmitRecord(SIGNATURE, Record);
-
if (WritingModule) {
+ // For implicit modules we output a signature that we can use to ensure
+ // duplicate module builds don't collide in the cache as their output order
+ // is non-deterministic.
+ // FIXME: Remove this when output is deterministic.
+ if (Context.getLangOpts().ImplicitModules) {
+ Record.clear();
+ Record.push_back(getSignature());
+ Stream.EmitRecord(SIGNATURE, Record);
+ }
+
// Module name
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));
// Create the on-disk hash table representation. We only store offsets
// for identifiers that appear here for the first time.
IdentifierOffsets.resize(NextIdentID - FirstIdentID);
- for (llvm::DenseMap<const IdentifierInfo *, IdentID>::iterator
- ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
- ID != IDEnd; ++ID) {
- 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,
- Trait);
+ for (auto IdentIDPair : IdentifierIDs) {
+ IdentifierInfo *II = const_cast<IdentifierInfo *>(IdentIDPair.first);
+ IdentID ID = IdentIDPair.second;
+ assert(II && "NULL identifier in identifier table");
+ if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization())
+ Generator.insert(II, ID, Trait);
}
// Create the on-disk hash table in a buffer.
--- /dev/null
+// RUN: rm -rf %t
+//
+// RUN: %clang_cc1 -fmodules -x c++ -fmodules-cache-path=%t \
+// RUN: -fno-implicit-modules -fno-modules-implicit-maps \
+// RUN: -emit-module -fmodule-name=empty -o %t/base.pcm \
+// RUN: %s
+//
+// RUN: %clang_cc1 -fmodules -x c++ -fmodules-cache-path=%t \
+// RUN: -fno-implicit-modules -fno-modules-implicit-maps \
+// RUN: -emit-module -fmodule-name=empty -o %t/check.pcm \
+// RUN: %s
+//
+// RUN: diff %t/base.pcm %t/check.pcm
+
+module empty { header "Inputs/empty.h" export * }