123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- clang/Basic/DirectoryEntry.h - Directory references ------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- ///
- /// \file
- /// Defines interfaces for clang::DirectoryEntry and clang::DirectoryEntryRef.
- ///
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_CLANG_BASIC_DIRECTORYENTRY_H
- #define LLVM_CLANG_BASIC_DIRECTORYENTRY_H
- #include "clang/Basic/LLVM.h"
- #include "llvm/ADT/DenseMapInfo.h"
- #include "llvm/ADT/Hashing.h"
- #include "llvm/ADT/StringMap.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/Support/ErrorOr.h"
- namespace clang {
- namespace FileMgr {
- template <class RefTy> class MapEntryOptionalStorage;
- } // end namespace FileMgr
- /// Cached information about one directory (either on disk or in
- /// the virtual file system).
- class DirectoryEntry {
- friend class FileManager;
- // FIXME: We should not be storing a directory entry name here.
- StringRef Name; // Name of the directory.
- public:
- StringRef getName() const { return Name; }
- };
- /// A reference to a \c DirectoryEntry that includes the name of the directory
- /// as it was accessed by the FileManager's client.
- class DirectoryEntryRef {
- public:
- const DirectoryEntry &getDirEntry() const { return *ME->getValue(); }
- StringRef getName() const { return ME->getKey(); }
- /// Hash code is based on the DirectoryEntry, not the specific named
- /// reference.
- friend llvm::hash_code hash_value(DirectoryEntryRef Ref) {
- return llvm::hash_value(&Ref.getDirEntry());
- }
- using MapEntry = llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>>;
- const MapEntry &getMapEntry() const { return *ME; }
- /// Check if RHS referenced the file in exactly the same way.
- bool isSameRef(DirectoryEntryRef RHS) const { return ME == RHS.ME; }
- DirectoryEntryRef() = delete;
- DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {}
- /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to
- /// facilitate incremental adoption.
- ///
- /// The goal is to avoid code churn due to dances like the following:
- /// \code
- /// // Old code.
- /// lvalue = rvalue;
- ///
- /// // Temporary code from an incremental patch.
- /// lvalue = &rvalue.getDirectoryEntry();
- ///
- /// // Final code.
- /// lvalue = rvalue;
- /// \endcode
- ///
- /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::getName
- /// has been deleted, delete this implicit conversion.
- operator const DirectoryEntry *() const { return &getDirEntry(); }
- private:
- friend class FileMgr::MapEntryOptionalStorage<DirectoryEntryRef>;
- struct optional_none_tag {};
- // Private constructor for use by OptionalStorage.
- DirectoryEntryRef(optional_none_tag) : ME(nullptr) {}
- bool hasOptionalValue() const { return ME; }
- friend struct llvm::DenseMapInfo<DirectoryEntryRef>;
- struct dense_map_empty_tag {};
- struct dense_map_tombstone_tag {};
- // Private constructors for use by DenseMapInfo.
- DirectoryEntryRef(dense_map_empty_tag)
- : ME(llvm::DenseMapInfo<const MapEntry *>::getEmptyKey()) {}
- DirectoryEntryRef(dense_map_tombstone_tag)
- : ME(llvm::DenseMapInfo<const MapEntry *>::getTombstoneKey()) {}
- bool isSpecialDenseMapKey() const {
- return isSameRef(DirectoryEntryRef(dense_map_empty_tag())) ||
- isSameRef(DirectoryEntryRef(dense_map_tombstone_tag()));
- }
- const MapEntry *ME;
- };
- namespace FileMgr {
- /// Customized storage for refs derived from map entires in FileManager, using
- /// the private optional_none_tag to keep it to the size of a single pointer.
- template <class RefTy> class MapEntryOptionalStorage {
- using optional_none_tag = typename RefTy::optional_none_tag;
- RefTy MaybeRef;
- public:
- MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
- template <class... ArgTypes>
- explicit MapEntryOptionalStorage(llvm::in_place_t, ArgTypes &&...Args)
- : MaybeRef(std::forward<ArgTypes>(Args)...) {}
- void reset() { MaybeRef = optional_none_tag(); }
- bool hasValue() const { return MaybeRef.hasOptionalValue(); }
- RefTy &getValue() LLVM_LVALUE_FUNCTION {
- assert(hasValue());
- return MaybeRef;
- }
- RefTy const &getValue() const LLVM_LVALUE_FUNCTION {
- assert(hasValue());
- return MaybeRef;
- }
- #if LLVM_HAS_RVALUE_REFERENCE_THIS
- RefTy &&getValue() && {
- assert(hasValue());
- return std::move(MaybeRef);
- }
- #endif
- template <class... Args> void emplace(Args &&...args) {
- MaybeRef = RefTy(std::forward<Args>(args)...);
- }
- MapEntryOptionalStorage &operator=(RefTy Ref) {
- MaybeRef = Ref;
- return *this;
- }
- };
- } // end namespace FileMgr
- } // end namespace clang
- namespace llvm {
- namespace optional_detail {
- /// Customize OptionalStorage<DirectoryEntryRef> to use DirectoryEntryRef and
- /// its optional_none_tag to keep it the size of a single pointer.
- template <>
- class OptionalStorage<clang::DirectoryEntryRef>
- : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
- using StorageImpl =
- clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>;
- public:
- OptionalStorage() = default;
- template <class... ArgTypes>
- explicit OptionalStorage(in_place_t, ArgTypes &&...Args)
- : StorageImpl(in_place_t{}, std::forward<ArgTypes>(Args)...) {}
- OptionalStorage &operator=(clang::DirectoryEntryRef Ref) {
- StorageImpl::operator=(Ref);
- return *this;
- }
- };
- static_assert(sizeof(Optional<clang::DirectoryEntryRef>) ==
- sizeof(clang::DirectoryEntryRef),
- "Optional<DirectoryEntryRef> must avoid size overhead");
- static_assert(
- std::is_trivially_copyable<Optional<clang::DirectoryEntryRef>>::value,
- "Optional<DirectoryEntryRef> should be trivially copyable");
- } // end namespace optional_detail
- /// Specialisation of DenseMapInfo for DirectoryEntryRef.
- template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
- static inline clang::DirectoryEntryRef getEmptyKey() {
- return clang::DirectoryEntryRef(
- clang::DirectoryEntryRef::dense_map_empty_tag());
- }
- static inline clang::DirectoryEntryRef getTombstoneKey() {
- return clang::DirectoryEntryRef(
- clang::DirectoryEntryRef::dense_map_tombstone_tag());
- }
- static unsigned getHashValue(clang::DirectoryEntryRef Val) {
- return hash_value(Val);
- }
- static bool isEqual(clang::DirectoryEntryRef LHS,
- clang::DirectoryEntryRef RHS) {
- // Catch the easy cases: both empty, both tombstone, or the same ref.
- if (LHS.isSameRef(RHS))
- return true;
- // Confirm LHS and RHS are valid.
- if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
- return false;
- // It's safe to use operator==.
- return LHS == RHS;
- }
- };
- } // end namespace llvm
- namespace clang {
- /// Wrapper around Optional<DirectoryEntryRef> that degrades to 'const
- /// DirectoryEntry*', facilitating incremental patches to propagate
- /// DirectoryEntryRef.
- ///
- /// This class can be used as return value or field where it's convenient for
- /// an Optional<DirectoryEntryRef> to degrade to a 'const DirectoryEntry*'. The
- /// purpose is to avoid code churn due to dances like the following:
- /// \code
- /// // Old code.
- /// lvalue = rvalue;
- ///
- /// // Temporary code from an incremental patch.
- /// Optional<DirectoryEntryRef> MaybeF = rvalue;
- /// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr;
- ///
- /// // Final code.
- /// lvalue = rvalue;
- /// \endcode
- ///
- /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef
- /// and DirectoryEntry::getName have been deleted, delete this class and
- /// replace instances with Optional<DirectoryEntryRef>.
- class OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr
- : public Optional<DirectoryEntryRef> {
- public:
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr() = default;
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
- const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
- operator=(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
- operator=(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(llvm::NoneType) {}
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(DirectoryEntryRef Ref)
- : Optional<DirectoryEntryRef>(Ref) {}
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(Optional<DirectoryEntryRef> MaybeRef)
- : Optional<DirectoryEntryRef>(MaybeRef) {}
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(llvm::NoneType) {
- Optional<DirectoryEntryRef>::operator=(None);
- return *this;
- }
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(DirectoryEntryRef Ref) {
- Optional<DirectoryEntryRef>::operator=(Ref);
- return *this;
- }
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
- operator=(Optional<DirectoryEntryRef> MaybeRef) {
- Optional<DirectoryEntryRef>::operator=(MaybeRef);
- return *this;
- }
- /// Degrade to 'const DirectoryEntry *' to allow DirectoryEntry::LastRef and
- /// DirectoryEntry::getName have been deleted, delete this class and replace
- /// instances with Optional<DirectoryEntryRef>
- operator const DirectoryEntry *() const {
- return hasValue() ? &getValue().getDirEntry() : nullptr;
- }
- };
- static_assert(std::is_trivially_copyable<
- OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value,
- "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be "
- "trivially copyable");
- } // end namespace clang
- #endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|