This revision was automatically updated to reflect the committed changes.
Closed by commit rL284644: [AST] Add CanonicalDeclPtr<T>. (authored by jlebar).

Changed prior to commit:
  https://reviews.llvm.org/D25703?vs=74911&id=75222#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D25703

Files:
  cfe/trunk/include/clang/AST/Redeclarable.h


Index: cfe/trunk/include/clang/AST/Redeclarable.h
===================================================================
--- cfe/trunk/include/clang/AST/Redeclarable.h
+++ cfe/trunk/include/clang/AST/Redeclarable.h
@@ -279,6 +279,68 @@
   bool isFirstDecl() const { return getFirstDecl() == this; }
 };
 
-}
+/// A wrapper class around a pointer that always points to its canonical
+/// declaration.
+///
+/// CanonicalDeclPtr<decl_type> behaves just like decl_type*, except we call
+/// decl_type::getCanonicalDecl() on construction.
+///
+/// This is useful for hashtables that you want to be keyed on a declaration's
+/// canonical decl -- if you use CanonicalDeclPtr as the key, you don't need to
+/// remember to call getCanonicalDecl() everywhere.
+template <typename decl_type> class CanonicalDeclPtr {
+public:
+  CanonicalDeclPtr() : Ptr(nullptr) {}
+  CanonicalDeclPtr(decl_type *Ptr)
+      : Ptr(Ptr ? Ptr->getCanonicalDecl() : nullptr) {}
+  CanonicalDeclPtr(const CanonicalDeclPtr &) = default;
+  CanonicalDeclPtr &operator=(const CanonicalDeclPtr &) = default;
+
+  operator decl_type *() { return Ptr; }
+  operator const decl_type *() const { return Ptr; }
+
+  decl_type *operator->() { return Ptr; }
+  const decl_type *operator->() const { return Ptr; }
+
+  decl_type &operator*() { return *Ptr; }
+  const decl_type &operator*() const { return *Ptr; }
+
+private:
+  friend struct llvm::DenseMapInfo<CanonicalDeclPtr<decl_type>>;
+
+  decl_type *Ptr;
+};
+} // namespace clang
+
+namespace llvm {
+template <typename decl_type>
+struct DenseMapInfo<clang::CanonicalDeclPtr<decl_type>> {
+  using CanonicalDeclPtr = clang::CanonicalDeclPtr<decl_type>;
+  using BaseInfo = DenseMapInfo<decl_type *>;
+
+  static CanonicalDeclPtr getEmptyKey() {
+    // Construct our CanonicalDeclPtr this way because the regular constructor
+    // would dereference P.Ptr, which is not allowed.
+    CanonicalDeclPtr P;
+    P.Ptr = BaseInfo::getEmptyKey();
+    return P;
+  }
+
+  static CanonicalDeclPtr getTombstoneKey() {
+    CanonicalDeclPtr P;
+    P.Ptr = BaseInfo::getTombstoneKey();
+    return P;
+  }
+
+  static unsigned getHashValue(const CanonicalDeclPtr &P) {
+    return BaseInfo::getHashValue(P);
+  }
+
+  static bool isEqual(const CanonicalDeclPtr &LHS,
+                      const CanonicalDeclPtr &RHS) {
+    return BaseInfo::isEqual(LHS, RHS);
+  }
+};
+} // namespace llvm
 
 #endif


Index: cfe/trunk/include/clang/AST/Redeclarable.h
===================================================================
--- cfe/trunk/include/clang/AST/Redeclarable.h
+++ cfe/trunk/include/clang/AST/Redeclarable.h
@@ -279,6 +279,68 @@
   bool isFirstDecl() const { return getFirstDecl() == this; }
 };
 
-}
+/// A wrapper class around a pointer that always points to its canonical
+/// declaration.
+///
+/// CanonicalDeclPtr<decl_type> behaves just like decl_type*, except we call
+/// decl_type::getCanonicalDecl() on construction.
+///
+/// This is useful for hashtables that you want to be keyed on a declaration's
+/// canonical decl -- if you use CanonicalDeclPtr as the key, you don't need to
+/// remember to call getCanonicalDecl() everywhere.
+template <typename decl_type> class CanonicalDeclPtr {
+public:
+  CanonicalDeclPtr() : Ptr(nullptr) {}
+  CanonicalDeclPtr(decl_type *Ptr)
+      : Ptr(Ptr ? Ptr->getCanonicalDecl() : nullptr) {}
+  CanonicalDeclPtr(const CanonicalDeclPtr &) = default;
+  CanonicalDeclPtr &operator=(const CanonicalDeclPtr &) = default;
+
+  operator decl_type *() { return Ptr; }
+  operator const decl_type *() const { return Ptr; }
+
+  decl_type *operator->() { return Ptr; }
+  const decl_type *operator->() const { return Ptr; }
+
+  decl_type &operator*() { return *Ptr; }
+  const decl_type &operator*() const { return *Ptr; }
+
+private:
+  friend struct llvm::DenseMapInfo<CanonicalDeclPtr<decl_type>>;
+
+  decl_type *Ptr;
+};
+} // namespace clang
+
+namespace llvm {
+template <typename decl_type>
+struct DenseMapInfo<clang::CanonicalDeclPtr<decl_type>> {
+  using CanonicalDeclPtr = clang::CanonicalDeclPtr<decl_type>;
+  using BaseInfo = DenseMapInfo<decl_type *>;
+
+  static CanonicalDeclPtr getEmptyKey() {
+    // Construct our CanonicalDeclPtr this way because the regular constructor
+    // would dereference P.Ptr, which is not allowed.
+    CanonicalDeclPtr P;
+    P.Ptr = BaseInfo::getEmptyKey();
+    return P;
+  }
+
+  static CanonicalDeclPtr getTombstoneKey() {
+    CanonicalDeclPtr P;
+    P.Ptr = BaseInfo::getTombstoneKey();
+    return P;
+  }
+
+  static unsigned getHashValue(const CanonicalDeclPtr &P) {
+    return BaseInfo::getHashValue(P);
+  }
+
+  static bool isEqual(const CanonicalDeclPtr &LHS,
+                      const CanonicalDeclPtr &RHS) {
+    return BaseInfo::isEqual(LHS, RHS);
+  }
+};
+} // namespace llvm
 
 #endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to