Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- clang/Basic/DirectoryEntry.h - Directory references ------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file
  10. /// Defines interfaces for clang::DirectoryEntry and clang::DirectoryEntryRef.
  11. ///
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_CLANG_BASIC_DIRECTORYENTRY_H
  15. #define LLVM_CLANG_BASIC_DIRECTORYENTRY_H
  16.  
  17. #include "clang/Basic/CustomizableOptional.h"
  18. #include "clang/Basic/LLVM.h"
  19. #include "llvm/ADT/DenseMapInfo.h"
  20. #include "llvm/ADT/Hashing.h"
  21. #include "llvm/ADT/STLExtras.h"
  22. #include "llvm/ADT/StringMap.h"
  23. #include "llvm/ADT/StringRef.h"
  24. #include "llvm/Support/ErrorOr.h"
  25.  
  26. #include <optional>
  27. #include <utility>
  28.  
  29. namespace clang {
  30. namespace FileMgr {
  31.  
  32. template <class RefTy> class MapEntryOptionalStorage;
  33.  
  34. } // end namespace FileMgr
  35.  
  36. /// Cached information about one directory (either on disk or in
  37. /// the virtual file system).
  38. class DirectoryEntry {
  39.   DirectoryEntry() = default;
  40.   DirectoryEntry(const DirectoryEntry &) = delete;
  41.   DirectoryEntry &operator=(const DirectoryEntry &) = delete;
  42.   friend class FileManager;
  43.   friend class FileEntryTestHelper;
  44.  
  45.   // FIXME: We should not be storing a directory entry name here.
  46.   StringRef Name; // Name of the directory.
  47.  
  48. public:
  49.   StringRef getName() const { return Name; }
  50. };
  51.  
  52. /// A reference to a \c DirectoryEntry  that includes the name of the directory
  53. /// as it was accessed by the FileManager's client.
  54. class DirectoryEntryRef {
  55. public:
  56.   const DirectoryEntry &getDirEntry() const { return *ME->getValue(); }
  57.  
  58.   StringRef getName() const { return ME->getKey(); }
  59.  
  60.   /// Hash code is based on the DirectoryEntry, not the specific named
  61.   /// reference.
  62.   friend llvm::hash_code hash_value(DirectoryEntryRef Ref) {
  63.     return llvm::hash_value(&Ref.getDirEntry());
  64.   }
  65.  
  66.   using MapEntry = llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>>;
  67.  
  68.   const MapEntry &getMapEntry() const { return *ME; }
  69.  
  70.   /// Check if RHS referenced the file in exactly the same way.
  71.   bool isSameRef(DirectoryEntryRef RHS) const { return ME == RHS.ME; }
  72.  
  73.   DirectoryEntryRef() = delete;
  74.   DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {}
  75.  
  76.   /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to
  77.   /// facilitate incremental adoption.
  78.   ///
  79.   /// The goal is to avoid code churn due to dances like the following:
  80.   /// \code
  81.   /// // Old code.
  82.   /// lvalue = rvalue;
  83.   ///
  84.   /// // Temporary code from an incremental patch.
  85.   /// lvalue = &rvalue.getDirectoryEntry();
  86.   ///
  87.   /// // Final code.
  88.   /// lvalue = rvalue;
  89.   /// \endcode
  90.   ///
  91.   /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::getName
  92.   /// has been deleted, delete this implicit conversion.
  93.   operator const DirectoryEntry *() const { return &getDirEntry(); }
  94.  
  95. private:
  96.   friend class FileMgr::MapEntryOptionalStorage<DirectoryEntryRef>;
  97.   struct optional_none_tag {};
  98.  
  99.   // Private constructor for use by OptionalStorage.
  100.   DirectoryEntryRef(optional_none_tag) : ME(nullptr) {}
  101.   bool hasOptionalValue() const { return ME; }
  102.  
  103.   friend struct llvm::DenseMapInfo<DirectoryEntryRef>;
  104.   struct dense_map_empty_tag {};
  105.   struct dense_map_tombstone_tag {};
  106.  
  107.   // Private constructors for use by DenseMapInfo.
  108.   DirectoryEntryRef(dense_map_empty_tag)
  109.       : ME(llvm::DenseMapInfo<const MapEntry *>::getEmptyKey()) {}
  110.   DirectoryEntryRef(dense_map_tombstone_tag)
  111.       : ME(llvm::DenseMapInfo<const MapEntry *>::getTombstoneKey()) {}
  112.   bool isSpecialDenseMapKey() const {
  113.     return isSameRef(DirectoryEntryRef(dense_map_empty_tag())) ||
  114.            isSameRef(DirectoryEntryRef(dense_map_tombstone_tag()));
  115.   }
  116.  
  117.   const MapEntry *ME;
  118. };
  119.  
  120. using OptionalDirectoryEntryRef = CustomizableOptional<DirectoryEntryRef>;
  121.  
  122. namespace FileMgr {
  123.  
  124. /// Customized storage for refs derived from map entires in FileManager, using
  125. /// the private optional_none_tag to keep it to the size of a single pointer.
  126. template <class RefTy> class MapEntryOptionalStorage {
  127.   using optional_none_tag = typename RefTy::optional_none_tag;
  128.   RefTy MaybeRef;
  129.  
  130. public:
  131.   MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
  132.  
  133.   template <class... ArgTypes>
  134.   explicit MapEntryOptionalStorage(std::in_place_t, ArgTypes &&...Args)
  135.       : MaybeRef(std::forward<ArgTypes>(Args)...) {}
  136.  
  137.   void reset() { MaybeRef = optional_none_tag(); }
  138.  
  139.   bool has_value() const { return MaybeRef.hasOptionalValue(); }
  140.  
  141.   RefTy &value() & {
  142.     assert(has_value());
  143.     return MaybeRef;
  144.   }
  145.   RefTy const &value() const & {
  146.     assert(has_value());
  147.     return MaybeRef;
  148.   }
  149.   RefTy &&value() && {
  150.     assert(has_value());
  151.     return std::move(MaybeRef);
  152.   }
  153.  
  154.   template <class... Args> void emplace(Args &&...args) {
  155.     MaybeRef = RefTy(std::forward<Args>(args)...);
  156.   }
  157.  
  158.   MapEntryOptionalStorage &operator=(RefTy Ref) {
  159.     MaybeRef = Ref;
  160.     return *this;
  161.   }
  162. };
  163.  
  164. } // end namespace FileMgr
  165.  
  166. namespace optional_detail {
  167.  
  168. /// Customize OptionalStorage<DirectoryEntryRef> to use DirectoryEntryRef and
  169. /// its optional_none_tag to keep it the size of a single pointer.
  170. template <>
  171. class OptionalStorage<clang::DirectoryEntryRef>
  172.     : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
  173.   using StorageImpl =
  174.       clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>;
  175.  
  176. public:
  177.   OptionalStorage() = default;
  178.  
  179.   template <class... ArgTypes>
  180.   explicit OptionalStorage(std::in_place_t, ArgTypes &&...Args)
  181.       : StorageImpl(std::in_place_t{}, std::forward<ArgTypes>(Args)...) {}
  182.  
  183.   OptionalStorage &operator=(clang::DirectoryEntryRef Ref) {
  184.     StorageImpl::operator=(Ref);
  185.     return *this;
  186.   }
  187. };
  188.  
  189. static_assert(sizeof(OptionalDirectoryEntryRef) == sizeof(DirectoryEntryRef),
  190.               "OptionalDirectoryEntryRef must avoid size overhead");
  191.  
  192. static_assert(std::is_trivially_copyable<OptionalDirectoryEntryRef>::value,
  193.               "OptionalDirectoryEntryRef should be trivially copyable");
  194.  
  195. } // end namespace optional_detail
  196. } // namespace clang
  197.  
  198. namespace llvm {
  199. /// Specialisation of DenseMapInfo for DirectoryEntryRef.
  200. template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
  201.   static inline clang::DirectoryEntryRef getEmptyKey() {
  202.     return clang::DirectoryEntryRef(
  203.         clang::DirectoryEntryRef::dense_map_empty_tag());
  204.   }
  205.  
  206.   static inline clang::DirectoryEntryRef getTombstoneKey() {
  207.     return clang::DirectoryEntryRef(
  208.         clang::DirectoryEntryRef::dense_map_tombstone_tag());
  209.   }
  210.  
  211.   static unsigned getHashValue(clang::DirectoryEntryRef Val) {
  212.     return hash_value(Val);
  213.   }
  214.  
  215.   static bool isEqual(clang::DirectoryEntryRef LHS,
  216.                       clang::DirectoryEntryRef RHS) {
  217.     // Catch the easy cases: both empty, both tombstone, or the same ref.
  218.     if (LHS.isSameRef(RHS))
  219.       return true;
  220.  
  221.     // Confirm LHS and RHS are valid.
  222.     if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
  223.       return false;
  224.  
  225.     // It's safe to use operator==.
  226.     return LHS == RHS;
  227.   }
  228. };
  229.  
  230. } // end namespace llvm
  231.  
  232. namespace clang {
  233.  
  234. /// Wrapper around OptionalDirectoryEntryRef that degrades to 'const
  235. /// DirectoryEntry*', facilitating incremental patches to propagate
  236. /// DirectoryEntryRef.
  237. ///
  238. /// This class can be used as return value or field where it's convenient for
  239. /// an OptionalDirectoryEntryRef to degrade to a 'const DirectoryEntry*'. The
  240. /// purpose is to avoid code churn due to dances like the following:
  241. /// \code
  242. /// // Old code.
  243. /// lvalue = rvalue;
  244. ///
  245. /// // Temporary code from an incremental patch.
  246. /// OptionalDirectoryEntryRef MaybeF = rvalue;
  247. /// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr;
  248. ///
  249. /// // Final code.
  250. /// lvalue = rvalue;
  251. /// \endcode
  252. ///
  253. /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef
  254. /// and DirectoryEntry::getName have been deleted, delete this class and
  255. /// replace instances with OptionalDirectoryEntryRef.
  256. class OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr
  257.     : public OptionalDirectoryEntryRef {
  258. public:
  259.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr() = default;
  260.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
  261.       OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
  262.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
  263.       const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
  264.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
  265.   operator=(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
  266.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
  267.   operator=(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
  268.  
  269.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(std::nullopt_t) {}
  270.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(DirectoryEntryRef Ref)
  271.       : OptionalDirectoryEntryRef(Ref) {}
  272.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
  273.       OptionalDirectoryEntryRef MaybeRef)
  274.       : OptionalDirectoryEntryRef(MaybeRef) {}
  275.  
  276.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
  277.   operator=(std::nullopt_t) {
  278.     OptionalDirectoryEntryRef::operator=(std::nullopt);
  279.     return *this;
  280.   }
  281.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(DirectoryEntryRef Ref) {
  282.     OptionalDirectoryEntryRef::operator=(Ref);
  283.     return *this;
  284.   }
  285.   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
  286.   operator=(OptionalDirectoryEntryRef MaybeRef) {
  287.     OptionalDirectoryEntryRef::operator=(MaybeRef);
  288.     return *this;
  289.   }
  290.  
  291.   /// Degrade to 'const DirectoryEntry *' to allow  DirectoryEntry::LastRef and
  292.   /// DirectoryEntry::getName have been deleted, delete this class and replace
  293.   /// instances with OptionalDirectoryEntryRef
  294.   operator const DirectoryEntry *() const {
  295.     return has_value() ? &(*this)->getDirEntry() : nullptr;
  296.   }
  297. };
  298.  
  299. static_assert(std::is_trivially_copyable<
  300.                   OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value,
  301.               "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be "
  302.               "trivially copyable");
  303.  
  304. } // end namespace clang
  305.  
  306. #endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H
  307.