mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
651 lines
21 KiB
C++
651 lines
21 KiB
C++
//===--- ImportDecl.cpp - Import Clang Declarations -----------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements support for importing Clang declarations into Swift.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ImporterImpl.h"
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/AST/Attr.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/AST/NameLookup.h"
|
|
#include "swift/AST/Types.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/DeclVisitor.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
using namespace swift;
|
|
|
|
namespace {
|
|
/// \brief Convert Clang declarations into the corresponding Swift
|
|
/// declarations.
|
|
class SwiftDeclConverter
|
|
: public clang::DeclVisitor<SwiftDeclConverter, ValueDecl *>
|
|
{
|
|
ClangImporter::Implementation &Impl;
|
|
|
|
public:
|
|
explicit SwiftDeclConverter(ClangImporter::Implementation &impl)
|
|
: Impl(impl) { }
|
|
|
|
ValueDecl *VisitDecl(clang::Decl *decl) {
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitTranslationUnitDecl(clang::TranslationUnitDecl *decl) {
|
|
// Note: translation units are handled specially by importDeclContext.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitNamespaceDecl(clang::NamespaceDecl *decl) {
|
|
// FIXME: Implement once Swift has namespaces.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitUsingDirectiveDecl(clang::UsingDirectiveDecl *decl) {
|
|
// Never imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitNamespaceAliasDecl(clang::NamespaceAliasDecl *decl) {
|
|
// FIXME: Implement once Swift has namespaces.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitLabelDecl(clang::LabelDecl *decl) {
|
|
// Labels are function-local, and therefore never imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitTypedefNameDecl(clang::TypedefNameDecl *decl){
|
|
auto name = Impl.importName(decl->getDeclName());
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
auto type = Impl.importType(decl->getUnderlyingType());
|
|
if (!type)
|
|
return nullptr;
|
|
|
|
return new (Impl.SwiftContext) TypeAliasDecl(
|
|
Impl.importSourceLoc(decl->getLocStart()),
|
|
name,
|
|
Impl.importSourceLoc(decl->getLocation()),
|
|
TypeLoc::withoutLoc(type),
|
|
dc,
|
|
{ });
|
|
}
|
|
|
|
ValueDecl *
|
|
VisitUnresolvedUsingTypenameDecl(clang::UnresolvedUsingTypenameDecl *decl) {
|
|
// Note: only occurs in templates.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitEnumDecl(clang::EnumDecl *decl) {
|
|
decl = decl->getDefinition();
|
|
if (!decl)
|
|
return nullptr;
|
|
|
|
Identifier name;
|
|
if (decl->getDeclName())
|
|
name = Impl.importName(decl->getDeclName());
|
|
else if (decl->getTypedefNameForAnonDecl())
|
|
name =Impl.importName(decl->getTypedefNameForAnonDecl()->getDeclName());
|
|
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
// Create the oneof declaration and record it.
|
|
auto result = new (Impl.SwiftContext)
|
|
OneOfDecl(Impl.importSourceLoc(decl->getLocStart()),
|
|
name,
|
|
Impl.importSourceLoc(decl->getLocation()),
|
|
{ }, nullptr, dc);
|
|
Impl.ImportedDecls[decl->getCanonicalDecl()] = result;
|
|
|
|
// Import each of the enumerators.
|
|
SmallVector<Decl *, 4> members;
|
|
for (auto ec = decl->enumerator_begin(), ecEnd = decl->enumerator_end();
|
|
ec != ecEnd; ++ec) {
|
|
auto ood = Impl.importDecl(*ec);
|
|
if (!ood)
|
|
continue;
|
|
|
|
members.push_back(ood);
|
|
}
|
|
|
|
// FIXME: Source range isn't totally accurate because Clang lacks the
|
|
// location of the '{'.
|
|
result->setMembers(Impl.SwiftContext.AllocateCopy(members),
|
|
Impl.importSourceRange(clang::SourceRange(
|
|
decl->getLocation(),
|
|
decl->getRBraceLoc())));
|
|
|
|
return result;
|
|
}
|
|
|
|
ValueDecl *VisitRecordDecl(clang::RecordDecl *decl) {
|
|
// FIXME: Skip unions for now. We can't properly map them to oneofs,
|
|
// because they aren't descriminated in any way. We could map them to
|
|
// structs, but that would make them very, very unsafe to use.
|
|
if (decl->isUnion())
|
|
return nullptr;
|
|
|
|
// FIXME: Skip Microsoft __interfaces.
|
|
if (decl->isInterface())
|
|
return nullptr;
|
|
|
|
// The types of anonymous structs or unions are never imported; their
|
|
// fields are dumped directly into the enclosing class.
|
|
if (decl->isAnonymousStructOrUnion())
|
|
return nullptr;
|
|
|
|
// FIXME: Figure out how to deal with incomplete types, since that
|
|
// notion doesn't exist in Swift.
|
|
decl = decl->getDefinition();
|
|
if (!decl)
|
|
return nullptr;
|
|
|
|
Identifier name;
|
|
if (decl->getDeclName())
|
|
name = Impl.importName(decl->getDeclName());
|
|
else if (decl->getTypedefNameForAnonDecl())
|
|
name =Impl.importName(decl->getTypedefNameForAnonDecl()->getDeclName());
|
|
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
// Create the struct declaration and record it.
|
|
auto result = new (Impl.SwiftContext)
|
|
StructDecl(Impl.importSourceLoc(decl->getLocStart()),
|
|
name,
|
|
Impl.importSourceLoc(decl->getLocation()),
|
|
{ }, nullptr, dc);
|
|
Impl.ImportedDecls[decl->getCanonicalDecl()] = result;
|
|
|
|
// FIXME: Figure out what to do with base classes in C++. One possible
|
|
// solution would be to turn them into members and add conversion
|
|
// functions.
|
|
|
|
// Import each of the members.
|
|
SmallVector<Decl *, 4> members;
|
|
for (auto m = decl->decls_begin(), mEnd = decl->decls_end();
|
|
m != mEnd; ++m) {
|
|
auto nd = dyn_cast<clang::NamedDecl>(*m);
|
|
if (!nd)
|
|
continue;
|
|
|
|
// Skip anonymous structs or unions; they'll be dealt with via the
|
|
// IndirectFieldDecls.
|
|
if (auto field = dyn_cast<clang::FieldDecl>(nd))
|
|
if (field->isAnonymousStructOrUnion())
|
|
continue;
|
|
|
|
auto member = Impl.importDecl(nd);
|
|
if (!member)
|
|
continue;
|
|
|
|
members.push_back(member);
|
|
}
|
|
|
|
// FIXME: Source range isn't totally accurate because Clang lacks the
|
|
// location of the '{'.
|
|
result->setMembers(Impl.SwiftContext.AllocateCopy(members),
|
|
Impl.importSourceRange(clang::SourceRange(
|
|
decl->getLocation(),
|
|
decl->getRBraceLoc())));
|
|
|
|
return result;
|
|
}
|
|
|
|
ValueDecl *VisitClassTemplateSpecializationDecl(
|
|
clang::ClassTemplateSpecializationDecl *decl) {
|
|
// FIXME: We could import specializations, but perhaps only as unnamed
|
|
// structural types.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitClassTemplatePartialSpecializationDecl(
|
|
clang::ClassTemplatePartialSpecializationDecl *decl) {
|
|
// Note: templates are not imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl *decl) {
|
|
// Note: templates are not imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitEnumConstantDecl(clang::EnumConstantDecl *decl) {
|
|
auto name = Impl.importName(decl->getDeclName());
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
auto result
|
|
= new (Impl.SwiftContext)
|
|
OneOfElementDecl(Impl.importSourceLoc(decl->getLocation()),
|
|
name, TypeLoc(), dc);
|
|
|
|
// Give the oneof element the appropriate type.
|
|
auto oneof = cast<OneOfDecl>(dc);
|
|
auto argTy = MetaTypeType::get(oneof->getDeclaredType(),
|
|
Impl.SwiftContext);
|
|
result->overwriteType(FunctionType::get(argTy, oneof->getDeclaredType(),
|
|
Impl.SwiftContext));
|
|
return result;
|
|
}
|
|
|
|
ValueDecl *
|
|
VisitUnresolvedUsingValueDecl(clang::UnresolvedUsingValueDecl *decl) {
|
|
// Note: templates are not imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitIndirectFieldDecl(clang::IndirectFieldDecl *decl) {
|
|
// Check whether the context of any of the fields in the chain is a
|
|
// union. If so, don't import this field.
|
|
for (auto f = decl->chain_begin(), fEnd = decl->chain_end(); f != fEnd;
|
|
++f) {
|
|
if (auto record = dyn_cast<clang::RecordDecl>((*f)->getDeclContext())) {
|
|
if (record->isUnion())
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
auto name = Impl.importName(decl->getDeclName());
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
auto type = Impl.importType(decl->getType());
|
|
if (!type)
|
|
return nullptr;
|
|
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
// Map this indirect field to a Swift variable.
|
|
return new (Impl.SwiftContext)
|
|
VarDecl(Impl.importSourceLoc(decl->getLocStart()),
|
|
name, type, dc);
|
|
}
|
|
|
|
ValueDecl *VisitFunctionDecl(clang::FunctionDecl *decl) {
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
// Import the function type. If we have parameters, make sure their names
|
|
// get into the resulting function type.
|
|
Type type;
|
|
if (decl->param_size())
|
|
type = Impl.importFunctionType(
|
|
decl->getType()->getAs<clang::FunctionType>()->getResultType(),
|
|
{ decl->param_begin(), decl->param_size() },
|
|
decl->isVariadic());
|
|
else
|
|
type = Impl.importType(decl->getType());
|
|
|
|
if (!type)
|
|
return nullptr;
|
|
|
|
auto name = Impl.importName(decl->getDeclName());
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
return new (Impl.SwiftContext)
|
|
FuncDecl(SourceLoc(),
|
|
Impl.importSourceLoc(decl->getLocStart()),
|
|
name,
|
|
Impl.importSourceLoc(decl->getLocation()),
|
|
/*GenericParams=*/0,
|
|
type,
|
|
/*Body=*/nullptr,
|
|
dc);
|
|
}
|
|
|
|
ValueDecl *VisitCXXMethodDecl(clang::CXXMethodDecl *decl) {
|
|
// FIXME: Import C++ member functions as methods.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitFieldDecl(clang::FieldDecl *decl) {
|
|
// Fields are imported as variables.
|
|
auto name = Impl.importName(decl->getDeclName());
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
auto type = Impl.importType(decl->getType());
|
|
if (!type)
|
|
return nullptr;
|
|
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
return new (Impl.SwiftContext)
|
|
VarDecl(Impl.importSourceLoc(decl->getLocation()),
|
|
name, type, dc);
|
|
}
|
|
|
|
ValueDecl *VisitObjCIvarDecl(clang::ObjCIvarDecl *decl) {
|
|
// FIXME: Deal with fact that a property and an ivar can have the same
|
|
// name.
|
|
return VisitFieldDecl(decl);
|
|
}
|
|
|
|
ValueDecl *VisitObjCAtDefsFieldDecl(clang::ObjCAtDefsFieldDecl *decl) {
|
|
// @defs is an anachronism; ignore it.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitVarDecl(clang::VarDecl *decl) {
|
|
// FIXME: Swift does not have static variables in structs/classes yet.
|
|
if (decl->getDeclContext()->isRecord())
|
|
return nullptr;
|
|
|
|
// Variables are imported as... variables.
|
|
auto name = Impl.importName(decl->getDeclName());
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
auto type = Impl.importType(decl->getType());
|
|
if (!type)
|
|
return nullptr;
|
|
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
return new (Impl.SwiftContext)
|
|
VarDecl(Impl.importSourceLoc(decl->getLocation()),
|
|
name, type, dc);
|
|
}
|
|
|
|
ValueDecl *VisitImplicitParamDecl(clang::ImplicitParamDecl *decl) {
|
|
// Parameters are never directly imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitParmVarDecl(clang::ParmVarDecl *decl) {
|
|
// Parameters are never directly imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *
|
|
VisitNonTypeTemplateParmDecl(clang::NonTypeTemplateParmDecl *decl) {
|
|
// Note: templates are not imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitTemplateDecl(clang::TemplateDecl *decl) {
|
|
// Note: templates are not imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitUsingDecl(clang::UsingDecl *decl) {
|
|
// Using declarations are not imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitUsingShadowDecl(clang::UsingShadowDecl *decl) {
|
|
// Using shadow declarations are not imported; rather, name lookup just
|
|
// looks through them.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitObjCMethodDecl(clang::ObjCMethodDecl *decl) {
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
// The name of the method is the first part of the selector.
|
|
auto name
|
|
= Impl.importName(decl->getSelector().getIdentifierInfoForSlot(0));
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
// Import the type that this method will have.
|
|
auto type = Impl.importFunctionType(decl->getResultType(),
|
|
{ decl->param_begin(),
|
|
decl->param_size() },
|
|
decl->isVariadic(),
|
|
decl->getSelector());
|
|
if (!type)
|
|
return nullptr;
|
|
|
|
// Figure out the type of the container.
|
|
auto containerTy= dc->getDeclaredTypeOfContext();
|
|
assert(containerTy && "Method in non-type context?");
|
|
|
|
// Add the implicit 'this' parameter.
|
|
auto thisTy = containerTy;
|
|
if (decl->isClassMethod())
|
|
thisTy = MetaTypeType::get(thisTy, Impl.SwiftContext);
|
|
TupleTypeElt thisParam(thisTy, Impl.SwiftContext.getIdentifier("this"));
|
|
auto thisTupleTy = TupleType::get({ &thisParam, 1 }, Impl.SwiftContext);
|
|
type = FunctionType::get(thisTupleTy, type, Impl.SwiftContext);
|
|
|
|
// FIXME: Related result type? Not so important when we get constructors
|
|
// working.
|
|
|
|
// FIXME: Add proper parameter patterns so this looks more like a method
|
|
// declaration when Swift prints it back out.
|
|
auto result = new (Impl.SwiftContext)
|
|
FuncDecl(SourceLoc(),
|
|
Impl.importSourceLoc(decl->getLocStart()),
|
|
name,
|
|
Impl.importSourceLoc(decl->getLocation()),
|
|
/*GenericParams=*/0,
|
|
type,
|
|
/*Body=*/nullptr,
|
|
dc);
|
|
|
|
if (decl->isClassMethod())
|
|
result->setStatic();
|
|
|
|
return result;
|
|
}
|
|
|
|
// FIXME: ObjCCategoryDecl
|
|
// FIXME: ObjCProtocolDecl
|
|
|
|
ValueDecl *VisitObjCInterfaceDecl(clang::ObjCInterfaceDecl *decl) {
|
|
// FIXME: Figure out how to deal with incomplete types, since that
|
|
// notion doesn't exist in Swift.
|
|
decl = decl->getDefinition();
|
|
if (!decl)
|
|
return nullptr;
|
|
|
|
auto name = Impl.importName(decl->getDeclName());
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
auto dc = Impl.importDeclContext(decl->getDeclContext());
|
|
if (!dc)
|
|
return nullptr;
|
|
|
|
// FIXME: Import the protocols that this class conforms to. There's
|
|
// a minor, annoying problem here because those protocols might mention
|
|
// this class before we've had a chance to build it (due to forward
|
|
// declarations). The same issue occurs with the superclass...
|
|
|
|
// Create the class declaration and record it.
|
|
auto result = new (Impl.SwiftContext)
|
|
ClassDecl(Impl.importSourceLoc(decl->getLocStart()),
|
|
name,
|
|
Impl.importSourceLoc(decl->getLocation()),
|
|
{ }, nullptr, dc);
|
|
Impl.ImportedDecls[decl->getCanonicalDecl()] = result;
|
|
|
|
// If this Objective-C class has a supertype, import it.
|
|
if (auto objcSuper = decl->getSuperClass()) {
|
|
auto super = cast_or_null<ClassDecl>(Impl.importDecl(objcSuper));
|
|
if (!super)
|
|
return nullptr;
|
|
|
|
TypeLoc superTy(super->getDeclaredType(),
|
|
Impl.importSourceRange(decl->getSuperClassLoc()));
|
|
result->setBaseClassLoc(superTy);
|
|
}
|
|
|
|
// Note that this is an Objective-C class.
|
|
result->getMutableAttrs().ObjC = true;
|
|
|
|
// Import each of the members.
|
|
SmallVector<Decl *, 4> members;
|
|
for (auto m = decl->decls_begin(), mEnd = decl->decls_end();
|
|
m != mEnd; ++m) {
|
|
auto nd = dyn_cast<clang::NamedDecl>(*m);
|
|
if (!nd)
|
|
continue;
|
|
|
|
auto member = Impl.importDecl(nd);
|
|
if (!member)
|
|
continue;
|
|
|
|
members.push_back(member);
|
|
}
|
|
|
|
// FIXME: Source range isn't totally accurate because Clang lacks the
|
|
// location of the '{'.
|
|
result->setMembers(Impl.SwiftContext.AllocateCopy(members),
|
|
Impl.importSourceRange(clang::SourceRange(
|
|
decl->getLocation(),
|
|
decl->getLocEnd())));
|
|
|
|
return result;
|
|
}
|
|
|
|
ValueDecl *VisitObjCImplDecl(clang::ObjCImplDecl *decl) {
|
|
// Implementations of Objective-C classes and categories are not
|
|
// reflected into Swift.
|
|
return nullptr;
|
|
}
|
|
|
|
// FIXME: ObjCPropertyDecl
|
|
|
|
ValueDecl *
|
|
VisitObjCCompatibleAliasDecl(clang::ObjCCompatibleAliasDecl *decl) {
|
|
// Like C++ using declarations, name lookup simply looks through
|
|
// Objective-C compatibility aliases. They are not imported directly.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitLinkageSpecDecl(clang::LinkageSpecDecl *decl) {
|
|
// Linkage specifications are not imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitObjCPropertyImplDecl(clang::ObjCPropertyImplDecl *decl) {
|
|
// @synthesize and @dynamic are not imported, since they are not part
|
|
// of the interface to a class.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitFileScopeAsmDecl(clang::FileScopeAsmDecl *decl) {
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitAccessSpecDecl(clang::AccessSpecDecl *decl) {
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitFriendDecl(clang::FriendDecl *decl) {
|
|
// Friends are not imported; Swift has a different access control
|
|
// mechanism.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitFriendTemplateDecl(clang::FriendTemplateDecl *decl) {
|
|
// Friends are not imported; Swift has a different access control
|
|
// mechanism.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitStaticAssertDecl(clang::StaticAssertDecl *decl) {
|
|
// Static assertions are an implementation detail.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitBlockDecl(clang::BlockDecl *decl) {
|
|
// Blocks are not imported (although block types can be imported).
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitClassScopeFunctionSpecializationDecl(
|
|
clang::ClassScopeFunctionSpecializationDecl *decl) {
|
|
// Note: templates are not imported.
|
|
return nullptr;
|
|
}
|
|
|
|
ValueDecl *VisitImportDecl(clang::ImportDecl *decl) {
|
|
// Transitive module imports are not handled at the declaration level.
|
|
// Rather, they are understood from the module itself.
|
|
return nullptr;
|
|
}
|
|
};
|
|
}
|
|
|
|
ValueDecl *ClangImporter::Implementation::importDecl(clang::NamedDecl *decl) {
|
|
auto known = ImportedDecls.find(decl->getCanonicalDecl());
|
|
if (known != ImportedDecls.end())
|
|
return known->second;
|
|
|
|
SwiftDeclConverter converter(*this);
|
|
auto result = converter.Visit(decl);
|
|
return ImportedDecls[decl->getCanonicalDecl()] = result;
|
|
}
|
|
|
|
DeclContext *
|
|
ClangImporter::Implementation::importDeclContext(clang::DeclContext *dc) {
|
|
// FIXME: Should map to the module we want to import into (?).
|
|
if (dc->isTranslationUnit())
|
|
return firstClangModule;
|
|
|
|
auto decl = dyn_cast<clang::NamedDecl>(dc);
|
|
if (!decl)
|
|
return nullptr;
|
|
|
|
auto swiftDecl = importDecl(decl);
|
|
if (!swiftDecl)
|
|
return nullptr;
|
|
|
|
if (auto nominal = dyn_cast<NominalTypeDecl>(swiftDecl))
|
|
return nominal;
|
|
if (auto extension = dyn_cast<ExtensionDecl>(swiftDecl))
|
|
return extension;
|
|
if (auto constructor = dyn_cast<ConstructorDecl>(swiftDecl))
|
|
return constructor;
|
|
if (auto destructor = dyn_cast<DestructorDecl>(swiftDecl))
|
|
return destructor;
|
|
return nullptr;
|
|
}
|