@@ -58,6 +58,17 @@ static void emitObjCConditional(raw_ostream &out,
5858 out << " #endif\n " ;
5959}
6060
61+ static void emitExternC (raw_ostream &out,
62+ llvm::function_ref<void ()> cCase) {
63+ emitCxxConditional (out, [&] {
64+ out << " extern \" C\" {\n " ;
65+ });
66+ cCase ();
67+ emitCxxConditional (out, [&] {
68+ out << " } // extern \" C\"\n " ;
69+ });
70+ }
71+
6172static void writePtrauthPrologue (raw_ostream &os, ASTContext &ctx) {
6273 emitCxxConditional (os, [&]() {
6374 ClangSyntaxPrinter (ctx, os).printIgnoredDiagnosticBlock (
@@ -207,6 +218,21 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
207218
208219 static_assert (SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4 ,
209220 " need to add SIMD typedefs here if max elements is increased" );
221+
222+ if (ctx.LangOpts .hasFeature (Feature::CDecl)) {
223+ // For C compilers which don’t support nullability attributes, ignore them;
224+ // for ones which do, suppress warnings about them being an extension.
225+ out << " #if !__has_feature(nullability)\n "
226+ " # define _Nonnull\n "
227+ " # define _Nullable\n "
228+ " # define _Null_unspecified\n "
229+ " #elif !defined(__OBJC__)\n "
230+ " # pragma clang diagnostic ignored \" -Wnullability-extension\"\n "
231+ " #endif\n "
232+ " #if !__has_feature(nullability_nullable_result)\n "
233+ " # define _Nullable_result _Nullable\n "
234+ " #endif\n " ;
235+ }
210236}
211237
212238static int compareImportModulesByName (const ImportModuleTy *left,
@@ -577,12 +603,21 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
577603 llvm::PrettyStackTraceString trace (" While generating Clang header" );
578604
579605 SwiftToClangInteropContext interopContext (*M, irGenOpts);
606+ writePrologue (os, M->getASTContext (), computeMacroGuard (M));
607+
608+ // C content (@cdecl)
609+ if (M->getASTContext ().LangOpts .hasFeature (Feature::CDecl)) {
610+ SmallPtrSet<ImportModuleTy, 8 > imports;
611+ emitExternC (os, [&] {
612+ printModuleContentsAsC (os, imports, *M, interopContext);
613+ });
614+ }
580615
616+ // Objective-C content
581617 SmallPtrSet<ImportModuleTy, 8 > imports;
582618 std::string objcModuleContentsBuf;
583619 llvm::raw_string_ostream objcModuleContents{objcModuleContentsBuf};
584620 printModuleContentsAsObjC (objcModuleContents, imports, *M, interopContext);
585- writePrologue (os, M->getASTContext (), computeMacroGuard (M));
586621 emitObjCConditional (os, [&] {
587622 llvm::StringMap<StringRef> exposedModuleHeaderNames;
588623 writeImports (os, imports, *M, bridgingHeader, frontendOpts,
@@ -591,6 +626,8 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
591626 writePostImportPrologue (os, *M);
592627 emitObjCConditional (os, [&] { os << " \n " << objcModuleContents.str (); });
593628 writeObjCEpilogue (os);
629+
630+ // C++ content
594631 emitCxxConditional (os, [&] {
595632 // FIXME: Expose Swift with @expose by default.
596633 bool enableCxx = frontendOpts.ClangHeaderExposedDecls .has_value () ||
0 commit comments