@@ -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) {
@@ -2099,18 +2103,21 @@ namespace {
20992103 if (decl->isInterface ())
21002104 return nullptr ;
21012105
2102- if (!decl->getDefinition ()) {
2106+ bool incompleteTypeAsReference = false ;
2107+ if (auto def = decl->getDefinition ()) {
2108+ // Continue with the definition of the type.
2109+ decl = def;
2110+ } else if (recordHasReferenceSemantics (decl)) {
2111+ // Incomplete types are okay if the resulting type has reference
2112+ // semantics.
2113+ incompleteTypeAsReference = true ;
2114+ } else {
21032115 Impl.addImportDiagnostic (
21042116 decl,
21052117 Diagnostic (diag::incomplete_record, Impl.SwiftContext .AllocateCopy (
21062118 decl->getNameAsString ())),
21072119 decl->getLocation ());
2108- }
21092120
2110- // FIXME: Figure out how to deal with incomplete types, since that
2111- // notion doesn't exist in Swift.
2112- decl = decl->getDefinition ();
2113- if (!decl) {
21142121 forwardDeclaration = true ;
21152122 return nullptr ;
21162123 }
@@ -2126,7 +2133,7 @@ namespace {
21262133 }
21272134
21282135 // Don't import nominal types that are over-aligned.
2129- if (Impl.isOverAligned (decl)) {
2136+ if (decl-> isCompleteDefinition () && Impl.isOverAligned (decl)) {
21302137 Impl.addImportDiagnostic (
21312138 decl, Diagnostic (
21322139 diag::record_over_aligned,
@@ -2137,6 +2144,9 @@ namespace {
21372144
21382145 auto isNonTrivialDueToAddressDiversifiedPtrAuth =
21392146 [](const clang::RecordDecl *decl) {
2147+ if (!decl->isCompleteDefinition ())
2148+ return true ;
2149+
21402150 for (auto *field : decl->fields ()) {
21412151 if (!field->getType ().isNonTrivialToPrimitiveCopy ()) {
21422152 continue ;
@@ -2192,7 +2202,8 @@ namespace {
21922202 *correctSwiftName);
21932203
21942204 auto dc =
2195- Impl.importDeclContextOf (decl, importedName.getEffectiveContext ());
2205+ Impl.importDeclContextOf (decl, importedName.getEffectiveContext (),
2206+ incompleteTypeAsReference);
21962207 if (!dc) {
21972208 Impl.addImportDiagnostic (
21982209 decl, Diagnostic (
@@ -2239,9 +2250,11 @@ namespace {
22392250 // solution would be to turn them into members and add conversion
22402251 // functions.
22412252 if (auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(decl)) {
2242- for (auto base : cxxRecordDecl->bases ()) {
2243- if (auto *baseRecordDecl = base.getType ()->getAsCXXRecordDecl ()) {
2244- Impl.importDecl (baseRecordDecl, getVersion ());
2253+ if (cxxRecordDecl->isCompleteDefinition ()) {
2254+ for (auto base : cxxRecordDecl->bases ()) {
2255+ if (auto *baseRecordDecl = base.getType ()->getAsCXXRecordDecl ()) {
2256+ Impl.importDecl (baseRecordDecl, getVersion ());
2257+ }
22452258 }
22462259 }
22472260 }
@@ -2449,15 +2462,18 @@ namespace {
24492462
24502463 const clang::CXXRecordDecl *cxxRecordDecl =
24512464 dyn_cast<clang::CXXRecordDecl>(decl);
2452- bool hasBaseClasses = cxxRecordDecl && !cxxRecordDecl->bases ().empty ();
2465+ bool hasBaseClasses = cxxRecordDecl &&
2466+ cxxRecordDecl->isCompleteDefinition () &&
2467+ !cxxRecordDecl->bases ().empty ();
24532468 if (hasBaseClasses) {
24542469 hasUnreferenceableStorage = true ;
24552470 hasMemberwiseInitializer = false ;
24562471 }
24572472
24582473 bool needsEmptyInitializer = true ;
24592474 if (cxxRecordDecl) {
2460- needsEmptyInitializer = !cxxRecordDecl->isAbstract () &&
2475+ needsEmptyInitializer = cxxRecordDecl->isCompleteDefinition () &&
2476+ !cxxRecordDecl->isAbstract () &&
24612477 (!cxxRecordDecl->hasDefaultConstructor () ||
24622478 cxxRecordDecl->ctors ().empty ());
24632479 }
@@ -2501,7 +2517,8 @@ namespace {
25012517 // only when the same is possible in C++. While we could check for that
25022518 // exactly, checking whether the C++ class is an aggregate
25032519 // (C++ [dcl.init.aggr]) has the same effect.
2504- bool isAggregate = !cxxRecordDecl || cxxRecordDecl->isAggregate ();
2520+ bool isAggregate = decl->isCompleteDefinition () &&
2521+ (!cxxRecordDecl || cxxRecordDecl->isAggregate ());
25052522 if ((hasReferenceableFields && hasMemberwiseInitializer && isAggregate) ||
25062523 forceMemberwiseInitializer) {
25072524 // The default zero initializer suppresses the implicit value
@@ -2905,7 +2922,13 @@ namespace {
29052922 if (!Impl.SwiftContext .LangOpts .EnableCXXInterop )
29062923 return VisitRecordDecl (decl);
29072924
2908- if (!decl->getDefinition ()) {
2925+ if (auto def = decl->getDefinition ()) {
2926+ // Continue with the definition of the type.
2927+ decl = def;
2928+ } else if (recordHasReferenceSemantics (decl)) {
2929+ // Incomplete types are okay if the resulting type has reference
2930+ // semantics.
2931+ } else {
29092932 Impl.addImportDiagnostic (
29102933 decl,
29112934 Diagnostic (diag::incomplete_record, Impl.SwiftContext .AllocateCopy (
@@ -2921,10 +2944,7 @@ namespace {
29212944 Impl.diagnose (HeaderLoc (attr.second ),
29222945 diag::private_fileid_attr_here);
29232946 }
2924- }
29252947
2926- decl = decl->getDefinition ();
2927- if (!decl) {
29282948 forwardDeclaration = true ;
29292949 return nullptr ;
29302950 }
@@ -3141,12 +3161,14 @@ namespace {
31413161 void
31423162 addExplicitProtocolConformances (NominalTypeDecl *decl,
31433163 const clang::CXXRecordDecl *clangDecl) {
3144- // Propagate conforms_to attribute from public base classes.
3145- for (auto base : clangDecl->bases ()) {
3146- if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
3147- continue ;
3148- if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
3149- addExplicitProtocolConformances (decl, baseClangDecl);
3164+ if (clangDecl->isCompleteDefinition ()) {
3165+ // Propagate conforms_to attribute from public base classes.
3166+ for (auto base : clangDecl->bases ()) {
3167+ if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
3168+ continue ;
3169+ if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
3170+ addExplicitProtocolConformances (decl, baseClangDecl);
3171+ }
31503172 }
31513173
31523174 if (!clangDecl->hasAttrs ())
@@ -10261,7 +10283,8 @@ ClangImporter::Implementation::importDeclForDeclContext(
1026110283DeclContext *
1026210284ClangImporter::Implementation::importDeclContextOf (
1026310285 const clang::Decl *decl,
10264- EffectiveClangContext context)
10286+ EffectiveClangContext context,
10287+ bool allowForwardDeclaration)
1026510288{
1026610289 DeclContext *importedDC = nullptr ;
1026710290 switch (context.getKind ()) {
@@ -10290,7 +10313,7 @@ ClangImporter::Implementation::importDeclContextOf(
1029010313 }
1029110314
1029210315 if (dc->isTranslationUnit ()) {
10293- if (auto *module = getClangModuleForDecl (decl))
10316+ if (auto *module = getClangModuleForDecl (decl, allowForwardDeclaration ))
1029410317 return module ;
1029510318 else
1029610319 return nullptr ;
@@ -10554,7 +10577,9 @@ void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
1055410577 }
1055510578
1055610579 // If this is a C++ record, look through the base classes too.
10557- if (auto cxxRecord = dyn_cast<clang::CXXRecordDecl>(clangRecord)) {
10580+ const clang::CXXRecordDecl *cxxRecord;
10581+ if ((cxxRecord = dyn_cast<clang::CXXRecordDecl>(clangRecord)) &&
10582+ cxxRecord->isCompleteDefinition ()) {
1055810583 for (auto base : cxxRecord->bases ()) {
1055910584 if (skipIfNonPublic && base.getAccessSpecifier () != clang::AS_public)
1056010585 continue ;
0 commit comments