blob: 4bf95087852b2683586bcc0155b8bb83870b45cc [file] [log] [blame]
//===--- Validation.h - Validation / errors for serialization ---*- C++ -*-===//
// This source file is part of the 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 for license information
// See for the list of Swift project authors
#include "swift/Basic/LLVM.h"
#include "swift/Serialization/SerializationOptions.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
namespace swift {
class ModuleFile;
enum class ResilienceStrategy : unsigned;
namespace serialization {
/// Describes whether a serialized module can be used by this compiler.
enum class Status {
/// The module is valid.
/// The module file format is too old to be used by this version of the
/// compiler.
/// The module file format is too new to be used by this version of the
/// compiler.
/// The module file depends on another module that can't be loaded.
/// The module file is an overlay for a Clang module, which can't be found.
/// The module file depends on a module that is still being loaded, i.e.
/// there is a circular dependency.
/// The module file depends on a bridging header that can't be loaded.
/// The module file is malformed in some way.
/// The module documentation file is malformed in some way.
/// The module file's name does not match the module it is being loaded
/// into.
/// The module file was built for a different target platform.
/// The module file was built for a target newer than the current target.
/// Returns true if the data looks like it contains a serialized AST.
bool isSerializedAST(StringRef data);
/// \see validateSerializedAST()
struct ValidationInfo {
StringRef name = {};
StringRef targetTriple = {};
StringRef shortVersion = {};
StringRef miscVersion = {};
version::Version compatibilityVersion = {};
size_t bytes = 0;
Status status = Status::Malformed;
/// A collection of options that can be used to set up a new AST context
/// before it has been created.
/// Note that this is intended to be a transient data structure; as such,
/// <strong>none of the string values added to it are copied</strong>.
/// \sa validateSerializedAST()
class ExtendedValidationInfo {
SmallVector<StringRef, 4> ExtraClangImporterOpts;
StringRef SDKPath;
struct {
unsigned ArePrivateImportsEnabled : 1;
unsigned IsSIB : 1;
unsigned IsTestable : 1;
unsigned ResilienceStrategy : 2;
unsigned IsImplicitDynamicEnabled : 1;
unsigned IsAllowModuleWithCompilerErrorsEnabled : 1;
} Bits;
ExtendedValidationInfo() : Bits() {}
StringRef getSDKPath() const { return SDKPath; }
void setSDKPath(StringRef path) {
SDKPath = path;
ArrayRef<StringRef> getExtraClangImporterOptions() const {
return ExtraClangImporterOpts;
void addExtraClangImporterOption(StringRef option) {
bool isSIB() const { return Bits.IsSIB; }
void setIsSIB(bool val) {
Bits.IsSIB = val;
bool arePrivateImportsEnabled() { return Bits.ArePrivateImportsEnabled; }
void setPrivateImportsEnabled(bool enabled) {
Bits.ArePrivateImportsEnabled = enabled;
bool isImplicitDynamicEnabled() { return Bits.IsImplicitDynamicEnabled; }
void setImplicitDynamicEnabled(bool val) {
Bits.IsImplicitDynamicEnabled = val;
bool isTestable() const { return Bits.IsTestable; }
void setIsTestable(bool val) {
Bits.IsTestable = val;
ResilienceStrategy getResilienceStrategy() const {
return ResilienceStrategy(Bits.ResilienceStrategy);
void setResilienceStrategy(ResilienceStrategy resilience) {
Bits.ResilienceStrategy = unsigned(resilience);
bool isAllowModuleWithCompilerErrorsEnabled() {
return Bits.IsAllowModuleWithCompilerErrorsEnabled;
void setAllowModuleWithCompilerErrorsEnabled(bool val) {
Bits.IsAllowModuleWithCompilerErrorsEnabled = val;
/// Returns info about the serialized AST in the given data.
/// If the returned status is anything but Status::Valid, the serialized data
/// cannot be loaded by this version of the compiler. If the returned size is
/// non-zero, it's possible to skip over this module's data, in case there is
/// more data in the buffer. The returned name, which may be empty, directly
/// points into the given data buffer.
/// Note that this does not actually try to load the module or validate any
/// of its dependencies; it only checks that it /can/ be loaded.
/// \param data A buffer containing the serialized AST. Result information
/// refers directly into this buffer.
/// \param[out] extendedInfo If present, will be populated with additional
/// compilation options serialized into the AST at build time that may be
/// necessary to load it properly.
/// \param[out] dependencies If present, will be populated with list of
/// input files the module depends on, if present in INPUT_BLOCK.
ValidationInfo validateSerializedAST(
StringRef data, ExtendedValidationInfo *extendedInfo = nullptr,
SmallVectorImpl<SerializationOptions::FileDependency> *dependencies =
/// Emit diagnostics explaining a failure to load a serialized AST.
/// - \p Ctx is an AST context through which any diagnostics are surfaced.
/// - \p diagLoc is the (possibly invalid) location used in the diagnostics.
/// - \p loadInfo and \p extendedInfo describe the attempt to load an AST
/// (\ref validateSerializedAST). Note that loadInfo.Status must not be
/// Status::Valid.
/// - \p moduleBufferID and \p moduleDocBufferID are the buffer identifiers
/// of the module input and doc input buffers respectively (\ref
/// SerializedModuleLoaderBase::loadAST, \ref ModuleFile::load).
/// - \p loadedModuleFile is an invalid loaded module.
/// - \p ModuleName is the name used to refer to the module in diagnostics.
void diagnoseSerializedASTLoadFailure(
ASTContext &Ctx, SourceLoc diagLoc, const ValidationInfo &loadInfo,
StringRef moduleBufferID, StringRef moduleDocBufferID,
ModuleFile *loadedModuleFile, Identifier ModuleName);
} // end namespace serialization
} // end namespace swift