Skip to content

Commit 4fd0671

Browse files
authored
Merge pull request #25870 from pschuh/cpp-1
Add -enable-cxx-interop flag and support for extern "C" {}
2 parents 3f0e69f + fa69a73 commit 4fd0671

File tree

16 files changed

+97
-25
lines changed

16 files changed

+97
-25
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ namespace swift {
147147
/// configuration options.
148148
bool EnableObjCInterop = true;
149149

150+
/// Enable C++ interop code generation and build configuration
151+
/// options. Disabled by default because there is no way to control the
152+
/// language mode of clang on a per-header or even per-module basis. Also
153+
/// disabled because it is not complete.
154+
bool EnableCXXInterop = false;
155+
150156
/// On Darwin platforms, use the pre-stable ABI's mark bit for Swift
151157
/// classes instead of the stable ABI's bit. This is needed when
152158
/// targeting OSes prior to macOS 10.14.4 and iOS 12.2, where

include/swift/Option/FrontendOptions.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,11 @@ def emit_sorted_sil : Flag<["-"], "emit-sorted-sil">,
500500
def emit_syntax : Flag<["-"], "emit-syntax">,
501501
HelpText<"Parse input file(s) and emit the Syntax tree(s) as JSON">, ModeOpt;
502502

503+
def enable_cxx_interop :
504+
Flag<["-"], "enable-cxx-interop">,
505+
HelpText<"Enable C++ interop code generation and config directives">,
506+
Flags<[FrontendOption, HelpHidden]>;
507+
503508
def use_malloc : Flag<["-"], "use-malloc">,
504509
HelpText<"Allocate internal data structures using malloc "
505510
"(for memory debugging)">;

lib/ClangImporter/ClangImporter.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,11 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
498498
"-Werror=non-modular-include-in-framework-module");
499499

500500
if (LangOpts.EnableObjCInterop) {
501-
invocationArgStrs.insert(invocationArgStrs.end(),
502-
{"-x", "objective-c", "-std=gnu11", "-fobjc-arc"});
501+
bool EnableCXXInterop = LangOpts.EnableCXXInterop;
502+
invocationArgStrs.insert(
503+
invocationArgStrs.end(),
504+
{"-x", EnableCXXInterop ? "objective-c++" : "objective-c",
505+
EnableCXXInterop ? "-std=gnu++17" : "-std=gnu11", "-fobjc-arc"});
503506
// TODO: Investigate whether 7.0 is a suitable default version.
504507
if (!triple.isOSDarwin())
505508
invocationArgStrs.insert(invocationArgStrs.end(),
@@ -518,7 +521,10 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
518521
});
519522

520523
} else {
521-
invocationArgStrs.insert(invocationArgStrs.end(), {"-x", "c", "-std=gnu11"});
524+
bool EnableCXXInterop = LangOpts.EnableCXXInterop;
525+
invocationArgStrs.insert(invocationArgStrs.end(),
526+
{"-x", EnableCXXInterop ? "c++" : "c",
527+
EnableCXXInterop ? "-std=gnu++17" : "-std=gnu11"});
522528
}
523529

524530
// Set C language options.

lib/ClangImporter/ImportDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8399,7 +8399,7 @@ bool ClangImporter::Implementation::addMemberAndAlternatesToExtension(
83998399
// Quickly check the context and bail out if it obviously doesn't
84008400
// belong here.
84018401
if (auto *importDC = newName.getEffectiveContext().getAsDeclContext())
8402-
if (importDC->isTranslationUnit())
8402+
if (importDC->isFileContext())
84038403
return true;
84048404

84058405
// Then try to import the decl under the specified name.

lib/ClangImporter/ImportName.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,8 +1404,8 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
14041404
case clang::DeclarationName::CXXOperatorName:
14051405
case clang::DeclarationName::CXXUsingDirective:
14061406
case clang::DeclarationName::CXXDeductionGuideName:
1407-
// Handling these is part of C++ interoperability.
1408-
llvm_unreachable("unhandled C++ interoperability");
1407+
// TODO: Handling these is part of C++ interoperability.
1408+
return ImportedName();
14091409

14101410
case clang::DeclarationName::Identifier:
14111411
// Map the identifier.

lib/ClangImporter/SwiftLookupTable.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ class SwiftLookupTableWriter : public clang::ModuleFileExtensionWriter {
8181
llvm::BitstreamWriter &stream) override;
8282

8383
void populateTable(SwiftLookupTable &table, NameImporter &);
84+
85+
void populateTableWithDecl(SwiftLookupTable &table,
86+
NameImporter &nameImporter, clang::Decl *decl);
8487
};
8588

8689
/// Module file extension reader for the Swift lookup tables.
@@ -1793,21 +1796,35 @@ void importer::finalizeLookupTable(SwiftLookupTable &table,
17931796
}
17941797
}
17951798

1799+
void SwiftLookupTableWriter::populateTableWithDecl(SwiftLookupTable &table,
1800+
NameImporter &nameImporter,
1801+
clang::Decl *decl) {
1802+
// Skip anything from an AST file.
1803+
if (decl->isFromASTFile())
1804+
return;
1805+
1806+
// Iterate into extern "C" {} type declarations.
1807+
if (auto linkageDecl = dyn_cast<clang::LinkageSpecDecl>(decl)) {
1808+
for (auto *decl : linkageDecl->noload_decls()) {
1809+
populateTableWithDecl(table, nameImporter, decl);
1810+
}
1811+
return;
1812+
}
1813+
1814+
// Skip non-named declarations.
1815+
auto named = dyn_cast<clang::NamedDecl>(decl);
1816+
if (!named)
1817+
return;
1818+
1819+
// Add this entry to the lookup table.
1820+
addEntryToLookupTable(table, named, nameImporter);
1821+
}
1822+
17961823
void SwiftLookupTableWriter::populateTable(SwiftLookupTable &table,
17971824
NameImporter &nameImporter) {
17981825
auto &sema = nameImporter.getClangSema();
17991826
for (auto decl : sema.Context.getTranslationUnitDecl()->noload_decls()) {
1800-
// Skip anything from an AST file.
1801-
if (decl->isFromASTFile())
1802-
continue;
1803-
1804-
// Skip non-named declarations.
1805-
auto named = dyn_cast<clang::NamedDecl>(decl);
1806-
if (!named)
1807-
continue;
1808-
1809-
// Add this entry to the lookup table.
1810-
addEntryToLookupTable(table, named, nameImporter);
1827+
populateTableWithDecl(table, nameImporter, decl);
18111828
}
18121829

18131830
// Add macros to the lookup table.

lib/ClangImporter/SwiftLookupTable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ class EffectiveClangContext {
196196
DC = omDecl->getCanonicalDecl();
197197
} else if (auto fDecl = dyn_cast<clang::FunctionDecl>(dc)) {
198198
DC = fDecl->getCanonicalDecl();
199+
} else if (auto nsDecl = dyn_cast<clang::NamespaceDecl>(dc)) {
200+
DC = nsDecl->getCanonicalDecl();
199201
} else {
200202
assert(isa<clang::TranslationUnitDecl>(dc) ||
201203
isa<clang::ObjCContainerDecl>(dc) &&

lib/Driver/ToolChains.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI,
194194
inputArgs.AddLastArg(arguments, options::OPT_enable_library_evolution);
195195
inputArgs.AddLastArg(arguments, options::OPT_enable_testing);
196196
inputArgs.AddLastArg(arguments, options::OPT_enable_private_imports);
197+
inputArgs.AddLastArg(arguments, options::OPT_enable_cxx_interop);
197198
inputArgs.AddLastArg(arguments, options::OPT_g_Group);
198199
inputArgs.AddLastArg(arguments, options::OPT_debug_info_format);
199200
inputArgs.AddLastArg(arguments, options::OPT_import_underlying_module);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
499499
TargetArg = A->getValue();
500500
}
501501

502+
Opts.EnableCXXInterop |= Args.hasArg(OPT_enable_cxx_interop);
502503
Opts.EnableObjCInterop =
503504
Args.hasFlag(OPT_enable_objc_interop, OPT_disable_objc_interop,
504505
Target.isOSDarwin());

stdlib/public/SwiftShims/GlobalObjects.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
#include "Visibility.h"
2525

2626
#ifdef __cplusplus
27-
namespace swift { extern "C" {
27+
#ifndef __swift__
28+
namespace swift {
29+
#endif
30+
extern "C" {
2831
#endif
2932

3033
struct _SwiftArrayBodyStorage {
@@ -102,7 +105,10 @@ static_assert(
102105
4 * sizeof(__swift_intptr_t) + sizeof(__swift_int64_t),
103106
"_SwiftSetBodyStorage has unexpected size");
104107

105-
}} // extern "C", namespace swift
108+
} // extern "C"
109+
#ifndef __swift__
110+
} // namespace swift
111+
#endif
106112
#endif
107113

108114
#endif

stdlib/public/SwiftShims/HeapObject.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 16
2121
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 8
2222

23-
#ifdef __cplusplus
23+
#ifndef __swift__
2424
#include <type_traits>
2525
#include "swift/Basic/type_traits.h"
2626

@@ -48,7 +48,7 @@ struct HeapObject {
4848

4949
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
5050

51-
#ifdef __cplusplus
51+
#ifndef __swift__
5252
HeapObject() = default;
5353

5454
// Initialize a HeapObject header as appropriate for a newly-allocated object.
@@ -68,7 +68,7 @@ struct HeapObject {
6868
void dump() const LLVM_ATTRIBUTE_USED;
6969
#endif
7070

71-
#endif // __cplusplus
71+
#endif // __swift__
7272
};
7373

7474
#ifdef __cplusplus
@@ -92,7 +92,7 @@ __swift_size_t swift_weakRetainCount(HeapObject *obj);
9292
} // extern "C"
9393
#endif
9494

95-
#ifdef __cplusplus
95+
#ifndef __swift__
9696
static_assert(std::is_trivially_destructible<HeapObject>::value,
9797
"HeapObject must be trivially destructible");
9898

stdlib/public/SwiftShims/RefCount.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ typedef struct {
2121
__swift_uintptr_t refCounts SWIFT_ATTRIBUTE_UNAVAILABLE;
2222
} InlineRefCountsPlaceholder;
2323

24-
#if !defined(__cplusplus)
24+
#if defined(__swift__)
2525

2626
typedef InlineRefCountsPlaceholder InlineRefCounts;
2727

stdlib/public/SwiftShims/SwiftStddef.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ typedef __SIZE_TYPE__ __swift_size_t;
2929
#endif
3030

3131
// This selects the signed equivalent of the unsigned type chosen for size_t.
32-
#if __STDC_VERSION__-0 >= 201112l
32+
#if __STDC_VERSION__-0 >= 201112l || defined(__swift__)
3333
typedef __typeof__(_Generic((__swift_size_t)0, \
3434
unsigned long long int : (long long int)0, \
3535
unsigned long int : (long int)0, \
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
// Ensure c++ features are used.
4+
namespace ns {
5+
class T {};
6+
} // namespace ns
7+
8+
struct Basic {
9+
int a;
10+
ns::T *b;
11+
};
12+
13+
Basic makeA();

test/ClangImporter/Inputs/custom-modules/module.map

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ module CoreCooling {
3636
export *
3737
}
3838

39+
module CXXInterop {
40+
header "cxx_interop.h"
41+
}
42+
3943
module ctypes_bits_exported {
4044
header "ctypes_bits_exported.h"
4145
export *

test/ClangImporter/cxx_interop.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -typecheck %s -I %S/Inputs/custom-modules -module-cache-path %t -enable-cxx-interop
3+
4+
import CXXInterop
5+
6+
// Basic structs
7+
do {
8+
var tmp: Basic = makeA()
9+
tmp.a = 3
10+
tmp.b = nil
11+
}

0 commit comments

Comments
 (0)