blob: a0c2ba5e6f8c60c4ec75d62ec2ac52de72e6eb9d [file] [log] [blame]
//===--- Validation.h - Validation / errors for serialization ---*- 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_SERIALIZATION_VALIDATION_H
#define SWIFT_SERIALIZATION_VALIDATION_H
#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.
Valid,
/// The module file format is too old to be used by this version of the
/// compiler.
FormatTooOld,
/// The module file format is too new to be used by this version of the
/// compiler.
FormatTooNew,
/// The module file depends on another module that can't be loaded.
MissingDependency,
/// The module file is an overlay for a Clang module, which can't be found.
MissingShadowedModule,
/// The module file depends on a module that is still being loaded, i.e.
/// there is a circular dependency.
CircularDependency,
/// The module file depends on a bridging header that can't be loaded.
FailedToLoadBridgingHeader,
/// The module file is malformed in some way.
Malformed,
/// The module documentation file is malformed in some way.
MalformedDocumentation,
/// The module file's name does not match the module it is being loaded
/// into.
NameMismatch,
/// The module file was built for a different target platform.
TargetIncompatible,
/// The module file was built for a target newer than the current target.
TargetTooNew
};
/// 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 = {};
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;
} Bits;
public:
ExtendedValidationInfo() : Bits() {}
StringRef getSDKPath() const { return SDKPath; }
void setSDKPath(StringRef path) {
assert(SDKPath.empty());
SDKPath = path;
}
ArrayRef<StringRef> getExtraClangImporterOptions() const {
return ExtraClangImporterOpts;
}
void addExtraClangImporterOption(StringRef option) {
ExtraClangImporterOpts.push_back(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 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);
}
};
/// 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 =
nullptr);
/// 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
/// SerializedModuleLoader::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,
const ExtendedValidationInfo &extendedInfo, StringRef moduleBufferID,
StringRef moduleDocBufferID, ModuleFile *loadedModuleFile,
Identifier ModuleName);
} // end namespace serialization
} // end namespace swift
#endif