mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[cxx-interop] Fix lookup of class template instantiations
To fix a crash during deserialization, we need to store the mangled names of C++ class template instantiations in the lookup table. For example, `std::string` will be serialized as `__CxxTemplateInstNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE`, and when another instance of the Swift compiler will later attempt to deserialize a decl referencing this instantiation, it will query the `SwiftLookupTable` for a decl with this name. If this instantiation is not referenced from the module that is currently being compiled, Swift will not instantiate `std::string` during typechecking, and the mangled name will be missing from `SwiftLookupTable`, leading to a deserialization failure. This happens when compiling with cross-module optimization enabled, and the current module does not reference `std::string`, but one of its dependencies does.
This commit is contained in:
@@ -1922,6 +1922,30 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table,
|
||||
}
|
||||
}
|
||||
|
||||
// Class template instantiations are imported lazily, however, the lookup
|
||||
// table must include their mangled name (__CxxTemplateInst...) to make it
|
||||
// possible to find these decls during deserialization. For any C++ typedef
|
||||
// that defines a name for a class template instantiation (e.g. std::string),
|
||||
// import the mangled name of this instantiation, and add it to the table.
|
||||
if (auto typedefNameDecl = dyn_cast<clang::TypedefNameDecl>(named)) {
|
||||
auto underlyingDecl = typedefNameDecl->getUnderlyingType()->getAsTagDecl();
|
||||
|
||||
if (auto specializationDecl =
|
||||
dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(
|
||||
underlyingDecl)) {
|
||||
auto name = nameImporter.importName(specializationDecl, currentVersion);
|
||||
|
||||
// Avoid adding duplicate entries into the table.
|
||||
auto existingEntries =
|
||||
table.lookup(DeclBaseName(name.getDeclName().getBaseName()),
|
||||
name.getEffectiveContext());
|
||||
if (existingEntries.empty()) {
|
||||
table.addEntry(name.getDeclName(), specializationDecl,
|
||||
name.getEffectiveContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Walk the members of any context that can have nested members.
|
||||
if (isa<clang::TagDecl>(named) || isa<clang::ObjCInterfaceDecl>(named) ||
|
||||
isa<clang::ObjCProtocolDecl>(named) ||
|
||||
|
||||
Reference in New Issue
Block a user