diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -781,7 +781,7 @@ /// /// CodeGen has to emit VTables for these records, so they have to be eagerly /// deserialized. - SmallVector VTableUses; + SmallVector VTableUses; /// A snapshot of the pending instantiations in the chain. /// @@ -789,7 +789,7 @@ /// end of the TU. It consists of a pair of values for every pending /// instantiation where the first value is the ID of the decl and the second /// is the instantiation location. - SmallVector PendingInstantiations; + SmallVector PendingInstantiations; //@} @@ -807,11 +807,11 @@ /// Method selectors used in a @selector expression. Used for /// implementation of -Wselector. - SmallVector ReferencedSelectorsData; + SmallVector ReferencedSelectorsData; /// A snapshot of Sema's weak undeclared identifier tracking, for /// generating warnings. - SmallVector WeakUndeclaredIdentifiers; + SmallVector WeakUndeclaredIdentifiers; /// The IDs of type aliases for ext_vectors that exist in the chain. /// @@ -900,7 +900,7 @@ /// A list of undefined decls with internal linkage followed by the /// SourceLocation of a matching ODR-use. - SmallVector UndefinedButUsed; + SmallVector UndefinedButUsed; /// Delete expressions to analyze at the end of translation unit. SmallVector DelayedDeleteExprs; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3868,8 +3868,7 @@ return; } - SourceLocation::UIntType SLocOffset = - endian::readNext(Data); + uint64_t SLocOffset = endian::readNext(Data); uint32_t IdentifierIDOffset = endian::readNext(Data); uint32_t MacroIDOffset = @@ -3885,6 +3884,15 @@ uint32_t TypeIndexOffset = endian::readNext(Data); + // SourceLocations are serialized as uint64_t, irrespective of + // CLANG_64_BIT_SOURCE_LOCATIONS. So we have to bounds-check them + // when reading back in. + if (SLocOffset > std::numeric_limits::max()) { + Error("This version of clang cannot handle SourceLocations bigger than " + "32 bits"); + return; + } + auto mapOffset = [&](uint32_t Offset, uint32_t BaseOffset, RemapBuilder &Remap) { constexpr uint32_t None = std::numeric_limits::max(); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4636,21 +4636,29 @@ LE.write(Name.size()); Out.write(Name.data(), Name.size()); - // Note: if a base ID was uint max, it would not be possible to load - // another module after it or have more than one entity inside it. - uint32_t None = std::numeric_limits::max(); - auto writeBaseIDOrNone = [&](auto BaseID, bool ShouldWrite) { - assert(BaseID < std::numeric_limits::max() && "base id too high"); + using T = decltype(BaseID); + static_assert(std::is_same::value || + std::is_same::value, + "Invalid BaseID type"); + assert(BaseID < std::numeric_limits::max() && "base id too high"); if (ShouldWrite) - LE.write(BaseID); - else - LE.write(None); + LE.write(BaseID); + else { + // Note: if a base ID was uint max, it would not be possible to load + // another module after it or have more than one entity inside it. + constexpr T None = std::numeric_limits::max(); + LE.write(None); + } }; // These values should be unique within a chain, since they will be read // as keys into ContinuousRangeMaps. - writeBaseIDOrNone(M.SLocEntryBaseOffset, M.LocalNumSLocEntries); + + // SourceLocations are serialized as uint64_t, irrespective of + // CLANG_64_BIT_SOURCE_LOCATIONS + writeBaseIDOrNone(static_cast(M.SLocEntryBaseOffset), + M.LocalNumSLocEntries); writeBaseIDOrNone(M.BaseIdentifierID, M.LocalNumIdentifiers); writeBaseIDOrNone(M.BaseMacroID, M.LocalNumMacros); writeBaseIDOrNone(M.BasePreprocessedEntityID,