//===--- ImporterImpl.h - Import Clang Modules: Implementation --*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 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 provides the implementation class definitions for the Clang // module loader. // //===----------------------------------------------------------------------===// #ifndef SWIFT_CLANG_IMPORTER_IMPL_H #define SWIFT_CLANG_IMPORTER_IMPL_H #include "ImportEnumInfo.h" #include "SwiftLookupTable.h" #include "swift/ClangImporter/ClangImporter.h" #include "swift/AST/ASTContext.h" #include "swift/AST/LazyResolver.h" #include "swift/AST/Module.h" #include "swift/AST/Type.h" #include "swift/AST/ForeignErrorConvention.h" #include "swift/Basic/StringExtras.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclVisitor.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Serialization/ModuleFileExtension.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/TinyPtrVector.h" #include namespace llvm { class SmallBitVector; } namespace clang { class APValue; class Decl; class DeclarationName; class EnumDecl; class MacroInfo; class MangleContext; class NamedDecl; class ObjCInterfaceDecl; class ObjCMethodDecl; class ObjCPropertyDecl; class ParmVarDecl; class Parser; class QualType; class TypedefNameDecl; } namespace swift { class ASTContext; class ClangModuleUnit; class ClassDecl; class ConstructorDecl; class Decl; class DeclContext; class Expr; class ExtensionDecl; class FuncDecl; class Identifier; class Pattern; class SubscriptDecl; class ValueDecl; /// \brief Describes the kind of conversion to apply to a constant value. enum class ConstantConvertKind { /// \brief No conversion required. None, /// \brief Coerce the constant to the given type. Coerce, /// \brief Construct the given type from the constant value. Construction, /// \brief Construct the given type from the constant value, using an /// optional initializer. ConstructionWithUnwrap, /// \brief Perform an unchecked downcast to the given type. Downcast }; /// \brief Describes the kind of type import we're performing. enum class ImportTypeKind { /// \brief Import a type in its most abstract form, without any adjustment. Abstract, /// \brief Import the underlying type of a typedef. Typedef, /// \brief Import the type of a literal value. Value, /// \brief Import the type of a literal value that can be bridged. BridgedValue, /// \brief Import the declared type of a variable. Variable, /// \brief Import the declared type of an audited variable. /// /// This is exactly like ImportTypeKind::Variable, except it /// disables wrapping CF class types in Unmanaged. AuditedVariable, /// \brief Import the declared type of a struct or union field. RecordField, /// \brief Import the result type of a function. /// /// This provides special treatment for 'void', among other things, and /// enables the conversion of bridged types. Result, /// \brief Import the result type of an audited function. /// /// This is exactly like ImportTypeKind::Result, except it /// disables wrapping CF class types in Unmanaged. AuditedResult, /// \brief Import the type of a function parameter. /// /// This provides special treatment for C++ references (which become /// [inout] parameters) and C pointers (which become magic [inout]-able types), /// among other things, and enables the conversion of bridged types. /// Parameters are always considered CF-audited. Parameter, /// \brief Import the type of a parameter declared with /// \c CF_RETURNS_RETAINED. /// /// This ensures that the parameter is not marked as Unmanaged. CFRetainedOutParameter, /// \brief Import the type of a parameter declared with /// \c CF_RETURNS_NON_RETAINED. /// /// This ensures that the parameter is not marked as Unmanaged. CFUnretainedOutParameter, /// \brief Import the type pointed to by a pointer or reference. /// /// This provides special treatment for pointer-to-ObjC-pointer /// types, which get imported as pointers to *checked* optional, /// *Pointer, instead of implicitly unwrapped optional as usual. Pointee, /// \brief Import the type of an ObjC property. /// /// This enables the conversion of bridged types. Properties are always /// considered CF-audited. Property, /// \brief Import the type of an ObjC property accessor. /// /// This behaves exactly like Property except that it accepts Void. PropertyAccessor, /// \brief Import the underlying type of an enum. /// /// This provides special treatment for 'NSUInteger'. Enum }; /// \brief Describes the kind of the C type that can be mapped to a stdlib /// swift type. enum class MappedCTypeKind { UnsignedInt, SignedInt, UnsignedWord, SignedWord, FloatIEEEsingle, FloatIEEEdouble, FloatX87DoubleExtended, VaList, ObjCBool, ObjCSel, ObjCId, ObjCClass, CGFloat, Block, }; /// \brief Describes what to do with the C name of a type that can be mapped to /// a Swift standard library type. enum class MappedTypeNameKind { DoNothing, DefineOnly, DefineAndUse }; /// \brief Describes certain kinds of methods that need to be specially /// handled by the importer. enum class SpecialMethodKind { Regular, Constructor, PropertyAccessor, NSDictionarySubscriptGetter }; #define SWIFT_NATIVE_ANNOTATION_STRING "__swift native" #define SWIFT_PROTOCOL_SUFFIX "Protocol" #define SWIFT_CFTYPE_SUFFIX "Ref" /// Describes whether to classify a factory method as an initializer. enum class FactoryAsInitKind { /// Infer based on name and type (the default). Infer, /// Treat as a class method. AsClassMethod, /// Treat as an initializer. AsInitializer }; /// \brief Implementation of the Clang importer. class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation : public LazyMemberLoader { friend class ClangImporter; class SwiftNameLookupExtension : public clang::ModuleFileExtension { Implementation &Impl; public: SwiftNameLookupExtension(Implementation &impl) : Impl(impl) { } clang::ModuleFileExtensionMetadata getExtensionMetadata() const override; llvm::hash_code hashExtension(llvm::hash_code code) const override; std::unique_ptr createExtensionWriter(clang::ASTWriter &writer) override; std::unique_ptr createExtensionReader(const clang::ModuleFileExtensionMetadata &metadata, clang::ASTReader &reader, clang::serialization::ModuleFile &mod, const llvm::BitstreamCursor &stream) override; }; friend class SwiftNameLookupExtension; public: Implementation(ASTContext &ctx, const ClangImporterOptions &opts); ~Implementation(); /// \brief Swift AST context. ASTContext &SwiftContext; const bool ImportForwardDeclarations; const bool OmitNeedlessWords; const bool InferDefaultArguments; const bool UseSwiftLookupTables; constexpr static const char * const moduleImportBufferName = ""; constexpr static const char * const bridgingHeaderBufferName = ""; private: /// The Swift lookup table for the bridging header. SwiftLookupTable BridgingHeaderLookupTable; /// The Swift lookup tables, per module. /// /// Annoyingly, we list this table early so that it gets torn down after /// the underlying Clang instances that reference it /// (through the Swift name lookup module file extension). llvm::StringMap> LookupTables; /// \brief A count of the number of load module operations. /// FIXME: Horrible, horrible hack for \c loadModule(). unsigned ImportCounter = 0; /// \brief The value of \c ImportCounter last time when imported modules were /// verified. unsigned VerifiedImportCounter = 0; /// \brief Clang compiler invocation. llvm::IntrusiveRefCntPtr Invocation; /// \brief Clang compiler instance, which is used to actually load Clang /// modules. std::unique_ptr Instance; /// \brief Clang compiler action, which is used to actually run the /// parser. std::unique_ptr Action; /// \brief Clang parser, which is used to load textual headers. std::unique_ptr Parser; /// \brief Clang parser, which is used to load textual headers. std::unique_ptr Mangler; /// The active type checker, or null if there is no active type checker. /// /// The flag is \c true if there has ever been a type resolver assigned, i.e. /// if type checking has begun. llvm::PointerIntPair typeResolver; public: /// \brief Mapping of already-imported declarations. llvm::DenseMap ImportedDecls; /// \brief The set of "special" typedef-name declarations, which are /// mapped to specific Swift types. /// /// Normal typedef-name declarations imported into Swift will maintain /// equality between the imported declaration's underlying type and the /// import of the underlying type. A typedef-name declaration is special /// when this is not the case, e.g., Objective-C's "BOOL" has an underlying /// type of "signed char", but is mapped to a special Swift struct type /// ObjCBool. llvm::SmallDenseMap SpecialTypedefNames; /// A mapping from module names to the prefixes placed on global names /// in that module, e.g., the Foundation module uses the "NS" prefix. llvm::StringMap ModulePrefixes; /// Is the given identifier a reserved name in Swift? static bool isSwiftReservedName(StringRef name); /// Translation API nullability from an API note into an optional kind. static OptionalTypeKind translateNullability(clang::NullabilityKind kind); /// Determine whether the given class has designated initializers, /// consulting bool hasDesignatedInitializers(const clang::ObjCInterfaceDecl *classDecl); /// Determine whether the given method is a designated initializer /// of the given class. bool isDesignatedInitializer(const clang::ObjCInterfaceDecl *classDecl, const clang::ObjCMethodDecl *method); /// Determine whether the given method is a required initializer /// of the given class. bool isRequiredInitializer(const clang::ObjCMethodDecl *method); /// Determine whether the given class method should be imported as /// an initializer. FactoryAsInitKind getFactoryAsInit(const clang::ObjCInterfaceDecl *classDecl, const clang::ObjCMethodDecl *method); /// \brief Typedefs that we should not be importing. We should be importing /// underlying decls instead. llvm::DenseSet SuperfluousTypedefs; /// Tag decls whose typedefs were imported instead. /// /// \sa SuperfluousTypedefs llvm::DenseSet DeclsWithSuperfluousTypedefs; /// \brief Mapping of already-imported declarations from protocols, which /// can (and do) get replicated into classes. llvm::DenseMap, Decl *> ImportedProtocolDecls; /// Mapping from identifiers to the set of macros that have that name along /// with their corresponding Swift declaration. /// /// Multiple macro definitions can map to the same declaration if the /// macros are identically defined. llvm::DenseMap, 2>> ImportedMacros; /// Keeps track of active selector-based lookups, so that we don't infinitely /// recurse when checking whether a method with a given selector has already /// been imported. llvm::DenseMap, unsigned> ActiveSelectors; /// Whether we should suppress the import of the given Clang declaration. static bool shouldSuppressDeclImport(const clang::Decl *decl); /// \brief Check if the declaration is one of the specially handled /// accessibility APIs. /// /// These appear as both properties and methods in ObjC and should be /// imported as methods into Swift. static bool isAccessibilityDecl(const clang::Decl *objCMethodOrProp); /// Determine whether this method is an Objective-C "init" method /// that will be imported as a Swift initializer. bool isInitMethod(const clang::ObjCMethodDecl *method); /// Determine whether this Objective-C method should be imported as /// an initializer. /// /// \param prefixLength Will be set to the length of the prefix that /// should be stripped from the first selector piece, e.g., "init" /// or the restated name of the class in a factory method. /// /// \param kind Will be set to the kind of initializer being /// imported. Note that this does not distinguish designated /// vs. convenience; both will be classified as "designated". bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method, unsigned &prefixLength, CtorInitializerKind &kind); private: /// \brief Generation number that is used for crude versioning. /// /// This value is incremented every time a new module is imported. unsigned Generation = 1; /// \brief A cached set of extensions for a particular Objective-C class. struct CachedExtensions { CachedExtensions() : Extensions(nullptr), Generation(0) { } CachedExtensions(const CachedExtensions &) = delete; CachedExtensions &operator=(const CachedExtensions &) = delete; CachedExtensions(CachedExtensions &&other) : Extensions(other.Extensions), Generation(other.Generation) { other.Extensions = nullptr; other.Generation = 0; } CachedExtensions &operator=(CachedExtensions &&other) { delete Extensions; Extensions = other.Extensions; Generation = other.Generation; other.Extensions = nullptr; other.Generation = 0; return *this; } ~CachedExtensions() { delete Extensions; } /// \brief The cached extensions. SmallVector *Extensions; /// \brief Generation number used to tell when this cache has gone stale. unsigned Generation; }; void bumpGeneration() { ++Generation; SwiftContext.bumpGeneration(); } /// \brief Cache enum infos, referenced with a dotted Clang name /// "ModuleName.EnumName". llvm::StringMap enumInfos; public: /// \brief Keep track of subscript declarations based on getter/setter /// pairs. llvm::DenseMap, SubscriptDecl *> Subscripts; /// Retrieve the key to use when looking for enum information. StringRef getEnumInfoKey(const clang::EnumDecl *decl, SmallVectorImpl &scratch) { StringRef moduleName; if (auto moduleOpt = getClangSubmoduleForDecl(decl)) { if (*moduleOpt) moduleName = (*moduleOpt)->getTopLevelModuleName(); } if (moduleName.empty()) moduleName = decl->getASTContext().getLangOpts().CurrentModule; StringRef enumName = decl->getDeclName() ? decl->getName() : decl->getTypedefNameForAnonDecl()->getName(); if (moduleName.empty()) return enumName; scratch.append(moduleName.begin(), moduleName.end()); scratch.push_back('.'); scratch.append(enumName.begin(), enumName.end()); return StringRef(scratch.data(), scratch.size()); } importer::EnumInfo getEnumInfo(const clang::EnumDecl *decl, clang::Preprocessor *ppOverride = nullptr) { // Due to the semaOverride present in importFullName(), we might be using a // decl from a different context. auto &preprocessor = ppOverride ? *ppOverride : getClangPreprocessor(); // If there is no name for linkage, the computation is trivial and we // wouldn't be able to perform name-based caching anyway. if (!decl->hasNameForLinkage()) return importer::EnumInfo(SwiftContext, decl, preprocessor); SmallString<32> keyScratch; auto key = getEnumInfoKey(decl, keyScratch); auto known = enumInfos.find(key); if (known != enumInfos.end()) return known->second; importer::EnumInfo enumInfo(SwiftContext, decl, preprocessor); enumInfos[key] = enumInfo; return enumInfo; } importer::EnumKind getEnumKind(const clang::EnumDecl *decl, clang::Preprocessor *ppOverride = nullptr) { return getEnumInfo(decl, ppOverride).getKind(); } /// \brief the prefix to be stripped from the names of the enum constants /// within the given enum. StringRef getEnumConstantNamePrefix(const clang::EnumDecl *decl, clang::Preprocessor *ppOverride = nullptr) { return getEnumInfo(decl, ppOverride).getConstantNamePrefix(); } private: class EnumConstantDenseMapInfo { public: using PairTy = std::pair; using PointerInfo = llvm::DenseMapInfo; static inline PairTy getEmptyKey() { return {PointerInfo::getEmptyKey(), llvm::APSInt(/*bitwidth=*/1)}; } static inline PairTy getTombstoneKey() { return {PointerInfo::getTombstoneKey(), llvm::APSInt(/*bitwidth=*/1)}; } static unsigned getHashValue(const PairTy &pair) { return llvm::combineHashValue(PointerInfo::getHashValue(pair.first), llvm::hash_value(pair.second)); } static bool isEqual(const PairTy &lhs, const PairTy &rhs) { return lhs == rhs; } }; public: /// \brief Keep track of enum constant values that have been imported. llvm::DenseMap, EnumElementDecl *, EnumConstantDenseMapInfo> EnumConstantValues; /// \brief Keep track of initializer declarations that correspond to /// imported methods. llvm::DenseMap, ConstructorDecl *> Constructors; /// A mapping from imported declarations to their "alternate" declarations, /// for cases where a single Clang declaration is imported to two /// different Swift declarations. llvm::DenseMap AlternateDecls; /// Retrieve the alternative declaration for the given imported /// Swift declaration. ValueDecl *getAlternateDecl(Decl *decl) { auto known = AlternateDecls.find(decl); if (known == AlternateDecls.end()) return nullptr; return known->second; } private: /// \brief NSObject, imported into Swift. Type NSObjectTy; /// A pair containing a ClangModuleUnit, /// and whether the adapters of its re-exported modules have all been forced /// to load already. using ModuleInitPair = llvm::PointerIntPair; public: /// A map from Clang modules to their Swift wrapper modules. llvm::SmallDenseMap ModuleWrappers; /// The module unit that contains declarations from imported headers. ClangModuleUnit *ImportedHeaderUnit = nullptr; /// The modules re-exported by imported headers. llvm::SmallVector ImportedHeaderExports; /// The modules that requested imported headers. /// /// These are used to look up Swift classes forward-declared with \@class. TinyPtrVector ImportedHeaderOwners; /// \brief Clang's objectAtIndexedSubscript: selector. clang::Selector objectAtIndexedSubscript; /// \brief Clang's setObjectAt:indexedSubscript: selector. clang::Selector setObjectAtIndexedSubscript; /// \brief Clang's objectForKeyedSubscript: selector. clang::Selector objectForKeyedSubscript; /// \brief Clang's setObject:forKeyedSubscript: selector. clang::Selector setObjectForKeyedSubscript; private: Optional checkedFoundationModule, checkedSIMDModule; /// External Decls that we have imported but not passed to the ASTContext yet. SmallVector RegisteredExternalDecls; /// Protocol conformances that may be missing witnesses. SmallVector DelayedProtocolConformances; unsigned NumCurrentImportingEntities = 0; /// Mapping from delayed conformance IDs to the set of delayed /// protocol conformances. llvm::DenseMap> DelayedConformances; /// The next delayed conformance ID to use with \c DelayedConformances. unsigned NextDelayedConformanceID = 0; /// The set of imported protocols for a declaration, used only to /// load all members of the declaration. llvm::DenseMap> ImportedProtocols; void startedImportingEntity(); void finishedImportingEntity(); void finishPendingActions(); void finishProtocolConformance(NormalProtocolConformance *conformance); struct ImportingEntityRAII { Implementation &Impl; ImportingEntityRAII(Implementation &Impl) : Impl(Impl) { Impl.startedImportingEntity(); } ~ImportingEntityRAII() { Impl.finishedImportingEntity(); } }; public: /// A predicate that indicates if the given platform should be /// considered for availability. std::function PlatformAvailabilityFilter; /// A predicate that indicates if the given platform version should /// should be included in the cutoff of deprecated APIs marked unavailable. std::function minor)> DeprecatedAsUnavailableFilter; /// The message to embed for implicitly unavailability if a deprecated /// API is now unavailable. std::string DeprecatedAsUnavailableMessage; /// Tracks top level decls from the bridging header. std::vector BridgeHeaderTopLevelDecls; std::vector> BridgeHeaderTopLevelImports; /// Tracks macro definitions from the bridging header. std::vector BridgeHeaderMacros; /// Tracks included headers from the bridging header. llvm::DenseSet BridgeHeaderFiles; void addBridgeHeaderTopLevelDecls(clang::Decl *D); bool shouldIgnoreBridgeHeaderTopLevelDecl(clang::Decl *D); /// Add the given named declaration as an entry to the given Swift name /// lookup table, including any of its child entries. void addEntryToLookupTable(clang::Sema &clangSema, SwiftLookupTable &table, clang::NamedDecl *named); /// Add the macros from the given Clang preprocessor to the given /// Swift name lookup table. void addMacrosToLookupTable(clang::ASTContext &clangCtx, clang::Preprocessor &pp, SwiftLookupTable &table); public: void registerExternalDecl(Decl *D) { RegisteredExternalDecls.push_back(D); } void scheduleFinishProtocolConformance(NormalProtocolConformance *C) { DelayedProtocolConformances.push_back(C); } /// \brief Retrieve the Clang AST context. clang::ASTContext &getClangASTContext() const { return Instance->getASTContext(); } /// \brief Retrieve the Clang Sema object. clang::Sema &getClangSema() const { return Instance->getSema(); } /// \brief Retrieve the Clang AST context. clang::Preprocessor &getClangPreprocessor() const { return Instance->getPreprocessor(); } clang::CodeGenOptions &getClangCodeGenOpts() const { return Instance->getCodeGenOpts(); } /// Imports the given header contents into the Clang context. bool importHeader(Module *adapter, StringRef headerName, SourceLoc diagLoc, bool trackParsedSymbols, std::unique_ptr contents); /// Returns the redeclaration of \p D that contains its definition for any /// tag type decl (struct, enum, or union) or Objective-C class or protocol. /// /// Returns \c None if \p D is not a redeclarable type declaration. /// Returns null if \p D is a redeclarable type, but it does not have a /// definition yet. Optional getDefinitionForClangTypeDecl(const clang::Decl *D); /// Returns the module \p D comes from, or \c None if \p D does not have /// a valid associated module. /// /// The returned module may be null (but not \c None) if \p D comes from /// an imported header. Optional getClangSubmoduleForDecl(const clang::Decl *D, bool allowForwardDeclaration = false); /// \brief Retrieve the imported module that should contain the given /// Clang decl. ClangModuleUnit *getClangModuleForDecl(const clang::Decl *D, bool allowForwardDeclaration = false); /// Returns the module \p MI comes from, or \c None if \p MI does not have /// a valid associated module. /// /// The returned module may be null (but not \c None) if \p MI comes from /// an imported header. Optional getClangSubmoduleForMacro(const clang::MacroInfo *MI); ClangModuleUnit *getClangModuleForMacro(const clang::MacroInfo *MI); /// Retrieve the type of an instance of the given Clang declaration context, /// or a null type if the DeclContext does not have a corresponding type. static clang::QualType getClangDeclContextType(const clang::DeclContext *dc); /// Determine whether this typedef is a CF type. static bool isCFTypeDecl(const clang::TypedefNameDecl *Decl); /// Determine the imported CF type for the given typedef-name, or the empty /// string if this is not an imported CF type name. static StringRef getCFTypeName(const clang::TypedefNameDecl *decl, StringRef *secondaryName = nullptr); /// Retrieve the type name of a Clang type for the purposes of /// omitting unneeded words. static OmissionTypeName getClangTypeNameForOmission(clang::ASTContext &ctx, clang::QualType type); /// Omit needless words in a function name. bool omitNeedlessWordsInFunctionName( clang::Sema &clangSema, StringRef &baseName, SmallVectorImpl &argumentNames, ArrayRef params, clang::QualType resultType, const clang::DeclContext *dc, const llvm::SmallBitVector &nonNullArgs, Optional errorParamIndex, bool returnsSelf, bool isInstanceMethod, StringScratchSpace &scratch); /// \brief Converts the given Swift identifier for Clang. clang::DeclarationName exportName(Identifier name); /// Information about imported error parameters. struct ImportedErrorInfo { ForeignErrorConvention::Kind Kind; ForeignErrorConvention::IsOwned_t IsOwned; /// The index of the error parameter. unsigned ParamIndex; /// Whether the parameter is being replaced with "void" /// (vs. removed). bool ReplaceParamWithVoid; }; /// The kind of accessor that an entity will be imported as. enum class ImportedAccessorKind { None = 0, PropertyGetter, PropertySetter, SubscriptGetter, SubscriptSetter, }; /// Describes a name that was imported from Clang. struct ImportedName { /// The imported name. DeclName Imported; /// An additional alias to the imported name, which should be /// recorded in name lookup tables as well. DeclName Alias; /// Whether this name was explicitly specified via a Clang /// swift_name attribute. bool HasCustomName = false; /// Whether this was one of a special class of Objective-C /// initializers for which we drop the variadic argument rather /// than refuse to import the initializer. bool DroppedVariadic = false; /// What kind of accessor this name refers to, if any. ImportedAccessorKind AccessorKind = ImportedAccessorKind::None; /// For an initializer, the kind of initializer to import. CtorInitializerKind InitKind = CtorInitializerKind::Designated; /// The context into which this declaration will be imported. /// /// When the context into which the declaration will be imported /// matches a Clang declaration context (the common case), the /// result will be expressed as a declaration context. Otherwise, /// if the Clang type is not itself a declaration context (for /// example, a typedef that comes into Swift as a strong type), /// the type declaration will be provided. EffectiveClangContext EffectiveContext; /// For names that map Objective-C error handling conventions into /// throwing Swift methods, describes how the mapping is performed. Optional ErrorInfo; /// Produce just the imported name, for clients that don't care /// about the details. operator DeclName() const { return Imported; } /// Whether any name was imported. explicit operator bool() const { return static_cast(Imported); } /// Whether this declaration is a property accessor (getter or setter). bool isPropertyAccessor() const { switch (AccessorKind) { case ImportedAccessorKind::None: case ImportedAccessorKind::SubscriptGetter: case ImportedAccessorKind::SubscriptSetter: return false; case ImportedAccessorKind::PropertyGetter: case ImportedAccessorKind::PropertySetter: return true; } } /// Whether this declaration is a subscript accessor (getter or setter). bool isSubscriptAccessor() const { switch (AccessorKind) { case ImportedAccessorKind::None: case ImportedAccessorKind::PropertyGetter: case ImportedAccessorKind::PropertySetter: return false; case ImportedAccessorKind::SubscriptGetter: case ImportedAccessorKind::SubscriptSetter: return true; } } }; /// Flags that control the import of names in importFullName. enum class ImportNameFlags { /// Suppress the factory-method-as-initializer transformation. SuppressFactoryMethodAsInit = 0x01, }; /// Options that control the import of names in importFullName. typedef OptionSet ImportNameOptions; /// Imports the full name of the given Clang declaration into Swift. /// /// Note that this may result in a name very different from the Clang name, /// so it should not be used when referencing Clang symbols. /// /// \param D The Clang declaration whose name should be imported. ImportedName importFullName(const clang::NamedDecl *D, ImportNameOptions options = None, clang::Sema *clangSemaOverride = nullptr); /// Imports the name of the given Clang macro into Swift. Identifier importMacroName(const clang::IdentifierInfo *clangIdentifier, const clang::MacroInfo *macro, clang::ASTContext &clangCtx); /// \brief Import the given Clang identifier into Swift. /// /// \param identifier The Clang identifier to map into Swift. /// /// \param removePrefix The prefix to remove from the Clang name to produce /// the Swift name. If the Clang name does not start with this prefix, /// nothing is removed. Identifier importIdentifier(const clang::IdentifierInfo *identifier, StringRef removePrefix = ""); /// Import an Objective-C selector. ObjCSelector importSelector(clang::Selector selector); /// Import a Swift name as a Clang selector. clang::Selector exportSelector(DeclName name, bool allowSimpleName = true); /// Export a Swift Objective-C selector as a Clang Objective-C selector. clang::Selector exportSelector(ObjCSelector selector); /// \brief Import the given Swift source location into Clang. clang::SourceLocation exportSourceLoc(SourceLoc loc); /// \brief Import the given Clang source location into Swift. SourceLoc importSourceLoc(clang::SourceLocation loc); /// \brief Import the given Clang source range into Swift. SourceRange importSourceRange(clang::SourceRange loc); /// \brief Import the given Clang preprocessor macro as a Swift value decl. /// /// \returns The imported declaration, or null if the macro could not be /// translated into Swift. ValueDecl *importMacro(Identifier name, clang::MacroInfo *macro); /// Import attributes from the given Clang declaration to its Swift /// equivalent. /// /// \param ClangDecl The decl being imported. /// \param MappedDecl The decl to attach attributes to. /// \param NewContext If present, the Clang node for the context the decl is /// being imported into, which may affect info from API notes. void importAttributes(const clang::NamedDecl *ClangDecl, Decl *MappedDecl, const clang::ObjCContainerDecl *NewContext = nullptr); /// If we already imported a given decl, return the corresponding Swift decl. /// Otherwise, return nullptr. Decl *importDeclCached(const clang::NamedDecl *ClangDecl); Decl *importDeclImpl(const clang::NamedDecl *ClangDecl, bool &TypedefIsSuperfluous, bool &HadForwardDeclaration); Decl *importDeclAndCacheImpl(const clang::NamedDecl *ClangDecl, bool SuperfluousTypedefsAreTransparent); /// \brief Same as \c importDeclReal, but for use inside importer /// implementation. /// /// Unlike \c importDeclReal, this function for convenience transparently /// looks through superfluous typedefs and returns the imported underlying /// decl in that case. Decl *importDecl(const clang::NamedDecl *ClangDecl) { return importDeclAndCacheImpl(ClangDecl, /*SuperfluousTypedefsAreTransparent=*/true); } /// \brief Import the given Clang declaration into Swift. Use this function /// outside of the importer implementation, when importing a decl requested by /// Swift code. /// /// \returns The imported declaration, or null if this declaration could /// not be represented in Swift. Decl *importDeclReal(const clang::NamedDecl *ClangDecl) { return importDeclAndCacheImpl(ClangDecl, /*SuperfluousTypedefsAreTransparent=*/false); } /// \brief Import a cloned version of the given declaration, which is part of /// an Objective-C protocol and currently must be a method or property, into /// the given declaration context. /// /// \returns The imported declaration, or null if this declaration could not /// be represented in Swift. Decl *importMirroredDecl(const clang::NamedDecl *decl, DeclContext *dc, ProtocolDecl *proto); /// \brief Import the given Clang declaration context into Swift. /// /// Usually one will use \c importDeclContextOf instead. /// /// \returns The imported declaration context, or null if it could not /// be converted. DeclContext *importDeclContextImpl(const clang::DeclContext *dc); /// \brief Import the declaration context of a given Clang declaration into /// Swift. /// /// \param context The effective context as determined by importFullName. /// /// \returns The imported declaration context, or null if it could not /// be converted. DeclContext *importDeclContextOf(const clang::Decl *D, EffectiveClangContext context); /// \brief Import the declaration context of a given Clang /// declaration into Swift. DeclContext *importDeclContextOf(const clang::Decl *D) { return importDeclContextOf( D, const_cast(D->getDeclContext())); } /// \brief Create a new named constant with the given value. /// /// \param name The name of the constant. /// \param dc The declaration context into which the name will be introduced. /// \param type The type of the named constant. /// \param value The value of the named constant. /// \param convertKind How to convert the constant to the given type. /// \param isStatic Whether the constant should be a static member of \p dc. ValueDecl *createConstant(Identifier name, DeclContext *dc, Type type, const clang::APValue &value, ConstantConvertKind convertKind, bool isStatic, ClangNode ClangN); /// \brief Create a new named constant with the given value. /// /// \param name The name of the constant. /// \param dc The declaration context into which the name will be introduced. /// \param type The type of the named constant. /// \param value The value of the named constant. /// \param convertKind How to convert the constant to the given type. /// \param isStatic Whether the constant should be a static member of \p dc. ValueDecl *createConstant(Identifier name, DeclContext *dc, Type type, StringRef value, ConstantConvertKind convertKind, bool isStatic, ClangNode ClangN); /// \brief Create a new named constant using the given expression. /// /// \param name The name of the constant. /// \param dc The declaration context into which the name will be introduced. /// \param type The type of the named constant. /// \param valueExpr An expression to use as the value of the constant. /// \param convertKind How to convert the constant to the given type. /// \param isStatic Whether the constant should be a static member of \p dc. ValueDecl *createConstant(Identifier name, DeclContext *dc, Type type, Expr *valueExpr, ConstantConvertKind convertKind, bool isStatic, ClangNode ClangN); /// \brief Add "Unavailable" annotation to the swift declaration. void markUnavailable(ValueDecl *decl, StringRef unavailabilityMsg); /// \brief Create a decl with error type and an "unavailable" attribute on it /// with the specified message. ValueDecl *createUnavailableDecl(Identifier name, DeclContext *dc, Type type, StringRef UnavailableMessage, bool isStatic, ClangNode ClangN); /// \brief Retrieve the standard library module. Module *getStdlibModule(); /// \brief Retrieve the named module. /// /// \param name The name of the module. /// /// \returns The named module, or null if the module has not been imported. Module *getNamedModule(StringRef name); /// \brief Returns the "Foundation" module, if it can be loaded. /// /// After this has been called, the Foundation module will or won't be loaded /// into the ASTContext. Module *tryLoadFoundationModule(); /// \brief Returns the "SIMD" module, if it can be loaded. /// /// After this has been called, the SIMD module will or won't be loaded /// into the ASTContext. Module *tryLoadSIMDModule(); /// \brief Retrieves the Swift wrapper for the given Clang module, creating /// it if necessary. ClangModuleUnit *getWrapperForModule(ClangImporter &importer, const clang::Module *underlying); /// \brief Constructs a Swift module for the given Clang module. Module *finishLoadingClangModule(ClangImporter &importer, const clang::Module *clangModule, bool preferAdapter); /// \brief Retrieve the named Swift type, e.g., Int32. /// /// \param module The name of the module in which the type should occur. /// /// \param name The name of the type to find. /// /// \returns The named type, or null if the type could not be found. Type getNamedSwiftType(Module *module, StringRef name); /// \brief Retrieve a specialization of the named Swift type, e.g., /// UnsafeMutablePointer. /// /// \param module The name of the module in which the type should occur. /// /// \param name The name of the type to find. /// /// \param args The arguments to use in the specialization. /// /// \returns The named type, or null if the type could not be found. Type getNamedSwiftTypeSpecialization(Module *module, StringRef name, ArrayRef args); /// \brief Retrieve the NSObject type. Type getNSObjectType(); /// \brief Retrieve the NSObject protocol type. Type getNSObjectProtocolType(); /// \brief Retrieve the NSCopying protocol type. Type getNSCopyingType(); /// \brief Retrieve the CFStringRef typealias. Type getCFStringRefType(); /// \brief Determines whether the given type matches an implicit type /// bound of "NSObject", which is used to validate NSDictionary/NSSet. bool matchesNSObjectBound(Type type); /// \brief Look up and attempt to import a Clang declaration with /// the given name. Decl *importDeclByName(StringRef name); /// \brief Import the given Clang type into Swift. /// /// \param type The Clang type to import. /// /// \param kind The kind of type import we're performing. /// /// \param allowNSUIntegerAsInt If true, NSUInteger will be imported as Int /// in certain contexts. If false, it will always be imported as UInt. /// /// \param canFullyBridgeTypes True if we can bridge types losslessly. /// This is an additional guarantee on top of the ImportTypeKind /// cases that allow bridging, and applies to the entire type. /// /// \returns The imported type, or null if this type could /// not be represented in Swift. Type importType(clang::QualType type, ImportTypeKind kind, bool allowNSUIntegerAsInt, bool canFullyBridgeTypes, OptionalTypeKind optional = OTK_ImplicitlyUnwrappedOptional); /// \brief Import the given function type. /// /// This routine should be preferred when importing function types for /// which we have actual function parameters, e.g., when dealing with a /// function declaration, because it produces a function type whose input /// tuple has argument names. /// /// \param clangDecl The underlying declaration, if any; should only be /// considered for any attributes it might carry. /// \param resultType The result type of the function. /// \param params The parameter types to the function. /// \param isVariadic Whether the function is variadic. /// \param isNoReturn Whether the function is noreturn. /// \param parameterList The parameters visible inside the function body. /// /// \returns the imported function type, or null if the type cannot be /// imported. Type importFunctionType(const clang::FunctionDecl *clangDecl, clang::QualType resultType, ArrayRef params, bool isVariadic, bool isNoReturn, bool isFromSystemModule, bool hasCustomName, ParameterList *¶meterList, DeclName &name); Type importPropertyType(const clang::ObjCPropertyDecl *clangDecl, bool isFromSystemModule); /// Attempt to infer a default argument for a parameter with the /// given Clang \c type, \c baseName, and optionality. DefaultArgumentKind inferDefaultArgument(clang::Preprocessor &pp, clang::QualType type, OptionalTypeKind clangOptionality, Identifier baseName, unsigned numParams, StringRef argumentLabel, bool isFirstParameter, bool isLastParameter); /// Retrieve a bit vector containing the non-null argument /// annotations for the given declaration. llvm::SmallBitVector getNonNullArgs( const clang::Decl *decl, ArrayRef params); /// \brief Import the type of an Objective-C method. /// /// This routine should be preferred when importing function types for /// which we have actual function parameters, e.g., when dealing with a /// function declaration, because it produces a function type whose input /// tuple has argument names. /// /// \param clangDecl The underlying declaration, if any; should only be /// considered for any attributes it might carry. /// \param resultType The result type of the function. /// \param params The parameter types to the function. /// \param isVariadic Whether the function is variadic. /// \param isNoReturn Whether the function is noreturn. /// \param isFromSystemModule Whether to apply special rules that only apply /// to system APIs. /// \param bodyParams The patterns visible inside the function body. /// whether the created arg/body patterns are different (selector-style). /// \param importedName The name of the imported method. /// \param errorConvention Information about the method's error conventions. /// \param kind Controls whether we're building a type for a method that /// needs special handling. /// /// \returns the imported function type, or null if the type cannot be /// imported. Type importMethodType(const clang::ObjCMethodDecl *clangDecl, clang::QualType resultType, ArrayRef params, bool isVariadic, bool isNoReturn, bool isFromSystemModule, ParameterList **bodyParams, ImportedName importedName, DeclName &name, Optional &errorConvention, SpecialMethodKind kind); /// \brief Determine whether the given typedef-name is "special", meaning /// that it has performed some non-trivial mapping of its underlying type /// based on the name of the typedef. Optional getSpecialTypedefKind(clang::TypedefNameDecl *decl); /// \brief Look up a name, accepting only typedef results. const clang::TypedefNameDecl *lookupTypedef(clang::DeclarationName); /// \brief Return whether a global of the given type should be imported as a /// 'let' declaration as opposed to 'var'. bool shouldImportGlobalAsLet(clang::QualType type); LazyResolver *getTypeResolver() const { return typeResolver.getPointer(); } void setTypeResolver(LazyResolver *newResolver) { assert((!typeResolver.getPointer() || !newResolver) && "already have a type resolver"); typeResolver.setPointerAndInt(newResolver, true); } bool hasBegunTypeChecking() const { return typeResolver.getInt(); } bool hasFinishedTypeChecking() const { return hasBegunTypeChecking() && !getTypeResolver(); } /// Allocate a new delayed conformance ID with the given set of /// conformances. unsigned allocateDelayedConformance( SmallVector &&conformances) { unsigned id = NextDelayedConformanceID++; DelayedConformances[id] = std::move(conformances); return id; } /// Take the delayed conformances associated with the given id. SmallVector takeDelayedConformance(unsigned id) { auto conformances = DelayedConformances.find(id); SmallVector result = std::move(conformances->second); DelayedConformances.erase(conformances); return result; } /// Record the set of imported protocols for the given declaration, /// to be used by member loading. /// /// FIXME: This is all a hack; we should have lazier deserialization /// of protocols separate from their conformances. void recordImportedProtocols(const Decl *decl, ArrayRef protocols) { if (protocols.empty()) return; auto &recorded = ImportedProtocols[decl]; recorded.insert(recorded.end(), protocols.begin(), protocols.end()); } /// Retrieve the imported protocols for the given declaration. SmallVector takeImportedProtocols(const Decl *decl) { SmallVector result; auto known = ImportedProtocols.find(decl); if (known != ImportedProtocols.end()) { result = std::move(known->second); ImportedProtocols.erase(known); } return result; } virtual void loadAllMembers(Decl *D, uint64_t unused) override; void loadAllConformances( const Decl *D, uint64_t contextData, SmallVectorImpl &Conformances) override; template DeclTy *createDeclWithClangNode(ClangNode ClangN, Targs &&... Args) { assert(ClangN); void *DeclPtr = allocateMemoryForDecl(SwiftContext, sizeof(DeclTy), true); auto D = ::new (DeclPtr) DeclTy(std::forward(Args)...); D->setClangNode(ClangN); D->setEarlyAttrValidation(true); if (auto VD = dyn_cast(D)) VD->setAccessibility(Accessibility::Public); if (auto ASD = dyn_cast(D)) ASD->setSetterAccessibility(Accessibility::Public); return D; } /// Find the lookup table that corresponds to the given Clang module. /// /// \param clangModule The module, or null to indicate that we're talking /// about the directly-parsed headers. SwiftLookupTable *findLookupTable(const clang::Module *clangModule); /// Look for namespace-scope values with the given name in the given /// Swift lookup table. void lookupValue(SwiftLookupTable &table, DeclName name, VisibleDeclConsumer &consumer); /// Look for namespace-scope values in the given Swift lookup table. void lookupVisibleDecls(SwiftLookupTable &table, VisibleDeclConsumer &consumer); /// Look for Objective-C members with the given name in the given /// Swift lookup table. void lookupObjCMembers(SwiftLookupTable &table, DeclName name, VisibleDeclConsumer &consumer); /// Look for all Objective-C members in the given Swift lookup table. void lookupAllObjCMembers(SwiftLookupTable &table, VisibleDeclConsumer &consumer); /// Dump the Swift-specific name lookup tables we generate. void dumpSwiftLookupTables(); }; } #endif