mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This is an attribute that gets put on an import in library FooKit to keep it from being a requirement to import FooKit. It's not checked at all, meaning that in this form it is up to the author of FooKit to make sure nothing in its API or ABI depends on the implementation-only dependency. There's also no debugging support here (debugging FooKit /should/ import the implementation-only dependency if it's present). The goal is to get to a point where it /can/ be checked, i.e. FooKit developers are prevented from writing code that would rely on FooKit's implementation-only dependency being present when compiling clients of FooKit. But right now it's not. rdar://problem/48985979
146 lines
4.8 KiB
C++
146 lines
4.8 KiB
C++
//===--- OptionSet.h - Sets of boolean options ------------------*- 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 defines the OptionSet class template.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_BASIC_OPTIONSET_H
|
|
#define SWIFT_BASIC_OPTIONSET_H
|
|
|
|
#include "llvm/ADT/None.h"
|
|
|
|
#include <type_traits>
|
|
#include <cstdint>
|
|
|
|
namespace swift {
|
|
|
|
using llvm::None;
|
|
|
|
/// The class template \c OptionSet captures a set of options stored as the
|
|
/// bits in an unsigned integral value.
|
|
///
|
|
/// Each option corresponds to a particular flag value in the provided
|
|
/// enumeration type (\c Flags). The option set provides ways to add options,
|
|
/// remove options, intersect sets, etc., providing a thin type-safe layer
|
|
/// over the underlying unsigned value.
|
|
///
|
|
/// \tparam Flags An enumeration type that provides the individual flags
|
|
/// for options. Each enumerator should have a power-of-two value, indicating
|
|
/// which bit it is associated with.
|
|
///
|
|
/// \tparam StorageType The unsigned integral type to use to store the flags
|
|
/// enabled within this option set. This defaults to the unsigned form of the
|
|
/// underlying type of the enumeration.
|
|
template<typename Flags,
|
|
typename StorageType = typename std::make_unsigned<
|
|
typename std::underlying_type<Flags>::type
|
|
>::type>
|
|
class OptionSet {
|
|
StorageType Storage;
|
|
|
|
public:
|
|
/// Create an empty option set.
|
|
OptionSet() : Storage() { }
|
|
|
|
/// Create an empty option set.
|
|
OptionSet(llvm::NoneType) : Storage() { }
|
|
|
|
/// Create an option set with only the given option set.
|
|
OptionSet(Flags flag) : Storage(static_cast<StorageType>(flag)) { }
|
|
|
|
/// Create an option set from raw storage.
|
|
explicit OptionSet(StorageType storage) : Storage(storage) { }
|
|
|
|
/// Check whether an option set is non-empty.
|
|
explicit operator bool() const { return Storage != 0; }
|
|
|
|
/// Explicitly convert an option set to its underlying storage.
|
|
explicit operator StorageType() const { return Storage; }
|
|
|
|
/// Explicitly convert an option set to intptr_t, for use in
|
|
/// llvm::PointerIntPair.
|
|
///
|
|
/// This member is not present if the underlying type is bigger than
|
|
/// a pointer.
|
|
template <typename T = std::intptr_t>
|
|
explicit operator typename std::enable_if<sizeof(StorageType) <= sizeof(T),
|
|
std::intptr_t>::type () const {
|
|
return static_cast<intptr_t>(Storage);
|
|
}
|
|
|
|
/// Retrieve the "raw" representation of this option set.
|
|
StorageType toRaw() const { return Storage; }
|
|
|
|
/// Determine whether this option set contains all of the options in the
|
|
/// given set.
|
|
bool contains(OptionSet set) const {
|
|
return !static_cast<bool>(set - *this);
|
|
}
|
|
|
|
/// Check if this option set contains the exact same options as the given set.
|
|
bool containsOnly(OptionSet set) {
|
|
return Storage == set.Storage;
|
|
}
|
|
|
|
// '==' and '!=' are deliberately not defined because they provide a pitfall
|
|
// where someone might use '==' but really want 'contains'. If you actually
|
|
// want '==' behavior, use 'containsOnly'.
|
|
|
|
/// Produce the union of two option sets.
|
|
friend OptionSet operator|(OptionSet lhs, OptionSet rhs) {
|
|
return OptionSet(lhs.Storage | rhs.Storage);
|
|
}
|
|
|
|
/// Produce the union of two option sets.
|
|
friend OptionSet &operator|=(OptionSet &lhs, OptionSet rhs) {
|
|
lhs.Storage |= rhs.Storage;
|
|
return lhs;
|
|
}
|
|
|
|
/// Produce the intersection of two option sets.
|
|
friend OptionSet operator&(OptionSet lhs, OptionSet rhs) {
|
|
return OptionSet(lhs.Storage & rhs.Storage);
|
|
}
|
|
|
|
/// Produce the intersection of two option sets.
|
|
friend OptionSet &operator&=(OptionSet &lhs, OptionSet rhs) {
|
|
lhs.Storage &= rhs.Storage;
|
|
return lhs;
|
|
}
|
|
|
|
/// Produce the difference of two option sets.
|
|
friend OptionSet operator-(OptionSet lhs, OptionSet rhs) {
|
|
return OptionSet(lhs.Storage & ~rhs.Storage);
|
|
}
|
|
|
|
/// Produce the difference of two option sets.
|
|
friend OptionSet &operator-=(OptionSet &lhs, OptionSet rhs) {
|
|
lhs.Storage &= ~rhs.Storage;
|
|
return lhs;
|
|
}
|
|
|
|
private:
|
|
template <typename T>
|
|
static auto _checkResultTypeOperatorOr(T t) -> decltype(t | t) { return T(); }
|
|
|
|
static void _checkResultTypeOperatorOr(...) {}
|
|
|
|
static_assert(!std::is_same<decltype(_checkResultTypeOperatorOr(Flags())),
|
|
Flags>::value,
|
|
"operator| should produce an OptionSet");
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_BASIC_OPTIONSET_H
|