blob: b02bac076b25a09ddb15cc1383c3f7c5b18471ac [file] [log] [blame]
//===--- ClangModuleLoader.h - Clang Module Loader Interface ----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_CLANG_MODULE_LOADER_H
#define SWIFT_AST_CLANG_MODULE_LOADER_H
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/Basic/TaggedUnion.h"
#include "clang/AST/DeclTemplate.h"
namespace clang {
class ASTContext;
class CompilerInstance;
class Decl;
class Module;
class Preprocessor;
class Sema;
class TargetInfo;
class Type;
} // namespace clang
namespace swift {
class Decl;
class DeclContext;
class VisibleDeclConsumer;
/// Represents the different namespaces for types in C.
///
/// A simplified version of clang::Sema::LookupKind.
enum class ClangTypeKind {
Typedef,
ObjCClass = Typedef,
/// Structs, enums, and unions.
Tag,
ObjCProtocol,
};
/// A path for serializing a declaration.
class StableSerializationPath {
public:
struct ExternalPath {
enum ComponentKind {
/// A named record type (but not a template specialization)
Record,
/// A named enum type
Enum,
/// A C++ namespace
Namespace,
/// A typedef
Typedef,
/// A typedef's anonymous tag declaration. Identifier is empty.
TypedefAnonDecl,
/// An Objective-C interface.
ObjCInterface,
/// An Objective-C protocol.
ObjCProtocol,
};
static bool requiresIdentifier(ComponentKind kind) {
return kind != TypedefAnonDecl;
}
SmallVector<std::pair<ComponentKind, Identifier>, 2> Path;
void add(ComponentKind kind, Identifier name) {
Path.push_back({kind, name});
}
};
private:
TaggedUnion<void, const Decl *, ExternalPath> Union;
public:
StableSerializationPath() {}
StableSerializationPath(const Decl *d) : Union(d) {}
StableSerializationPath(ExternalPath ext) : Union(ext) {}
explicit operator bool() const { return !Union.empty(); }
bool isSwiftDecl() const { return Union.isa<const Decl*>(); }
const Decl *getSwiftDecl() const {
assert(isSwiftDecl());
return Union.get<const Decl*>();
}
bool isExternalPath() const { return Union.isa<ExternalPath>(); }
const ExternalPath &getExternalPath() const {
assert(isExternalPath());
return Union.get<ExternalPath>();
}
SWIFT_DEBUG_DUMP;
void dump(raw_ostream &os) const;
};
class ClangModuleLoader : public ModuleLoader {
private:
virtual void anchor() override;
protected:
using ModuleLoader::ModuleLoader;
public:
virtual clang::TargetInfo &getTargetInfo() const = 0;
virtual clang::ASTContext &getClangASTContext() const = 0;
virtual clang::Preprocessor &getClangPreprocessor() const = 0;
virtual clang::Sema &getClangSema() const = 0;
virtual const clang::CompilerInstance &getClangInstance() const = 0;
virtual void printStatistics() const = 0;
/// Returns the module that contains imports and declarations from all loaded
/// Objective-C header files.
virtual ModuleDecl *getImportedHeaderModule() const = 0;
/// Retrieves the Swift wrapper for the given Clang module, creating
/// it if necessary.
virtual ModuleDecl *
getWrapperForModule(const clang::Module *mod,
bool returnOverlayIfPossible = false) const = 0;
/// Adds a new search path to the Clang CompilerInstance, as if specified with
/// -I or -F.
///
/// \returns true if there was an error adding the search path.
virtual bool addSearchPath(StringRef newSearchPath, bool isFramework,
bool isSystem) = 0;
/// Determine whether \c overlayDC is within an overlay module for the
/// imported context enclosing \c importedDC.
///
/// This routine is used for various hacks that are only permitted within
/// overlays of imported modules, e.g., Objective-C bridging conformances.
virtual bool
isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
const DeclContext *importedDC) = 0;
/// Look for declarations associated with the given name.
///
/// \param name The name we're searching for.
virtual void lookupValue(DeclName name, VisibleDeclConsumer &consumer) = 0;
/// Look up a type declaration by its Clang name.
///
/// Note that this method does no filtering. If it finds the type in a loaded
/// module, it returns it. This is intended for use in reflection / debugging
/// contexts where access is not a problem.
virtual void
lookupTypeDecl(StringRef clangName, ClangTypeKind kind,
llvm::function_ref<void(TypeDecl *)> receiver) = 0;
/// Look up type a declaration synthesized by the Clang importer itself, using
/// a "related entity kind" to determine which type it should be. For example,
/// this can be used to find the synthesized error struct for an
/// NS_ERROR_ENUM.
///
/// Note that this method does no filtering. If it finds the type in a loaded
/// module, it returns it. This is intended for use in reflection / debugging
/// contexts where access is not a problem.
virtual void
lookupRelatedEntity(StringRef clangName, ClangTypeKind kind,
StringRef relatedEntityKind,
llvm::function_ref<void(TypeDecl *)> receiver) = 0;
/// Try to parse the string as a Clang function type.
///
/// Returns null if there was a parsing failure.
virtual const clang::Type *parseClangFunctionType(StringRef type,
SourceLoc loc) const = 0;
/// Print the Clang type.
virtual void printClangType(const clang::Type *type,
llvm::raw_ostream &os) const = 0;
/// Try to find a stable serialization path for the given declaration,
/// if there is one.
virtual StableSerializationPath
findStableSerializationPath(const clang::Decl *decl) const = 0;
/// Try to resolve a stable serialization path down to the original
/// declaration.
virtual const clang::Decl *
resolveStableSerializationPath(const StableSerializationPath &path) const = 0;
/// Determine whether the given type is serializable.
///
/// If \c checkCanonical is true, checks the canonical type,
/// not the given possibly-sugared type. In general:
/// - non-canonical representations should be preserving the
/// sugared type even if it isn't serializable, since that
/// maintains greater source fidelity;
/// - semantic checks need to be checking the serializability
/// of the canonical type, since it's always potentially
/// necessary to serialize that (e.g. in SIL); and
/// - serializers can try to serialize the sugared type to
/// maintain source fidelity and just fall back on the canonical
/// type if that's not possible.
///
/// The expectation here is that this predicate is meaningful
/// independent of the actual form of serialization: the types
/// that we can't reliably binary-serialize without an absolute
/// Clang AST cross-reference are the same types that won't
/// reliably round-trip through a textual format. At the very
/// least, it's probably best to use conservative predicates
/// that work both ways so that language behavior doesn't differ
/// based on subtleties like the target module interface format.
virtual bool isSerializable(const clang::Type *type,
bool checkCanonical) const = 0;
virtual clang::FunctionDecl *
instantiateCXXFunctionTemplate(ASTContext &ctx,
clang::FunctionTemplateDecl *func,
SubstitutionMap subst) = 0;
};
/// Used to describe a template instantiation error.
struct TemplateInstantiationError {
/// Generic types that could not be converted to QualTypes using the
/// ClangTypeConverter.
SmallVector<Type, 4> failedTypes;
};
} // namespace swift
#endif // LLVM_SWIFT_AST_CLANG_MODULE_LOADER_H