@@ -846,6 +846,10 @@ using MirroredMethodEntry =
846846 std::tuple<const clang::ObjCMethodDecl*, ProtocolDecl*, bool /* isAsync*/ >;
847847
848848static bool areRecordFieldsComplete (const clang::CXXRecordDecl *decl) {
849+ // If the type is incomplete, then the fields are not complete.
850+ if (!decl->isCompleteDefinition ())
851+ return false ;
852+
849853 for (const auto *f : decl->fields ()) {
850854 auto *fieldRecord = f->getType ()->getAsCXXRecordDecl ();
851855 if (fieldRecord) {
@@ -2101,18 +2105,21 @@ namespace {
21012105 if (decl->isInterface ())
21022106 return nullptr ;
21032107
2104- if (!decl->getDefinition ()) {
2108+ bool incompleteTypeAsReference = false ;
2109+ if (auto def = decl->getDefinition ()) {
2110+ // Continue with the definition of the type.
2111+ decl = def;
2112+ } else if (recordHasReferenceSemantics (decl)) {
2113+ // Incomplete types are okay if the resulting type has reference
2114+ // semantics.
2115+ incompleteTypeAsReference = true ;
2116+ } else {
21052117 Impl.addImportDiagnostic (
21062118 decl,
21072119 Diagnostic (diag::incomplete_record, Impl.SwiftContext .AllocateCopy (
21082120 decl->getNameAsString ())),
21092121 decl->getLocation ());
2110- }
21112122
2112- // FIXME: Figure out how to deal with incomplete types, since that
2113- // notion doesn't exist in Swift.
2114- decl = decl->getDefinition ();
2115- if (!decl) {
21162123 forwardDeclaration = true ;
21172124 return nullptr ;
21182125 }
@@ -2128,7 +2135,7 @@ namespace {
21282135 }
21292136
21302137 // Don't import nominal types that are over-aligned.
2131- if (Impl.isOverAligned (decl)) {
2138+ if (decl-> isCompleteDefinition () && Impl.isOverAligned (decl)) {
21322139 Impl.addImportDiagnostic (
21332140 decl, Diagnostic (
21342141 diag::record_over_aligned,
@@ -2139,6 +2146,9 @@ namespace {
21392146
21402147 auto isNonTrivialDueToAddressDiversifiedPtrAuth =
21412148 [](const clang::RecordDecl *decl) {
2149+ if (!decl->isCompleteDefinition ())
2150+ return true ;
2151+
21422152 for (auto *field : decl->fields ()) {
21432153 if (!field->getType ().isNonTrivialToPrimitiveCopy ()) {
21442154 continue ;
@@ -2194,7 +2204,8 @@ namespace {
21942204 *correctSwiftName);
21952205
21962206 auto dc =
2197- Impl.importDeclContextOf (decl, importedName.getEffectiveContext ());
2207+ Impl.importDeclContextOf (decl, importedName.getEffectiveContext (),
2208+ incompleteTypeAsReference);
21982209 if (!dc) {
21992210 Impl.addImportDiagnostic (
22002211 decl, Diagnostic (
@@ -2241,9 +2252,11 @@ namespace {
22412252 // solution would be to turn them into members and add conversion
22422253 // functions.
22432254 if (auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(decl)) {
2244- for (auto base : cxxRecordDecl->bases ()) {
2245- if (auto *baseRecordDecl = base.getType ()->getAsCXXRecordDecl ()) {
2246- Impl.importDecl (baseRecordDecl, getVersion ());
2255+ if (cxxRecordDecl->isCompleteDefinition ()) {
2256+ for (auto base : cxxRecordDecl->bases ()) {
2257+ if (auto *baseRecordDecl = base.getType ()->getAsCXXRecordDecl ()) {
2258+ Impl.importDecl (baseRecordDecl, getVersion ());
2259+ }
22472260 }
22482261 }
22492262 }
@@ -2451,15 +2464,18 @@ namespace {
24512464
24522465 const clang::CXXRecordDecl *cxxRecordDecl =
24532466 dyn_cast<clang::CXXRecordDecl>(decl);
2454- bool hasBaseClasses = cxxRecordDecl && !cxxRecordDecl->bases ().empty ();
2467+ bool hasBaseClasses = cxxRecordDecl &&
2468+ cxxRecordDecl->isCompleteDefinition () &&
2469+ !cxxRecordDecl->bases ().empty ();
24552470 if (hasBaseClasses) {
24562471 hasUnreferenceableStorage = true ;
24572472 hasMemberwiseInitializer = false ;
24582473 }
24592474
24602475 bool needsEmptyInitializer = true ;
24612476 if (cxxRecordDecl) {
2462- needsEmptyInitializer = !cxxRecordDecl->isAbstract () &&
2477+ needsEmptyInitializer = cxxRecordDecl->isCompleteDefinition () &&
2478+ !cxxRecordDecl->isAbstract () &&
24632479 (!cxxRecordDecl->hasDefaultConstructor () ||
24642480 cxxRecordDecl->ctors ().empty ());
24652481 }
@@ -2503,7 +2519,8 @@ namespace {
25032519 // only when the same is possible in C++. While we could check for that
25042520 // exactly, checking whether the C++ class is an aggregate
25052521 // (C++ [dcl.init.aggr]) has the same effect.
2506- bool isAggregate = !cxxRecordDecl || cxxRecordDecl->isAggregate ();
2522+ bool isAggregate = decl->isCompleteDefinition () &&
2523+ (!cxxRecordDecl || cxxRecordDecl->isAggregate ());
25072524 if ((hasReferenceableFields && hasMemberwiseInitializer && isAggregate) ||
25082525 forceMemberwiseInitializer) {
25092526 // The default zero initializer suppresses the implicit value
@@ -2907,7 +2924,13 @@ namespace {
29072924 if (!Impl.SwiftContext .LangOpts .EnableCXXInterop )
29082925 return VisitRecordDecl (decl);
29092926
2910- if (!decl->getDefinition ()) {
2927+ if (auto def = decl->getDefinition ()) {
2928+ // Continue with the definition of the type.
2929+ decl = def;
2930+ } else if (recordHasReferenceSemantics (decl)) {
2931+ // Incomplete types are okay if the resulting type has reference
2932+ // semantics.
2933+ } else {
29112934 Impl.addImportDiagnostic (
29122935 decl,
29132936 Diagnostic (diag::incomplete_record, Impl.SwiftContext .AllocateCopy (
@@ -2923,10 +2946,7 @@ namespace {
29232946 Impl.diagnose (HeaderLoc (attr.second ),
29242947 diag::private_fileid_attr_here);
29252948 }
2926- }
29272949
2928- decl = decl->getDefinition ();
2929- if (!decl) {
29302950 forwardDeclaration = true ;
29312951 return nullptr ;
29322952 }
@@ -3143,12 +3163,14 @@ namespace {
31433163 void
31443164 addExplicitProtocolConformances (NominalTypeDecl *decl,
31453165 const clang::CXXRecordDecl *clangDecl) {
3146- // Propagate conforms_to attribute from public base classes.
3147- for (auto base : clangDecl->bases ()) {
3148- if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
3149- continue ;
3150- if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
3151- addExplicitProtocolConformances (decl, baseClangDecl);
3166+ if (clangDecl->isCompleteDefinition ()) {
3167+ // Propagate conforms_to attribute from public base classes.
3168+ for (auto base : clangDecl->bases ()) {
3169+ if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
3170+ continue ;
3171+ if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
3172+ addExplicitProtocolConformances (decl, baseClangDecl);
3173+ }
31523174 }
31533175
31543176 if (!clangDecl->hasAttrs ())
@@ -10236,7 +10258,8 @@ ClangImporter::Implementation::importDeclForDeclContext(
1023610258DeclContext *
1023710259ClangImporter::Implementation::importDeclContextOf (
1023810260 const clang::Decl *decl,
10239- EffectiveClangContext context)
10261+ EffectiveClangContext context,
10262+ bool allowForwardDeclaration)
1024010263{
1024110264 DeclContext *importedDC = nullptr ;
1024210265 switch (context.getKind ()) {
@@ -10265,7 +10288,7 @@ ClangImporter::Implementation::importDeclContextOf(
1026510288 }
1026610289
1026710290 if (dc->isTranslationUnit ()) {
10268- if (auto *module = getClangModuleForDecl (decl))
10291+ if (auto *module = getClangModuleForDecl (decl, allowForwardDeclaration ))
1026910292 return module ;
1027010293 else
1027110294 return nullptr ;
@@ -10529,7 +10552,9 @@ void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
1052910552 }
1053010553
1053110554 // If this is a C++ record, look through the base classes too.
10532- if (auto cxxRecord = dyn_cast<clang::CXXRecordDecl>(clangRecord)) {
10555+ const clang::CXXRecordDecl *cxxRecord;
10556+ if ((cxxRecord = dyn_cast<clang::CXXRecordDecl>(clangRecord)) &&
10557+ cxxRecord->isCompleteDefinition ()) {
1053310558 for (auto base : cxxRecord->bases ()) {
1053410559 if (skipIfNonPublic && base.getAccessSpecifier () != clang::AS_public)
1053510560 continue ;
0 commit comments