@@ -1950,7 +1950,8 @@ namespace {
19501950 bool recordHasReferenceSemantics (const clang::RecordDecl *decl) {
19511951 if (auto cxxRecord = dyn_cast<clang::CXXRecordDecl>(decl)) {
19521952 auto semanticsKind = evaluateOrDefault (
1953- Impl.SwiftContext .evaluator , CxxRecordSemantics ({cxxRecord}), {});
1953+ Impl.SwiftContext .evaluator ,
1954+ CxxRecordSemantics ({cxxRecord, Impl.SwiftContext }), {});
19541955 return semanticsKind == CxxRecordSemanticsKind::Reference;
19551956 }
19561957
@@ -1982,6 +1983,13 @@ namespace {
19821983 if (decl->isInterface ())
19831984 return nullptr ;
19841985
1986+ if (!decl->getDefinition ()) {
1987+ Impl.addImportDiagnostic (
1988+ decl,
1989+ Diagnostic (diag::incomplete_record,
1990+ Impl.SwiftContext .AllocateCopy (decl->getNameAsString ())));
1991+ }
1992+
19851993 // FIXME: Figure out how to deal with incomplete types, since that
19861994 // notion doesn't exist in Swift.
19871995 decl = decl->getDefinition ();
@@ -1991,12 +1999,22 @@ namespace {
19911999 }
19922000
19932001 // TODO(SR-13809): fix this once we support dependent types.
1994- if (decl->getTypeForDecl ()->isDependentType ())
2002+ if (decl->getTypeForDecl ()->isDependentType ()) {
2003+ Impl.addImportDiagnostic (
2004+ decl,
2005+ Diagnostic (diag::record_is_dependent,
2006+ Impl.SwiftContext .AllocateCopy (decl->getNameAsString ())));
19952007 return nullptr ;
2008+ }
19962009
19972010 // Don't import nominal types that are over-aligned.
1998- if (Impl.isOverAligned (decl))
2011+ if (Impl.isOverAligned (decl)) {
2012+ Impl.addImportDiagnostic (
2013+ decl,
2014+ Diagnostic (diag::record_over_aligned,
2015+ Impl.SwiftContext .AllocateCopy (decl->getNameAsString ())));
19992016 return nullptr ;
2017+ }
20002018
20012019 // FIXME: We should actually support strong ARC references and similar in
20022020 // C structs. That'll require some SIL and IRGen work, though.
@@ -2012,6 +2030,10 @@ namespace {
20122030 // imported function and the developer would be able to use it without
20132031 // referencing the name, which would sidestep our availability
20142032 // diagnostics.
2033+ Impl.addImportDiagnostic (
2034+ decl,
2035+ Diagnostic (diag::record_non_trivial_copy_destroy,
2036+ Impl.SwiftContext .AllocateCopy (decl->getNameAsString ())));
20152037 return nullptr ;
20162038 }
20172039
@@ -2030,8 +2052,13 @@ namespace {
20302052
20312053 auto dc =
20322054 Impl.importDeclContextOf (decl, importedName.getEffectiveContext ());
2033- if (!dc)
2055+ if (!dc) {
2056+ Impl.addImportDiagnostic (
2057+ decl,
2058+ Diagnostic (diag::record_parent_unimportable,
2059+ Impl.SwiftContext .AllocateCopy (decl->getNameAsString ())));
20342060 return nullptr ;
2061+ }
20352062
20362063 // Create the struct declaration and record it.
20372064 auto name = importedName.getDeclName ().getBaseIdentifier ();
@@ -2403,6 +2430,11 @@ namespace {
24032430 if (!Impl.SwiftContext .LangOpts .EnableCXXInterop )
24042431 return VisitRecordDecl (decl);
24052432
2433+ if (!decl->getDefinition ()) {
2434+ Impl.addImportDiagnostic (decl, Diagnostic (diag::incomplete_record,
2435+ Impl.SwiftContext .AllocateCopy (decl->getNameAsString ())));
2436+ }
2437+
24062438 decl = decl->getDefinition ();
24072439 if (!decl) {
24082440 forwardDeclaration = true ;
@@ -2453,10 +2485,24 @@ namespace {
24532485
24542486 // It is import that we bail on an unimportable record *before* we import
24552487 // any of its members or cache the decl.
2456- auto semanticsKind = evaluateOrDefault (Impl.SwiftContext .evaluator ,
2457- CxxRecordSemantics ({decl}), {});
2458- if (semanticsKind == CxxRecordSemanticsKind::UnsafeLifetimeOperation)
2488+ auto semanticsKind = evaluateOrDefault (
2489+ Impl.SwiftContext .evaluator ,
2490+ CxxRecordSemantics ({decl, Impl.SwiftContext }), {});
2491+ if (semanticsKind == CxxRecordSemanticsKind::MissingLifetimeOperation) {
2492+ Impl.addImportDiagnostic (
2493+ decl,
2494+ Diagnostic (diag::record_not_automatically_importable,
2495+ Impl.SwiftContext .AllocateCopy (decl->getNameAsString ()),
2496+ " does not have a copy constructor or destructor" ));
2497+ return nullptr ;
2498+ } else if (semanticsKind == CxxRecordSemanticsKind::UnsafeLifetimeOperation) {
2499+ Impl.addImportDiagnostic (
2500+ decl,
2501+ Diagnostic (diag::record_not_automatically_importable,
2502+ Impl.SwiftContext .AllocateCopy (decl->getNameAsString ()),
2503+ " has custom, potentially unsafe copy constructor or destructor" ));
24592504 return nullptr ;
2505+ }
24602506
24612507 return VisitRecordDecl (decl);
24622508 }
@@ -2634,8 +2680,10 @@ namespace {
26342680 if (auto parent = dyn_cast<clang::CXXRecordDecl>(
26352681 decl->getAnonField ()->getParent ())) {
26362682 auto semanticsKind = evaluateOrDefault (
2637- Impl.SwiftContext .evaluator , CxxRecordSemantics ({parent}), {});
2638- if (semanticsKind == CxxRecordSemanticsKind::UnsafeLifetimeOperation)
2683+ Impl.SwiftContext .evaluator ,
2684+ CxxRecordSemantics ({parent, Impl.SwiftContext }), {});
2685+ if (semanticsKind == CxxRecordSemanticsKind::MissingLifetimeOperation ||
2686+ semanticsKind == CxxRecordSemanticsKind::UnsafeLifetimeOperation)
26392687 return nullptr ;
26402688 }
26412689
@@ -2712,19 +2760,33 @@ namespace {
27122760
27132761 bool foreignReferenceTypePassedByRef (const clang::FunctionDecl *decl) {
27142762 bool anyParamPassesByVal =
2715- llvm::any_of (decl->parameters (), [this ](auto *param) {
2763+ llvm::any_of (decl->parameters (), [this , decl ](auto *param) {
27162764 if (auto recordType = dyn_cast<clang::RecordType>(
2717- param->getType ().getCanonicalType ()))
2718- return recordHasReferenceSemantics (recordType->getDecl ());
2765+ param->getType ().getCanonicalType ())) {
2766+ if (recordHasReferenceSemantics (recordType->getDecl ())) {
2767+ Impl.addImportDiagnostic (
2768+ decl,
2769+ Diagnostic (diag::reference_passed_by_value,
2770+ Impl.SwiftContext .AllocateCopy (recordType->getDecl ()->getNameAsString ()),
2771+ " a parameter" ));
2772+ return true ;
2773+ }
2774+ }
27192775 return false ;
27202776 });
27212777
27222778 if (anyParamPassesByVal)
27232779 return true ;
27242780
27252781 if (auto recordType = dyn_cast<clang::RecordType>(
2726- decl->getReturnType ().getCanonicalType ()))
2782+ decl->getReturnType ().getCanonicalType ())) {
2783+ Impl.addImportDiagnostic (
2784+ decl,
2785+ Diagnostic (diag::reference_passed_by_value,
2786+ Impl.SwiftContext .AllocateCopy (recordType->getDecl ()->getNameAsString ()),
2787+ " the return" ));
27272788 return recordHasReferenceSemantics (recordType->getDecl ());
2789+ }
27282790
27292791 return false ;
27302792 }
0 commit comments