| //===--- 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. |
| MissingUnderlyingModule, |
| |
| /// 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 = {}; |
| 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; |
| 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 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 = |
| 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 |
| /// 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 |
| |
| #endif |