Skip to content

Commit 54b466f

Browse files
committed
[interop] emit a parsable C++ header for a module that includes namespace declaration for the module interface
1 parent e106551 commit 54b466f

File tree

6 files changed

+141
-62
lines changed

6 files changed

+141
-62
lines changed

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,3 +619,15 @@ swift::printModuleContentsAsObjC(raw_ostream &os,
619619
: AccessLevel::Internal;
620620
ModuleWriter(os, imports, M, requiredAccess).write();
621621
}
622+
623+
void swift::printModuleContentsAsCxx(
624+
raw_ostream &os, llvm::SmallPtrSetImpl<ImportModuleTy> &imports,
625+
ModuleDecl &M) {
626+
os << "namespace ";
627+
M.ValueDecl::getName().print(os);
628+
os << " {\n\n";
629+
// TODO (Alex): Emit module contents.
630+
os << "\n} // namespace ";
631+
M.ValueDecl::getName().print(os);
632+
os << "\n\n";
633+
}

lib/PrintAsClang/ModuleContentsWriter.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- ModuleContentsWriter.h - Walk a module to print ObjC ---*- C++ -*-===//
1+
//===--- ModuleContentsWriter.h - Walk module to print ObjC/C++ -*- C++ -*-===//
22
//
33
// This source file is part of the Swift.org open source project
44
//
@@ -33,6 +33,12 @@ void printModuleContentsAsObjC(raw_ostream &os,
3333
llvm::SmallPtrSetImpl<ImportModuleTy> &imports,
3434
ModuleDecl &M);
3535

36+
/// Prints the declarations of \p M to \p os in C++ language mode and collects
37+
/// imports in \p imports along the way.
38+
void printModuleContentsAsCxx(raw_ostream &os,
39+
llvm::SmallPtrSetImpl<ImportModuleTy> &imports,
40+
ModuleDecl &M);
41+
3642
} // end namespace swift
3743

3844
#endif

lib/PrintAsClang/OutputLanguageMode.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===--- OutputLanguageMode.h - Output mode for clang printer ---*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_PRINTASCLANG_OUTPUTLANGUAGEMODE_H
14+
#define SWIFT_PRINTASCLANG_OUTPUTLANGUAGEMODE_H
15+
16+
namespace swift {
17+
18+
enum class OutputLanguageMode { ObjC, Cxx };
19+
20+
} // end namespace swift
21+
22+
#endif

lib/PrintAsClang/PrintAsClang.cpp

Lines changed: 78 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "swift/PrintAsClang/PrintAsClang.h"
1414

1515
#include "ModuleContentsWriter.h"
16+
#include "OutputLanguageMode.h"
1617

1718
#include "swift/AST/ASTContext.h"
1819
#include "swift/AST/Module.h"
@@ -27,12 +28,14 @@
2728
using namespace swift;
2829

2930
static void writePrologue(raw_ostream &out, ASTContext &ctx,
30-
StringRef macroGuard) {
31-
out << "// Generated by " << version::getSwiftFullVersion(
32-
ctx.LangOpts.EffectiveLanguageVersion) << "\n"
33-
// Guard against recursive definition.
34-
<< "#ifndef " << macroGuard << "\n"
35-
<< "#define " << macroGuard << "\n"
31+
StringRef macroGuard, OutputLanguageMode Lang) {
32+
out << "// Generated by "
33+
<< version::getSwiftFullVersion(ctx.LangOpts.EffectiveLanguageVersion)
34+
<< "\n"
35+
// Guard against recursive definition.
36+
<< "#ifndef " << macroGuard << "\n"
37+
<< "#define " << macroGuard
38+
<< "\n"
3639
"#pragma clang diagnostic push\n"
3740
"#pragma clang diagnostic ignored \"-Wgcc-compat\"\n"
3841
"\n"
@@ -53,12 +56,18 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
5356
"# include <swift/objc-prologue.h>\n"
5457
"#endif\n"
5558
"\n"
56-
"#pragma clang diagnostic ignored \"-Wauto-import\"\n"
57-
"#include <Foundation/Foundation.h>\n"
58-
"#include <stdint.h>\n"
59-
"#include <stddef.h>\n"
60-
"#include <stdbool.h>\n"
61-
"\n"
59+
"#pragma clang diagnostic ignored \"-Wauto-import\"\n";
60+
if (Lang == OutputLanguageMode::Cxx) {
61+
out << "#include <cstdint>\n"
62+
"#include <cstddef>\n"
63+
"#include <cstdbool>\n";
64+
} else {
65+
out << "#include <Foundation/Foundation.h>\n"
66+
"#include <stdint.h>\n"
67+
"#include <stddef.h>\n"
68+
"#include <stdbool.h>\n";
69+
}
70+
out << "\n"
6271
"#if !defined(SWIFT_TYPEDEFS)\n"
6372
"# define SWIFT_TYPEDEFS 1\n"
6473
"# if __has_include(<uchar.h>)\n"
@@ -95,19 +104,19 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
95104
"\n"
96105
"#if __has_attribute(objc_runtime_name)\n"
97106
"# define SWIFT_RUNTIME_NAME(X) "
98-
"__attribute__((objc_runtime_name(X)))\n"
107+
"__attribute__((objc_runtime_name(X)))\n"
99108
"#else\n"
100109
"# define SWIFT_RUNTIME_NAME(X)\n"
101110
"#endif\n"
102111
"#if __has_attribute(swift_name)\n"
103112
"# define SWIFT_COMPILE_NAME(X) "
104-
"__attribute__((swift_name(X)))\n"
113+
"__attribute__((swift_name(X)))\n"
105114
"#else\n"
106115
"# define SWIFT_COMPILE_NAME(X)\n"
107116
"#endif\n"
108117
"#if __has_attribute(objc_method_family)\n"
109118
"# define SWIFT_METHOD_FAMILY(X) "
110-
"__attribute__((objc_method_family(X)))\n"
119+
"__attribute__((objc_method_family(X)))\n"
111120
"#else\n"
112121
"# define SWIFT_METHOD_FAMILY(X)\n"
113122
"#endif\n"
@@ -122,7 +131,8 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
122131
"# define SWIFT_RELEASES_ARGUMENT\n"
123132
"#endif\n"
124133
"#if __has_attribute(warn_unused_result)\n"
125-
"# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))\n"
134+
"# define SWIFT_WARN_UNUSED_RESULT "
135+
"__attribute__((warn_unused_result))\n"
126136
"#else\n"
127137
"# define SWIFT_WARN_UNUSED_RESULT\n"
128138
"#endif\n"
@@ -143,41 +153,41 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
143153
"#if !defined(SWIFT_CLASS)\n"
144154
"# if __has_attribute(objc_subclassing_restricted)\n"
145155
"# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) "
146-
"__attribute__((objc_subclassing_restricted)) "
147-
"SWIFT_CLASS_EXTRA\n"
156+
"__attribute__((objc_subclassing_restricted)) "
157+
"SWIFT_CLASS_EXTRA\n"
148158
"# define SWIFT_CLASS_NAMED(SWIFT_NAME) "
149-
"__attribute__((objc_subclassing_restricted)) "
150-
"SWIFT_COMPILE_NAME(SWIFT_NAME) "
151-
"SWIFT_CLASS_EXTRA\n"
159+
"__attribute__((objc_subclassing_restricted)) "
160+
"SWIFT_COMPILE_NAME(SWIFT_NAME) "
161+
"SWIFT_CLASS_EXTRA\n"
152162
"# else\n"
153163
"# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) "
154-
"SWIFT_CLASS_EXTRA\n"
164+
"SWIFT_CLASS_EXTRA\n"
155165
"# define SWIFT_CLASS_NAMED(SWIFT_NAME) "
156-
"SWIFT_COMPILE_NAME(SWIFT_NAME) "
157-
"SWIFT_CLASS_EXTRA\n"
166+
"SWIFT_COMPILE_NAME(SWIFT_NAME) "
167+
"SWIFT_CLASS_EXTRA\n"
158168
"# endif\n"
159169
"#endif\n"
160170
"#if !defined(SWIFT_RESILIENT_CLASS)\n"
161171
"# if __has_attribute(objc_class_stub)\n"
162172
"# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) "
163-
"__attribute__((objc_class_stub))\n"
173+
"__attribute__((objc_class_stub))\n"
164174
"# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) "
165-
"__attribute__((objc_class_stub)) "
166-
"SWIFT_CLASS_NAMED(SWIFT_NAME)\n"
175+
"__attribute__((objc_class_stub)) "
176+
"SWIFT_CLASS_NAMED(SWIFT_NAME)\n"
167177
"# else\n"
168178
"# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) "
169-
"SWIFT_CLASS(SWIFT_NAME)\n"
179+
"SWIFT_CLASS(SWIFT_NAME)\n"
170180
"# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) "
171-
"SWIFT_CLASS_NAMED(SWIFT_NAME)\n"
181+
"SWIFT_CLASS_NAMED(SWIFT_NAME)\n"
172182
"# endif\n"
173183
"#endif\n"
174184
"\n"
175185
"#if !defined(SWIFT_PROTOCOL)\n"
176186
"# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) "
177-
"SWIFT_PROTOCOL_EXTRA\n"
187+
"SWIFT_PROTOCOL_EXTRA\n"
178188
"# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) "
179-
"SWIFT_COMPILE_NAME(SWIFT_NAME) "
180-
"SWIFT_PROTOCOL_EXTRA\n"
189+
"SWIFT_COMPILE_NAME(SWIFT_NAME) "
190+
"SWIFT_PROTOCOL_EXTRA\n"
181191
"#endif\n"
182192
"\n"
183193
"#if !defined(SWIFT_EXTENSION)\n"
@@ -187,44 +197,46 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
187197
"#if !defined(OBJC_DESIGNATED_INITIALIZER)\n"
188198
"# if __has_attribute(objc_designated_initializer)\n"
189199
"# define OBJC_DESIGNATED_INITIALIZER "
190-
"__attribute__((objc_designated_initializer))\n"
200+
"__attribute__((objc_designated_initializer))\n"
191201
"# else\n"
192202
"# define OBJC_DESIGNATED_INITIALIZER\n"
193203
"# endif\n"
194204
"#endif\n"
195205
"#if !defined(SWIFT_ENUM_ATTR)\n"
196206
"# if defined(__has_attribute) && "
197-
"__has_attribute(enum_extensibility)\n"
207+
"__has_attribute(enum_extensibility)\n"
198208
"# define SWIFT_ENUM_ATTR(_extensibility) "
199-
"__attribute__((enum_extensibility(_extensibility)))\n"
209+
"__attribute__((enum_extensibility(_extensibility)))\n"
200210
"# else\n"
201211
"# define SWIFT_ENUM_ATTR(_extensibility)\n"
202212
"# endif\n"
203213
"#endif\n"
204214
"#if !defined(SWIFT_ENUM)\n"
205215
"# define SWIFT_ENUM(_type, _name, _extensibility) "
206-
"enum _name : _type _name; "
207-
"enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA "
208-
"_name : _type\n"
216+
"enum _name : _type _name; "
217+
"enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA "
218+
"_name : _type\n"
209219
"# if __has_feature(generalized_swift_name)\n"
210220
"# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, "
211-
"_extensibility) "
212-
"enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); "
213-
"enum SWIFT_COMPILE_NAME(SWIFT_NAME) "
214-
"SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type\n"
221+
"_extensibility) "
222+
"enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); "
223+
"enum SWIFT_COMPILE_NAME(SWIFT_NAME) "
224+
"SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type\n"
215225
"# else\n"
216226
"# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, "
217-
"_extensibility) SWIFT_ENUM(_type, _name, _extensibility)\n"
227+
"_extensibility) SWIFT_ENUM(_type, _name, _extensibility)\n"
218228
"# endif\n"
219229
"#endif\n"
220230
"#if !defined(SWIFT_UNAVAILABLE)\n"
221231
"# define SWIFT_UNAVAILABLE __attribute__((unavailable))\n"
222232
"#endif\n"
223233
"#if !defined(SWIFT_UNAVAILABLE_MSG)\n"
224-
"# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg)))\n"
234+
"# define SWIFT_UNAVAILABLE_MSG(msg) "
235+
"__attribute__((unavailable(msg)))\n"
225236
"#endif\n"
226237
"#if !defined(SWIFT_AVAILABILITY)\n"
227-
"# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__)))\n"
238+
"# define SWIFT_AVAILABILITY(plat, ...) "
239+
"__attribute__((availability(plat, __VA_ARGS__)))\n"
228240
"#endif\n"
229241
"#if !defined(SWIFT_WEAK_IMPORT)\n"
230242
"# define SWIFT_WEAK_IMPORT __attribute__((weak_import))\n"
@@ -233,24 +245,27 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
233245
"# define SWIFT_DEPRECATED __attribute__((deprecated))\n"
234246
"#endif\n"
235247
"#if !defined(SWIFT_DEPRECATED_MSG)\n"
236-
"# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))\n"
248+
"# define SWIFT_DEPRECATED_MSG(...) "
249+
"__attribute__((deprecated(__VA_ARGS__)))\n"
237250
"#endif\n"
238251
"#if __has_feature(attribute_diagnose_if_objc)\n"
239-
"# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, \"warning\")))\n"
252+
"# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, "
253+
"Msg, \"warning\")))\n"
240254
"#else\n"
241255
"# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)\n"
242-
"#endif\n"
243-
"#if !defined(IBSegueAction)\n"
244-
"# define IBSegueAction\n"
245-
"#endif\n"
246-
"#if !defined(SWIFT_EXTERN)\n"
256+
"#endif\n";
257+
if (Lang == OutputLanguageMode::ObjC) {
258+
out << "#if !defined(IBSegueAction)\n"
259+
"# define IBSegueAction\n"
260+
"#endif\n";
261+
}
262+
out << "#if !defined(SWIFT_EXTERN)\n"
247263
"# if defined(__cplusplus)\n"
248264
"# define SWIFT_EXTERN extern \"C\"\n"
249265
"# else\n"
250266
"# define SWIFT_EXTERN extern\n"
251267
"# endif\n"
252-
"#endif\n"
253-
;
268+
"#endif\n";
254269
static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4,
255270
"need to add SIMD typedefs here if max elements is increased");
256271
}
@@ -401,7 +416,8 @@ bool swift::printAsObjC(raw_ostream &os, ModuleDecl *M,
401416
std::string moduleContentsBuf;
402417
llvm::raw_string_ostream moduleContents{moduleContentsBuf};
403418
printModuleContentsAsObjC(moduleContents, imports, *M);
404-
writePrologue(os, M->getASTContext(), computeMacroGuard(M));
419+
writePrologue(os, M->getASTContext(), computeMacroGuard(M),
420+
OutputLanguageMode::ObjC);
405421
writeImports(os, imports, *M, bridgingHeader);
406422
writePostImportPrologue(os, *M);
407423
os << moduleContents.str();
@@ -413,9 +429,14 @@ bool swift::printAsObjC(raw_ostream &os, ModuleDecl *M,
413429
bool swift::printAsCXX(raw_ostream &os, ModuleDecl *M) {
414430
llvm::PrettyStackTraceString trace("While generating C++ header");
415431

416-
writePrologue(os, M->getASTContext(), computeMacroGuard(M));
432+
SmallPtrSet<ImportModuleTy, 8> imports;
433+
std::string moduleContentsBuf;
434+
llvm::raw_string_ostream moduleContents{moduleContentsBuf};
435+
printModuleContentsAsCxx(moduleContents, imports, *M);
436+
writePrologue(os, M->getASTContext(), computeMacroGuard(M),
437+
OutputLanguageMode::Cxx);
417438
writePostImportPrologue(os, *M);
418-
// TODO (Alex): emit module contents.
439+
os << moduleContents.str();
419440
writeEpilogue(os);
420441

421442
return false;

test/PrintAsCxx/empty.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -typecheck -emit-cxx-header-path %t/empty.h
33
// RUN: %FileCheck %s < %t/empty.h
44

5+
// RUN: %check-in-clang++ -std=c++14 %t/empty.h
6+
// RUN: %check-in-clang++ -std=c++17 %t/empty.h
7+
58
// CHECK-NOT: @import Swift;
9+
// CHECK-NOT: IBSegueAction
610

711
// CHECK-LABEL: #ifndef EMPTY_SWIFT_H
812
// CHECK-NEXT: #define EMPTY_SWIFT_H
@@ -23,10 +27,9 @@
2327
// CHECK-NEXT: # define __has_warning(x) 0
2428
// CHECK-NEXT: #endif
2529

26-
// CHECK-LABEL: #include <Foundation/Foundation.h>
27-
// CHECK: #include <stdint.h>
28-
// CHECK: #include <stddef.h>
29-
// CHECK: #include <stdbool.h>
30+
// CHECK-LABEL: #include <cstdint>
31+
// CHECK: #include <cstddef>
32+
// CHECK: #include <cstdbool>
3033

3134
// CHECK-LABEL: !defined(SWIFT_TYPEDEFS)
3235
// CHECK-NEXT: # define SWIFT_TYPEDEFS 1
@@ -51,4 +54,7 @@
5154
// CHECK: # define SWIFT_EXTENSION(M)
5255
// CHECK: # define OBJC_DESIGNATED_INITIALIZER
5356

57+
// CHECK-LABEL: namespace empty {
58+
// CHECK: } // namespace empty
59+
5460
// CHECK-NOT: @

test/PrintAsCxx/lit.local.cfg

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Make a local copy of the substitutions.
2+
config.substitutions = list(config.substitutions)
3+
4+
config.substitutions.insert(0, ('%check-in-clang\+\+',
5+
'%%clang --driver-mode=g++ -fsyntax-only -x c++-header '
6+
'-Weverything -Werror -Wno-unused-macros -Wno-incomplete-module '
7+
'-Wno-auto-import -Wno-variadic-macros -Wno-c++98-compat-pedantic '
8+
'-Wno-poison-system-directories '
9+
'-Wno-unused-command-line-argument ' # for -fmodules-cache-path
10+
'-F %%clang-importer-sdk-path/frameworks '
11+
'-I %%clang-include-dir '
12+
'-isysroot %r/Inputs/clang-importer-sdk' % config.test_source_root) )

0 commit comments

Comments
 (0)