mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This is more of rdar://problem/24869070; StringRefs are leaking out of importFullName still, in a DenseMap that can get deallocated. When we cache this data, put them in "permanent" (Swift ASTContext) storage.
1368 lines
50 KiB
C++
1368 lines
50 KiB
C++
//===--- 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 <set>
|
|
|
|
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<NSFoo?>, 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<clang::ModuleFileExtensionWriter>
|
|
createExtensionWriter(clang::ASTWriter &writer) override;
|
|
|
|
std::unique_ptr<clang::ModuleFileExtensionReader>
|
|
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 =
|
|
"<swift-imported-modules>";
|
|
constexpr static const char * const bridgingHeaderBufferName =
|
|
"<bridging-header-import>";
|
|
|
|
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<std::unique_ptr<SwiftLookupTable>> 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<clang::CompilerInvocation> Invocation;
|
|
|
|
/// \brief Clang compiler instance, which is used to actually load Clang
|
|
/// modules.
|
|
std::unique_ptr<clang::CompilerInstance> Instance;
|
|
|
|
/// \brief Clang compiler action, which is used to actually run the
|
|
/// parser.
|
|
std::unique_ptr<clang::FrontendAction> Action;
|
|
|
|
/// \brief Clang parser, which is used to load textual headers.
|
|
std::unique_ptr<clang::Parser> Parser;
|
|
|
|
/// \brief Clang parser, which is used to load textual headers.
|
|
std::unique_ptr<clang::MangleContext> 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<LazyResolver *, 1, bool> typeResolver;
|
|
|
|
public:
|
|
/// \brief Mapping of already-imported declarations.
|
|
llvm::DenseMap<const clang::Decl *, Decl *> 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<const clang::TypedefNameDecl *, MappedTypeNameKind, 16>
|
|
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<std::string> 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<const clang::Decl *> SuperfluousTypedefs;
|
|
/// Tag decls whose typedefs were imported instead.
|
|
///
|
|
/// \sa SuperfluousTypedefs
|
|
llvm::DenseSet<const clang::Decl *> DeclsWithSuperfluousTypedefs;
|
|
|
|
/// \brief Mapping of already-imported declarations from protocols, which
|
|
/// can (and do) get replicated into classes.
|
|
llvm::DenseMap<std::pair<const clang::Decl *, DeclContext *>, 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<Identifier,
|
|
SmallVector<std::pair<clang::MacroInfo *, ValueDecl *>, 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<std::pair<ObjCSelector, char>, 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<ExtensionDecl *, 4> *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<importer::EnumInfo> enumInfos;
|
|
|
|
public:
|
|
/// \brief Keep track of subscript declarations based on getter/setter
|
|
/// pairs.
|
|
llvm::DenseMap<std::pair<FuncDecl *, FuncDecl *>, SubscriptDecl *> Subscripts;
|
|
|
|
/// Retrieve the key to use when looking for enum information.
|
|
StringRef getEnumInfoKey(const clang::EnumDecl *decl,
|
|
SmallVectorImpl<char> &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<const clang::EnumDecl *, llvm::APSInt>;
|
|
using PointerInfo = llvm::DenseMapInfo<const clang::EnumDecl *>;
|
|
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<std::pair<const clang::EnumDecl *, llvm::APSInt>,
|
|
EnumElementDecl *,
|
|
EnumConstantDenseMapInfo>
|
|
EnumConstantValues;
|
|
|
|
/// \brief Keep track of initializer declarations that correspond to
|
|
/// imported methods.
|
|
llvm::DenseMap<std::pair<const clang::ObjCMethodDecl *, DeclContext *>,
|
|
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<Decl *, ValueDecl *> 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<ClangModuleUnit *, 1, bool>;
|
|
|
|
public:
|
|
/// A map from Clang modules to their Swift wrapper modules.
|
|
llvm::SmallDenseMap<const clang::Module *, ModuleInitPair, 16> ModuleWrappers;
|
|
|
|
/// The module unit that contains declarations from imported headers.
|
|
ClangModuleUnit *ImportedHeaderUnit = nullptr;
|
|
|
|
/// The modules re-exported by imported headers.
|
|
llvm::SmallVector<Module::ImportedModule, 8> ImportedHeaderExports;
|
|
|
|
/// The modules that requested imported headers.
|
|
///
|
|
/// These are used to look up Swift classes forward-declared with \@class.
|
|
TinyPtrVector<Module *> 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<Module *> checkedFoundationModule, checkedSIMDModule;
|
|
|
|
/// External Decls that we have imported but not passed to the ASTContext yet.
|
|
SmallVector<Decl *, 4> RegisteredExternalDecls;
|
|
|
|
/// Protocol conformances that may be missing witnesses.
|
|
SmallVector<NormalProtocolConformance *, 4> DelayedProtocolConformances;
|
|
|
|
unsigned NumCurrentImportingEntities = 0;
|
|
|
|
/// Mapping from delayed conformance IDs to the set of delayed
|
|
/// protocol conformances.
|
|
llvm::DenseMap<unsigned, SmallVector<ProtocolConformance *, 4>>
|
|
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<const Decl *, SmallVector<ProtocolDecl *, 4>>
|
|
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<bool (StringRef PlatformName)>
|
|
PlatformAvailabilityFilter;
|
|
|
|
/// A predicate that indicates if the given platform version should
|
|
/// should be included in the cutoff of deprecated APIs marked unavailable.
|
|
std::function<bool (unsigned major, llvm::Optional<unsigned> 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<clang::Decl *> BridgeHeaderTopLevelDecls;
|
|
std::vector<llvm::PointerUnion<clang::ImportDecl *, ImportDecl *>>
|
|
BridgeHeaderTopLevelImports;
|
|
|
|
/// Tracks macro definitions from the bridging header.
|
|
std::vector<clang::IdentifierInfo *> BridgeHeaderMacros;
|
|
/// Tracks included headers from the bridging header.
|
|
llvm::DenseSet<const clang::FileEntry *> 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<llvm::MemoryBuffer> 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<const clang::Decl *>
|
|
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<clang::Module *>
|
|
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<clang::Module *>
|
|
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<StringRef> &argumentNames,
|
|
ArrayRef<const clang::ParmVarDecl *> params,
|
|
clang::QualType resultType,
|
|
const clang::DeclContext *dc,
|
|
const llvm::SmallBitVector &nonNullArgs,
|
|
Optional<unsigned> 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<ImportedErrorInfo> 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<bool>(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<ImportNameFlags> 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<clang::DeclContext *>(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<T>.
|
|
///
|
|
/// \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<Type> 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<const clang::ParmVarDecl *> 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<const clang::ParmVarDecl *> 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<const clang::ParmVarDecl *> params,
|
|
bool isVariadic, bool isNoReturn,
|
|
bool isFromSystemModule,
|
|
ParameterList **bodyParams,
|
|
ImportedName importedName,
|
|
DeclName &name,
|
|
Optional<ForeignErrorConvention> &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<MappedTypeNameKind>
|
|
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<ProtocolConformance *, 4> &&conformances) {
|
|
unsigned id = NextDelayedConformanceID++;
|
|
DelayedConformances[id] = std::move(conformances);
|
|
return id;
|
|
}
|
|
|
|
/// Take the delayed conformances associated with the given id.
|
|
SmallVector<ProtocolConformance *, 4> takeDelayedConformance(unsigned id) {
|
|
auto conformances = DelayedConformances.find(id);
|
|
SmallVector<ProtocolConformance *, 4> 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<ProtocolDecl *> 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<ProtocolDecl *, 4> takeImportedProtocols(const Decl *decl) {
|
|
SmallVector<ProtocolDecl *, 4> 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<ProtocolConformance *> &Conformances) override;
|
|
|
|
template <typename DeclTy, typename ...Targs>
|
|
DeclTy *createDeclWithClangNode(ClangNode ClangN, Targs &&... Args) {
|
|
assert(ClangN);
|
|
void *DeclPtr = allocateMemoryForDecl<DeclTy>(SwiftContext, sizeof(DeclTy),
|
|
true);
|
|
auto D = ::new (DeclPtr) DeclTy(std::forward<Targs>(Args)...);
|
|
D->setClangNode(ClangN);
|
|
D->setEarlyAttrValidation(true);
|
|
if (auto VD = dyn_cast<ValueDecl>(D))
|
|
VD->setAccessibility(Accessibility::Public);
|
|
if (auto ASD = dyn_cast<AbstractStorageDecl>(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
|