@@ -1153,69 +1153,113 @@ static void conformToCxxDictionary(ClangImporter::Implementation &impl,
11531153 const clang::CXXRecordDecl *clangDecl) {
11541154 PrettyStackTraceDecl trace (" conforming to CxxDictionary" , decl);
11551155 ASTContext &ctx = decl->getASTContext ();
1156+ clang::ASTContext &clangCtx = impl.getClangASTContext ();
1157+ clang::Sema &clangSema = impl.getClangSema ();
11561158
1157- auto keyType = lookupDirectSingleWithoutExtensions<TypeAliasDecl>(
1158- decl, ctx.getIdentifier (" key_type" ));
1159- auto valueType = lookupDirectSingleWithoutExtensions<TypeAliasDecl>(
1160- decl, ctx.getIdentifier (" mapped_type" ));
1161- auto iterType = lookupDirectSingleWithoutExtensions<TypeAliasDecl>(
1162- decl, ctx.getIdentifier (" const_iterator" ));
1163- auto mutableIterType = lookupDirectSingleWithoutExtensions<TypeAliasDecl>(
1164- decl, ctx.getIdentifier (" iterator" ));
1165- auto sizeType = lookupDirectSingleWithoutExtensions<TypeAliasDecl>(
1166- decl, ctx.getIdentifier (" size_type" ));
1167- auto keyValuePairType = lookupDirectSingleWithoutExtensions<TypeAliasDecl>(
1168- decl, ctx.getIdentifier (" value_type" ));
1169- if (!keyType || !valueType || !iterType || !mutableIterType || !sizeType ||
1170- !keyValuePairType)
1171- return ;
1159+ #define lookup_type (member ) \
1160+ auto *member = lookupCxxTypeMember (clangSema, clangDecl, #member, \
1161+ /* mustBeComplete=*/ true ); \
1162+ if (!member) \
1163+ return
1164+
1165+ lookup_type (key_type);
1166+ lookup_type (mapped_type);
1167+ lookup_type (value_type);
1168+ lookup_type (size_type);
1169+ lookup_type (iterator);
1170+ lookup_type (const_iterator);
1171+ #undef lookup_type
1172+
1173+ const clang::CXXMethodDecl *insert = nullptr ;
1174+ {
1175+ // CxxDictionary requires the InsertionResult associated type, which is the
1176+ // return type of std::map (and co.)'s insert function. But there is no
1177+ // equivalent typedef in C++ we can use directly, so we need get it by
1178+ // converting the return type of this overload of the insert function:
1179+ //
1180+ // insert_return_type insert(const value_type &value);
1181+ //
1182+ // See also: extended monologuing in conformToCxxSet().
1183+ auto R = clang::LookupResult (
1184+ clangSema, &clangSema.PP .getIdentifierTable ().get (" insert" ),
1185+ clang::SourceLocation (), clang::Sema::LookupMemberName);
1186+ R.suppressDiagnostics ();
1187+ auto *Ctx = static_cast <const clang::DeclContext *>(clangDecl);
1188+ clangSema.LookupQualifiedName (R, const_cast <clang::DeclContext *>(Ctx));
1189+ switch (R.getResultKind ()) {
1190+ case clang::LookupResultKind::Found:
1191+ case clang::LookupResultKind::FoundOverloaded:
1192+ break ;
1193+ default :
1194+ return ;
1195+ }
11721196
1173- auto insert = getInsertFunc (decl, keyValuePairType);
1197+ for (auto *nd : R) {
1198+ if (auto *insertOverload = dyn_cast<clang::CXXMethodDecl>(nd)) {
1199+ if (insertOverload->param_size () != 1 )
1200+ continue ;
1201+ auto *paramTy = (*insertOverload->param_begin ())
1202+ ->getType ()
1203+ ->getAs <clang::ReferenceType>();
1204+ if (!paramTy)
1205+ continue ;
1206+ if (paramTy->getPointeeType ()->getCanonicalTypeUnqualified () !=
1207+ clangCtx.getTypeDeclType (value_type)->getCanonicalTypeUnqualified ())
1208+ continue ;
1209+ if (!paramTy->getPointeeType ().isConstQualified ())
1210+ continue ;
1211+ insert = insertOverload; // Found the insert() we're looking for
1212+ break ;
1213+ }
1214+ }
1215+ }
11741216 if (!insert)
11751217 return ;
11761218
1177- ProtocolDecl *cxxInputIteratorProto =
1178- ctx.getProtocol (KnownProtocolKind::UnsafeCxxInputIterator);
1179- ProtocolDecl *cxxMutableInputIteratorProto =
1180- ctx.getProtocol (KnownProtocolKind::UnsafeCxxMutableInputIterator);
1181- if (!cxxInputIteratorProto || !cxxMutableInputIteratorProto)
1182- return ;
1219+ #define importTypeAlias (to, from ) \
1220+ auto *to = dyn_cast_or_null<TypeAliasDecl>( \
1221+ impl.importDecl (from, impl.CurrentVersion )); \
1222+ if (!to) \
1223+ return
11831224
1184- auto rawIteratorTy = iterType->getUnderlyingType ();
1185- auto rawMutableIteratorTy = mutableIterType->getUnderlyingType ();
1225+ importTypeAlias (Size, size_type);
1226+ importTypeAlias (Key, key_type);
1227+ importTypeAlias (Value, mapped_type);
1228+ importTypeAlias (Element, value_type);
1229+ importTypeAlias (RawIterator, const_iterator);
1230+ importTypeAlias (RawMutableIterator, iterator);
1231+ #undef importTypeAlias
11861232
1187- // Check if RawIterator conforms to UnsafeCxxInputIterator.
1188- if (!checkConformance (rawIteratorTy, cxxInputIteratorProto))
1233+ auto *Insert =
1234+ dyn_cast_or_null<FuncDecl>(impl.importDecl (insert, impl.CurrentVersion ));
1235+ if (!Insert)
11891236 return ;
11901237
1191- // Check if RawMutableIterator conforms to UnsafeCxxMutableInputIterator.
1192- if (!checkConformance (rawMutableIteratorTy, cxxMutableInputIteratorProto))
1193- return ;
1238+ impl.addSynthesizedTypealias (decl, ctx.Id_Key , Key->getUnderlyingType ());
1239+ impl.addSynthesizedTypealias (decl, ctx.Id_Value , Value->getUnderlyingType ());
1240+ impl.addSynthesizedTypealias (decl, ctx.Id_Element ,
1241+ Element->getUnderlyingType ());
1242+ impl.addSynthesizedTypealias (decl, ctx.getIdentifier (" RawIterator" ),
1243+ RawIterator->getUnderlyingType ());
1244+ impl.addSynthesizedTypealias (decl, ctx.getIdentifier (" RawMutableIterator" ),
1245+ RawMutableIterator->getUnderlyingType ());
1246+ impl.addSynthesizedTypealias (decl, ctx.getIdentifier (" Size" ),
1247+ Size->getUnderlyingType ());
1248+ impl.addSynthesizedTypealias (decl, ctx.getIdentifier (" InsertionResult" ),
1249+ Insert->getResultInterfaceType ());
1250+ impl.addSynthesizedProtocolAttrs (decl, {KnownProtocolKind::CxxDictionary});
11941251
11951252 // Make the original subscript that returns a non-optional value unavailable.
11961253 // CxxDictionary adds another subscript that returns an optional value,
11971254 // similarly to Swift.Dictionary.
1255+ //
1256+ // NOTE: this relies on the SubscriptDecl member being imported eagerly.
11981257 for (auto member : decl->getCurrentMembersWithoutLoading ()) {
11991258 if (auto subscript = dyn_cast<SubscriptDecl>(member)) {
12001259 impl.markUnavailable (subscript,
12011260 " use subscript with optional return value" );
12021261 }
12031262 }
1204-
1205- impl.addSynthesizedTypealias (decl, ctx.Id_Key , keyType->getUnderlyingType ());
1206- impl.addSynthesizedTypealias (decl, ctx.Id_Value ,
1207- valueType->getUnderlyingType ());
1208- impl.addSynthesizedTypealias (decl, ctx.Id_Element ,
1209- keyValuePairType->getUnderlyingType ());
1210- impl.addSynthesizedTypealias (decl, ctx.getIdentifier (" RawIterator" ),
1211- rawIteratorTy);
1212- impl.addSynthesizedTypealias (decl, ctx.getIdentifier (" RawMutableIterator" ),
1213- rawMutableIteratorTy);
1214- impl.addSynthesizedTypealias (decl, ctx.getIdentifier (" Size" ),
1215- sizeType->getUnderlyingType ());
1216- impl.addSynthesizedTypealias (decl, ctx.getIdentifier (" InsertionResult" ),
1217- insert->getResultInterfaceType ());
1218- impl.addSynthesizedProtocolAttrs (decl, {KnownProtocolKind::CxxDictionary});
12191263}
12201264
12211265static void conformToCxxVector (ClangImporter::Implementation &impl,
0 commit comments