//===--- 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 { 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 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 members; for (auto m = decl->decls_begin(), mEnd = decl->decls_end(); m != mEnd; ++m) { auto nd = dyn_cast(*m); if (!nd) continue; // Skip anonymous structs or unions; they'll be dealt with via the // IndirectFieldDecls. if (auto field = dyn_cast(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(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((*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()->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(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 members; for (auto m = decl->decls_begin(), mEnd = decl->decls_end(); m != mEnd; ++m) { auto nd = dyn_cast(*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(dc); if (!decl) return nullptr; auto swiftDecl = importDecl(decl); if (!swiftDecl) return nullptr; if (auto nominal = dyn_cast(swiftDecl)) return nominal; if (auto extension = dyn_cast(swiftDecl)) return extension; if (auto constructor = dyn_cast(swiftDecl)) return constructor; if (auto destructor = dyn_cast(swiftDecl)) return destructor; return nullptr; }