Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:49

0001 //===- clang/Basic/DirectoryEntry.h - Directory references ------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// Defines interfaces for clang::DirectoryEntry and clang::DirectoryEntryRef.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_BASIC_DIRECTORYENTRY_H
0015 #define LLVM_CLANG_BASIC_DIRECTORYENTRY_H
0016 
0017 #include "clang/Basic/CustomizableOptional.h"
0018 #include "clang/Basic/LLVM.h"
0019 #include "llvm/ADT/DenseMapInfo.h"
0020 #include "llvm/ADT/Hashing.h"
0021 #include "llvm/ADT/STLExtras.h"
0022 #include "llvm/ADT/StringMap.h"
0023 #include "llvm/ADT/StringRef.h"
0024 #include "llvm/Support/ErrorOr.h"
0025 
0026 #include <optional>
0027 #include <utility>
0028 
0029 namespace clang {
0030 namespace FileMgr {
0031 
0032 template <class RefTy> class MapEntryOptionalStorage;
0033 
0034 } // end namespace FileMgr
0035 
0036 /// Cached information about one directory (either on disk or in
0037 /// the virtual file system).
0038 class DirectoryEntry {
0039   DirectoryEntry() = default;
0040   DirectoryEntry(const DirectoryEntry &) = delete;
0041   DirectoryEntry &operator=(const DirectoryEntry &) = delete;
0042   friend class FileManager;
0043   friend class FileEntryTestHelper;
0044 };
0045 
0046 /// A reference to a \c DirectoryEntry  that includes the name of the directory
0047 /// as it was accessed by the FileManager's client.
0048 class DirectoryEntryRef {
0049 public:
0050   const DirectoryEntry &getDirEntry() const { return *ME->getValue(); }
0051 
0052   StringRef getName() const { return ME->getKey(); }
0053 
0054   /// Hash code is based on the DirectoryEntry, not the specific named
0055   /// reference.
0056   friend llvm::hash_code hash_value(DirectoryEntryRef Ref) {
0057     return llvm::hash_value(&Ref.getDirEntry());
0058   }
0059 
0060   using MapEntry = llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>>;
0061 
0062   const MapEntry &getMapEntry() const { return *ME; }
0063 
0064   /// Check if RHS referenced the file in exactly the same way.
0065   bool isSameRef(DirectoryEntryRef RHS) const { return ME == RHS.ME; }
0066 
0067   DirectoryEntryRef() = delete;
0068   explicit DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {}
0069 
0070   /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to
0071   /// facilitate incremental adoption.
0072   ///
0073   /// The goal is to avoid code churn due to dances like the following:
0074   /// \code
0075   /// // Old code.
0076   /// lvalue = rvalue;
0077   ///
0078   /// // Temporary code from an incremental patch.
0079   /// lvalue = &rvalue.getDirectoryEntry();
0080   ///
0081   /// // Final code.
0082   /// lvalue = rvalue;
0083   /// \endcode
0084   ///
0085   /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::getName
0086   /// has been deleted, delete this implicit conversion.
0087   operator const DirectoryEntry *() const { return &getDirEntry(); }
0088 
0089 private:
0090   friend class FileMgr::MapEntryOptionalStorage<DirectoryEntryRef>;
0091   struct optional_none_tag {};
0092 
0093   // Private constructor for use by OptionalStorage.
0094   DirectoryEntryRef(optional_none_tag) : ME(nullptr) {}
0095   bool hasOptionalValue() const { return ME; }
0096 
0097   friend struct llvm::DenseMapInfo<DirectoryEntryRef>;
0098   struct dense_map_empty_tag {};
0099   struct dense_map_tombstone_tag {};
0100 
0101   // Private constructors for use by DenseMapInfo.
0102   DirectoryEntryRef(dense_map_empty_tag)
0103       : ME(llvm::DenseMapInfo<const MapEntry *>::getEmptyKey()) {}
0104   DirectoryEntryRef(dense_map_tombstone_tag)
0105       : ME(llvm::DenseMapInfo<const MapEntry *>::getTombstoneKey()) {}
0106   bool isSpecialDenseMapKey() const {
0107     return isSameRef(DirectoryEntryRef(dense_map_empty_tag())) ||
0108            isSameRef(DirectoryEntryRef(dense_map_tombstone_tag()));
0109   }
0110 
0111   const MapEntry *ME;
0112 };
0113 
0114 using OptionalDirectoryEntryRef = CustomizableOptional<DirectoryEntryRef>;
0115 
0116 namespace FileMgr {
0117 
0118 /// Customized storage for refs derived from map entires in FileManager, using
0119 /// the private optional_none_tag to keep it to the size of a single pointer.
0120 template <class RefTy> class MapEntryOptionalStorage {
0121   using optional_none_tag = typename RefTy::optional_none_tag;
0122   RefTy MaybeRef;
0123 
0124 public:
0125   MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
0126 
0127   template <class... ArgTypes>
0128   explicit MapEntryOptionalStorage(std::in_place_t, ArgTypes &&...Args)
0129       : MaybeRef(std::forward<ArgTypes>(Args)...) {}
0130 
0131   void reset() { MaybeRef = optional_none_tag(); }
0132 
0133   bool has_value() const { return MaybeRef.hasOptionalValue(); }
0134 
0135   RefTy &value() & {
0136     assert(has_value());
0137     return MaybeRef;
0138   }
0139   RefTy const &value() const & {
0140     assert(has_value());
0141     return MaybeRef;
0142   }
0143   RefTy &&value() && {
0144     assert(has_value());
0145     return std::move(MaybeRef);
0146   }
0147 
0148   template <class... Args> void emplace(Args &&...args) {
0149     MaybeRef = RefTy(std::forward<Args>(args)...);
0150   }
0151 
0152   MapEntryOptionalStorage &operator=(RefTy Ref) {
0153     MaybeRef = Ref;
0154     return *this;
0155   }
0156 };
0157 
0158 } // end namespace FileMgr
0159 
0160 namespace optional_detail {
0161 
0162 /// Customize OptionalStorage<DirectoryEntryRef> to use DirectoryEntryRef and
0163 /// its optional_none_tag to keep it the size of a single pointer.
0164 template <>
0165 class OptionalStorage<clang::DirectoryEntryRef>
0166     : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
0167   using StorageImpl =
0168       clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>;
0169 
0170 public:
0171   OptionalStorage() = default;
0172 
0173   template <class... ArgTypes>
0174   explicit OptionalStorage(std::in_place_t, ArgTypes &&...Args)
0175       : StorageImpl(std::in_place_t{}, std::forward<ArgTypes>(Args)...) {}
0176 
0177   OptionalStorage &operator=(clang::DirectoryEntryRef Ref) {
0178     StorageImpl::operator=(Ref);
0179     return *this;
0180   }
0181 };
0182 
0183 static_assert(sizeof(OptionalDirectoryEntryRef) == sizeof(DirectoryEntryRef),
0184               "OptionalDirectoryEntryRef must avoid size overhead");
0185 
0186 static_assert(std::is_trivially_copyable<OptionalDirectoryEntryRef>::value,
0187               "OptionalDirectoryEntryRef should be trivially copyable");
0188 
0189 } // end namespace optional_detail
0190 } // namespace clang
0191 
0192 namespace llvm {
0193 
0194 template <> struct PointerLikeTypeTraits<clang::DirectoryEntryRef> {
0195   static inline void *getAsVoidPointer(clang::DirectoryEntryRef Dir) {
0196     return const_cast<clang::DirectoryEntryRef::MapEntry *>(&Dir.getMapEntry());
0197   }
0198 
0199   static inline clang::DirectoryEntryRef getFromVoidPointer(void *Ptr) {
0200     return clang::DirectoryEntryRef(
0201         *reinterpret_cast<const clang::DirectoryEntryRef::MapEntry *>(Ptr));
0202   }
0203 
0204   static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<
0205       const clang::DirectoryEntryRef::MapEntry *>::NumLowBitsAvailable;
0206 };
0207 
0208 /// Specialisation of DenseMapInfo for DirectoryEntryRef.
0209 template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
0210   static inline clang::DirectoryEntryRef getEmptyKey() {
0211     return clang::DirectoryEntryRef(
0212         clang::DirectoryEntryRef::dense_map_empty_tag());
0213   }
0214 
0215   static inline clang::DirectoryEntryRef getTombstoneKey() {
0216     return clang::DirectoryEntryRef(
0217         clang::DirectoryEntryRef::dense_map_tombstone_tag());
0218   }
0219 
0220   static unsigned getHashValue(clang::DirectoryEntryRef Val) {
0221     return hash_value(Val);
0222   }
0223 
0224   static bool isEqual(clang::DirectoryEntryRef LHS,
0225                       clang::DirectoryEntryRef RHS) {
0226     // Catch the easy cases: both empty, both tombstone, or the same ref.
0227     if (LHS.isSameRef(RHS))
0228       return true;
0229 
0230     // Confirm LHS and RHS are valid.
0231     if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
0232       return false;
0233 
0234     // It's safe to use operator==.
0235     return LHS == RHS;
0236   }
0237 };
0238 
0239 } // end namespace llvm
0240 
0241 #endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H