Skip to content

Add -enable-cxx-interop flag and support for extern "C" {} #25870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ namespace swift {
/// configuration options.
bool EnableObjCInterop = true;

/// Enable C++ interop code generation and build configuration
/// options. Disabled by default because there is no way to control the
/// language mode of clang on a per-header or even per-module basis. Also
/// disabled because it is not complete.
bool EnableCXXInterop = false;

/// On Darwin platforms, use the pre-stable ABI's mark bit for Swift
/// classes instead of the stable ABI's bit. This is needed when
/// targeting OSes prior to macOS 10.14.4 and iOS 12.2, where
Expand Down
5 changes: 5 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,11 @@ def emit_sorted_sil : Flag<["-"], "emit-sorted-sil">,
def emit_syntax : Flag<["-"], "emit-syntax">,
HelpText<"Parse input file(s) and emit the Syntax tree(s) as JSON">, ModeOpt;

def enable_cxx_interop :
Flag<["-"], "enable-cxx-interop">,
HelpText<"Enable C++ interop code generation and config directives">,
Flags<[FrontendOption, HelpHidden]>;

def use_malloc : Flag<["-"], "use-malloc">,
HelpText<"Allocate internal data structures using malloc "
"(for memory debugging)">;
Expand Down
12 changes: 9 additions & 3 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,11 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
"-Werror=non-modular-include-in-framework-module");

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

} else {
invocationArgStrs.insert(invocationArgStrs.end(), {"-x", "c", "-std=gnu11"});
bool EnableCXXInterop = LangOpts.EnableCXXInterop;
invocationArgStrs.insert(invocationArgStrs.end(),
{"-x", EnableCXXInterop ? "c++" : "c",
EnableCXXInterop ? "-std=gnu++17" : "-std=gnu11"});
}

// Set C language options.
Expand Down
2 changes: 1 addition & 1 deletion lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8451,7 +8451,7 @@ bool ClangImporter::Implementation::addMemberAndAlternatesToExtension(
// Quickly check the context and bail out if it obviously doesn't
// belong here.
if (auto *importDC = newName.getEffectiveContext().getAsDeclContext())
if (importDC->isTranslationUnit())
if (importDC->isFileContext())
return true;

// Then try to import the decl under the specified name.
Expand Down
4 changes: 2 additions & 2 deletions lib/ClangImporter/ImportName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1404,8 +1404,8 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
case clang::DeclarationName::CXXOperatorName:
case clang::DeclarationName::CXXUsingDirective:
case clang::DeclarationName::CXXDeductionGuideName:
// Handling these is part of C++ interoperability.
llvm_unreachable("unhandled C++ interoperability");
// TODO: Handling these is part of C++ interoperability.
return ImportedName();

case clang::DeclarationName::Identifier:
// Map the identifier.
Expand Down
39 changes: 28 additions & 11 deletions lib/ClangImporter/SwiftLookupTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ class SwiftLookupTableWriter : public clang::ModuleFileExtensionWriter {
llvm::BitstreamWriter &stream) override;

void populateTable(SwiftLookupTable &table, NameImporter &);

void populateTableWithDecl(SwiftLookupTable &table,
NameImporter &nameImporter, clang::Decl *decl);
};

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

void SwiftLookupTableWriter::populateTableWithDecl(SwiftLookupTable &table,
NameImporter &nameImporter,
clang::Decl *decl) {
// Skip anything from an AST file.
if (decl->isFromASTFile())
return;

// Iterate into extern "C" {} type declarations.
if (auto linkageDecl = dyn_cast<clang::LinkageSpecDecl>(decl)) {
for (auto *decl : linkageDecl->noload_decls()) {
populateTableWithDecl(table, nameImporter, decl);
}
return;
}

// Skip non-named declarations.
auto named = dyn_cast<clang::NamedDecl>(decl);
if (!named)
return;

// Add this entry to the lookup table.
addEntryToLookupTable(table, named, nameImporter);
}

void SwiftLookupTableWriter::populateTable(SwiftLookupTable &table,
NameImporter &nameImporter) {
auto &sema = nameImporter.getClangSema();
for (auto decl : sema.Context.getTranslationUnitDecl()->noload_decls()) {
// Skip anything from an AST file.
if (decl->isFromASTFile())
continue;

// Skip non-named declarations.
auto named = dyn_cast<clang::NamedDecl>(decl);
if (!named)
continue;

// Add this entry to the lookup table.
addEntryToLookupTable(table, named, nameImporter);
populateTableWithDecl(table, nameImporter, decl);
}

// Add macros to the lookup table.
Expand Down
2 changes: 2 additions & 0 deletions lib/ClangImporter/SwiftLookupTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ class EffectiveClangContext {
DC = omDecl->getCanonicalDecl();
} else if (auto fDecl = dyn_cast<clang::FunctionDecl>(dc)) {
DC = fDecl->getCanonicalDecl();
} else if (auto nsDecl = dyn_cast<clang::NamespaceDecl>(dc)) {
DC = nsDecl->getCanonicalDecl();
} else {
assert(isa<clang::TranslationUnitDecl>(dc) ||
isa<clang::ObjCContainerDecl>(dc) &&
Expand Down
1 change: 1 addition & 0 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI,
inputArgs.AddLastArg(arguments, options::OPT_enable_library_evolution);
inputArgs.AddLastArg(arguments, options::OPT_enable_testing);
inputArgs.AddLastArg(arguments, options::OPT_enable_private_imports);
inputArgs.AddLastArg(arguments, options::OPT_enable_cxx_interop);
inputArgs.AddLastArg(arguments, options::OPT_g_Group);
inputArgs.AddLastArg(arguments, options::OPT_debug_info_format);
inputArgs.AddLastArg(arguments, options::OPT_import_underlying_module);
Expand Down
1 change: 1 addition & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
TargetArg = A->getValue();
}

Opts.EnableCXXInterop |= Args.hasArg(OPT_enable_cxx_interop);
Opts.EnableObjCInterop =
Args.hasFlag(OPT_enable_objc_interop, OPT_disable_objc_interop,
Target.isOSDarwin());
Expand Down
10 changes: 8 additions & 2 deletions stdlib/public/SwiftShims/GlobalObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
#include "Visibility.h"

#ifdef __cplusplus
namespace swift { extern "C" {
#ifndef __swift__
namespace swift {
#endif
extern "C" {
#endif

struct _SwiftArrayBodyStorage {
Expand Down Expand Up @@ -102,7 +105,10 @@ static_assert(
4 * sizeof(__swift_intptr_t) + sizeof(__swift_int64_t),
"_SwiftSetBodyStorage has unexpected size");

}} // extern "C", namespace swift
} // extern "C"
#ifndef __swift__
} // namespace swift
#endif
#endif

#endif
8 changes: 4 additions & 4 deletions stdlib/public/SwiftShims/HeapObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 16
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 8

#ifdef __cplusplus
#ifndef __swift__
#include <type_traits>
#include "swift/Basic/type_traits.h"

Expand Down Expand Up @@ -48,7 +48,7 @@ struct HeapObject {

SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;

#ifdef __cplusplus
#ifndef __swift__
HeapObject() = default;

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

#endif // __cplusplus
#endif // __swift__
};

#ifdef __cplusplus
Expand All @@ -92,7 +92,7 @@ __swift_size_t swift_weakRetainCount(HeapObject *obj);
} // extern "C"
#endif

#ifdef __cplusplus
#ifndef __swift__
static_assert(std::is_trivially_destructible<HeapObject>::value,
"HeapObject must be trivially destructible");

Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SwiftShims/RefCount.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ typedef struct {
__swift_uintptr_t refCounts SWIFT_ATTRIBUTE_UNAVAILABLE;
} InlineRefCountsPlaceholder;

#if !defined(__cplusplus)
#if defined(__swift__)

typedef InlineRefCountsPlaceholder InlineRefCounts;

Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SwiftShims/SwiftStddef.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ typedef __SIZE_TYPE__ __swift_size_t;
#endif

// This selects the signed equivalent of the unsigned type chosen for size_t.
#if __STDC_VERSION__-0 >= 201112l
#if __STDC_VERSION__-0 >= 201112l || defined(__swift__)
typedef __typeof__(_Generic((__swift_size_t)0, \
unsigned long long int : (long long int)0, \
unsigned long int : (long int)0, \
Expand Down
13 changes: 13 additions & 0 deletions test/ClangImporter/Inputs/custom-modules/cxx_interop.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

// Ensure c++ features are used.
namespace ns {
class T {};
} // namespace ns

struct Basic {
int a;
ns::T *b;
};

Basic makeA();
4 changes: 4 additions & 0 deletions test/ClangImporter/Inputs/custom-modules/module.map
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ module CoreCooling {
export *
}

module CXXInterop {
header "cxx_interop.h"
}

module ctypes_bits_exported {
header "ctypes_bits_exported.h"
export *
Expand Down
11 changes: 11 additions & 0 deletions test/ClangImporter/cxx_interop.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -typecheck %s -I %S/Inputs/custom-modules -module-cache-path %t -enable-cxx-interop

import CXXInterop

// Basic structs
do {
var tmp: Basic = makeA()
tmp.a = 3
tmp.b = nil
}