summaryrefslogtreecommitdiffstats
path: root/clang/include
diff options
context:
space:
mode:
authorJustin Lebar <jlebar@google.com>2016-10-19 21:03:42 +0000
committerJustin Lebar <jlebar@google.com>2016-10-19 21:03:42 +0000
commit2271ba2c528478851a0ef8f0f4d7a2ed0af7bc43 (patch)
tree7d2bdcb50f07813939357eb4b94d18bd2d29e69b /clang/include
parent9730ae943f3c639f9d0798a1319b4adc6d3deafc (diff)
downloadbcm5719-llvm-2271ba2c528478851a0ef8f0f4d7a2ed0af7bc43.tar.gz
bcm5719-llvm-2271ba2c528478851a0ef8f0f4d7a2ed0af7bc43.zip
[AST] Add CanonicalDeclPtr<T>.
Summary: CanonicalDeclPtr<T> is just like a T*, except it calls T::getCanonicalDecl() on construction. This is useful as the key in a "set of canonical Decls" -- it's much less error-prone than calling getCanonicalDecl() every time you touch the set. Reviewers: rnk Subscribers: cfe-commits, tra Differential Revision: https://reviews.llvm.org/D25703 llvm-svn: 284644
Diffstat (limited to 'clang/include')
-rw-r--r--clang/include/clang/AST/Redeclarable.h64
1 files changed, 63 insertions, 1 deletions
diff --git a/clang/include/clang/AST/Redeclarable.h b/clang/include/clang/AST/Redeclarable.h
index dd8254668ac..cd5f186a208 100644
--- a/clang/include/clang/AST/Redeclarable.h
+++ b/clang/include/clang/AST/Redeclarable.h
@@ -279,6 +279,68 @@ public:
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
OpenPOWER on IntegriCloud