mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[cxx-interop] Support nested structs
It is really involved to change how methods and classes are emitted into the header so this patch introduces the impression of nested structs through using statements and still emits the structs themselves as top level structs. It emits them in their own namespace to avoid name collisions. This patch also had to change some names to be fully qualified to avoid some name lookup errors in case of nested structs. Moreover, nesting level of 3 and above requires C++17 because it relies on nested namespaces. Only nested structs are supported, not nested classes. Since this patch is already started to grow quite big, I decided to put it out for reviews and plan to address some of the shortcomings in a follow-up PR. rdar://118793469
This commit is contained in:
@@ -20,8 +20,10 @@
|
||||
#include "swift/AST/TypeCheckRequests.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace cxx_synthesis;
|
||||
@@ -79,7 +81,6 @@ void ClangSyntaxPrinter::printModuleNamespaceQualifiersIfNeeded(
|
||||
|
||||
bool ClangSyntaxPrinter::printNominalTypeOutsideMemberDeclTemplateSpecifiers(
|
||||
const NominalTypeDecl *typeDecl) {
|
||||
// FIXME: Full qualifiers for nested types?
|
||||
if (!typeDecl->isGeneric())
|
||||
return true;
|
||||
printGenericSignature(
|
||||
@@ -126,6 +127,26 @@ void ClangSyntaxPrinter::printClangTypeReference(const clang::Decl *typeDecl) {
|
||||
}
|
||||
}
|
||||
|
||||
bool ClangSyntaxPrinter::printNestedTypeNamespaceQualifiers(
|
||||
const ValueDecl *D) const {
|
||||
bool first = true;
|
||||
while (auto parent = dyn_cast_or_null<NominalTypeDecl>(
|
||||
D->getDeclContext()->getAsDecl())) {
|
||||
// C++ namespaces are imported as enums.
|
||||
if (parent->hasClangNode() &&
|
||||
isa<clang::NamespaceDecl>(parent->getClangNode().getAsDecl()))
|
||||
break;
|
||||
if (!first)
|
||||
os << "::";
|
||||
first = false;
|
||||
os << "__";
|
||||
printBaseName(parent);
|
||||
os << "Nested";
|
||||
D = parent;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
void ClangSyntaxPrinter::printNominalTypeReference(
|
||||
const NominalTypeDecl *typeDecl, const ModuleDecl *moduleContext) {
|
||||
if (typeDecl->hasClangNode()) {
|
||||
@@ -134,7 +155,8 @@ void ClangSyntaxPrinter::printNominalTypeReference(
|
||||
}
|
||||
printModuleNamespaceQualifiersIfNeeded(typeDecl->getModuleContext(),
|
||||
moduleContext);
|
||||
// FIXME: Full qualifiers for nested types?
|
||||
if (!printNestedTypeNamespaceQualifiers(typeDecl))
|
||||
os << "::";
|
||||
ClangSyntaxPrinter(os).printBaseName(typeDecl);
|
||||
if (typeDecl->isGeneric())
|
||||
printGenericSignatureParams(
|
||||
@@ -180,6 +202,18 @@ void ClangSyntaxPrinter::printNamespace(
|
||||
printNamespace([&](raw_ostream &os) { os << name; }, bodyPrinter, trivia);
|
||||
}
|
||||
|
||||
void ClangSyntaxPrinter::printParentNamespaceForNestedTypes(
|
||||
const ValueDecl *D, llvm::function_ref<void(raw_ostream &OS)> bodyPrinter,
|
||||
NamespaceTrivia trivia) const {
|
||||
if (!isa_and_nonnull<NominalTypeDecl>(D->getDeclContext()->getAsDecl())) {
|
||||
bodyPrinter(os);
|
||||
return;
|
||||
}
|
||||
printNamespace(
|
||||
[=](raw_ostream &os) { printNestedTypeNamespaceQualifiers(D); },
|
||||
bodyPrinter, trivia);
|
||||
}
|
||||
|
||||
void ClangSyntaxPrinter::printExternC(
|
||||
llvm::function_ref<void(raw_ostream &OS)> bodyPrinter) const {
|
||||
os << "#ifdef __cplusplus\n";
|
||||
@@ -383,7 +417,8 @@ void ClangSyntaxPrinter::printPrimaryCxxTypeName(
|
||||
const NominalTypeDecl *type, const ModuleDecl *moduleContext) {
|
||||
printModuleNamespaceQualifiersIfNeeded(type->getModuleContext(),
|
||||
moduleContext);
|
||||
// FIXME: Print class qualifiers for nested class references.
|
||||
if (!printNestedTypeNamespaceQualifiers(type))
|
||||
os << "::";
|
||||
printBaseName(type);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user