Files
swift-mirror/include/swift/ClangImporter/SwiftAbstractBasicWriter.h
John McCall faee21b626 Implement Swift serialization and deserialization of Clang types.
As part of this, we have to change the type export rules to
prevent `@convention(c)` function types from being used in
exported interfaces if they aren't serializable.  This is a
more conservative version of the original rule I had, which
was to import such function-pointer types as opaque pointers.
That rule would've completely prevented importing function-pointer
types defined in bridging headers and so simply doesn't work,
so we're left trying to catch the unsupportable cases
retroactively.  This has the unfortunate consequence that we
can't necessarily serialize the internal state of the compiler,
but that was already true due to normal type uses of aggregate
types from bridging headers; if we can teach the compiler to
reliably serialize such types, we should be able to use the
same mechanisms for function types.

This PR doesn't flip the switch to use Clang function types
by default, so many of the clang-function-type-serialization
FIXMEs are still in place.
2020-02-06 22:09:00 -05:00

91 lines
3.1 KiB
C++

//===- SwiftAbstractBasicWriter.h - Clang serialization adapter -*- 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
//
//===----------------------------------------------------------------------===//
//
// This file provides an intermediate CRTP class which implements most of
// Clang's AbstractBasicWriter interface, allowing largely the same logic
// to be used for both the importer's "can this be serialized" checks and
// the serializer's actual serialization logic.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_CLANGIMPORTER_SWIFTABSTRACTBASICWRITER_H
#define SWIFT_CLANGIMPORTER_SWIFTABSTRACTBASICWRITER_H
#include "clang/AST/AbstractTypeWriter.h"
namespace swift {
/// An implementation of Clang's AbstractBasicWriter interface for a Swift
/// datastream-based reader. This is paired with the AbstractBasicReader
/// implementation in SwiftAbstractBasicReader.h. Note that the general
/// expectation is that the types and declarations involved will have passed
/// a serializability check when this is used for actual serialization.
/// The code in this class is also used when implementing that
/// serializability check and so must be a little more cautious.
///
/// The subclass must implement:
/// void writeUInt64(uint64_t value);
/// void writeIdentifier(const clang::IdentifierInfo *ident);
/// void writeStmtRef(const clang::Stmt *stmt);
/// void writeDeclRef(const clang::Decl *decl);
template <class Impl>
class DataStreamBasicWriter
: public clang::serialization::DataStreamBasicWriter<Impl> {
using super = clang::serialization::DataStreamBasicWriter<Impl>;
public:
using super::asImpl;
/// Perform all the calls necessary to write out the given type.
void writeTypeRef(const clang::Type *type) {
asImpl().writeUInt64(uint64_t(type->getTypeClass()));
clang::serialization::AbstractTypeWriter<Impl>(asImpl()).write(type);
}
void writeBool(bool value) {
asImpl().writeUInt64(uint64_t(value));
}
void writeUInt32(uint32_t value) {
asImpl().writeUInt64(uint64_t(value));
}
void writeSelector(clang::Selector selector) {
if (selector.isNull()) {
asImpl().writeUInt64(0);
return;
}
asImpl().writeUInt64(selector.getNumArgs() + 1);
for (unsigned i = 0, e = std::max(selector.getNumArgs(), 1U); i != e; ++i)
asImpl().writeIdentifier(selector.getIdentifierInfoForSlot(i));
}
void writeSourceLocation(clang::SourceLocation loc) {
// DataStreamBasicReader will always read null; the serializability
// check overrides this to complain about non-null source locations.
}
void writeQualType(clang::QualType type) {
assert(!type.isNull());
auto split = type.split();
asImpl().writeQualifiers(split.Quals);
// Just recursively visit the given type.
asImpl().writeTypeRef(split.Ty);
}
};
}
#endif