10b57cec5SDimitry Andric //===- ASTUnresolvedSet.h - Unresolved sets of declarations -----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file provides an UnresolvedSet-like class, whose contents are
100b57cec5SDimitry Andric //  allocated using the allocator associated with an ASTContext.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
150b57cec5SDimitry Andric #define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "clang/AST/ASTVector.h"
180b57cec5SDimitry Andric #include "clang/AST/DeclAccessPair.h"
190b57cec5SDimitry Andric #include "clang/AST/UnresolvedSet.h"
200b57cec5SDimitry Andric #include "clang/Basic/Specifiers.h"
210b57cec5SDimitry Andric #include <cassert>
220b57cec5SDimitry Andric #include <cstdint>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace clang {
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric class NamedDecl;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric /// An UnresolvedSet-like class which uses the ASTContext's allocator.
290b57cec5SDimitry Andric class ASTUnresolvedSet {
300b57cec5SDimitry Andric   friend class LazyASTUnresolvedSet;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   struct DeclsTy : ASTVector<DeclAccessPair> {
330b57cec5SDimitry Andric     DeclsTy() = default;
DeclsTyDeclsTy340b57cec5SDimitry Andric     DeclsTy(ASTContext &C, unsigned N) : ASTVector<DeclAccessPair>(C, N) {}
350b57cec5SDimitry Andric 
isLazyDeclsTy360b57cec5SDimitry Andric     bool isLazy() const { return getTag(); }
setLazyDeclsTy370b57cec5SDimitry Andric     void setLazy(bool Lazy) { setTag(Lazy); }
380b57cec5SDimitry Andric   };
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   DeclsTy Decls;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric public:
430b57cec5SDimitry Andric   ASTUnresolvedSet() = default;
ASTUnresolvedSet(ASTContext & C,unsigned N)440b57cec5SDimitry Andric   ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {}
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   using iterator = UnresolvedSetIterator;
470b57cec5SDimitry Andric   using const_iterator = UnresolvedSetIterator;
480b57cec5SDimitry Andric 
begin()490b57cec5SDimitry Andric   iterator begin() { return iterator(Decls.begin()); }
end()500b57cec5SDimitry Andric   iterator end() { return iterator(Decls.end()); }
510b57cec5SDimitry Andric 
begin()520b57cec5SDimitry Andric   const_iterator begin() const { return const_iterator(Decls.begin()); }
end()530b57cec5SDimitry Andric   const_iterator end() const { return const_iterator(Decls.end()); }
540b57cec5SDimitry Andric 
addDecl(ASTContext & C,NamedDecl * D,AccessSpecifier AS)550b57cec5SDimitry Andric   void addDecl(ASTContext &C, NamedDecl *D, AccessSpecifier AS) {
560b57cec5SDimitry Andric     Decls.push_back(DeclAccessPair::make(D, AS), C);
570b57cec5SDimitry Andric   }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   /// Replaces the given declaration with the new one, once.
600b57cec5SDimitry Andric   ///
610b57cec5SDimitry Andric   /// \return true if the set changed
replace(const NamedDecl * Old,NamedDecl * New,AccessSpecifier AS)620b57cec5SDimitry Andric   bool replace(const NamedDecl *Old, NamedDecl *New, AccessSpecifier AS) {
630b57cec5SDimitry Andric     for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) {
640b57cec5SDimitry Andric       if (I->getDecl() == Old) {
650b57cec5SDimitry Andric         I->set(New, AS);
660b57cec5SDimitry Andric         return true;
670b57cec5SDimitry Andric       }
680b57cec5SDimitry Andric     }
690b57cec5SDimitry Andric     return false;
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric 
erase(unsigned I)72bdd1243dSDimitry Andric   void erase(unsigned I) {
73bdd1243dSDimitry Andric     if (I == Decls.size() - 1)
74bdd1243dSDimitry Andric       Decls.pop_back();
75bdd1243dSDimitry Andric     else
76bdd1243dSDimitry Andric       Decls[I] = Decls.pop_back_val();
77bdd1243dSDimitry Andric   }
780b57cec5SDimitry Andric 
clear()790b57cec5SDimitry Andric   void clear() { Decls.clear(); }
800b57cec5SDimitry Andric 
empty()810b57cec5SDimitry Andric   bool empty() const { return Decls.empty(); }
size()820b57cec5SDimitry Andric   unsigned size() const { return Decls.size(); }
830b57cec5SDimitry Andric 
reserve(ASTContext & C,unsigned N)840b57cec5SDimitry Andric   void reserve(ASTContext &C, unsigned N) {
850b57cec5SDimitry Andric     Decls.reserve(C, N);
860b57cec5SDimitry Andric   }
870b57cec5SDimitry Andric 
append(ASTContext & C,iterator I,iterator E)880b57cec5SDimitry Andric   void append(ASTContext &C, iterator I, iterator E) {
890b57cec5SDimitry Andric     Decls.append(C, I.I, E.I);
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   DeclAccessPair &operator[](unsigned I) { return Decls[I]; }
930b57cec5SDimitry Andric   const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; }
940b57cec5SDimitry Andric };
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric /// An UnresolvedSet-like class that might not have been loaded from the
970b57cec5SDimitry Andric /// external AST source yet.
980b57cec5SDimitry Andric class LazyASTUnresolvedSet {
990b57cec5SDimitry Andric   mutable ASTUnresolvedSet Impl;
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   void getFromExternalSource(ASTContext &C) const;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric public:
get(ASTContext & C)1040b57cec5SDimitry Andric   ASTUnresolvedSet &get(ASTContext &C) const {
1050b57cec5SDimitry Andric     if (Impl.Decls.isLazy())
1060b57cec5SDimitry Andric       getFromExternalSource(C);
1070b57cec5SDimitry Andric     return Impl;
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric 
reserve(ASTContext & C,unsigned N)1100b57cec5SDimitry Andric   void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); }
1110b57cec5SDimitry Andric 
addLazyDecl(ASTContext & C,uintptr_t ID,AccessSpecifier AS)1120b57cec5SDimitry Andric   void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) {
1130b57cec5SDimitry Andric     assert(Impl.empty() || Impl.Decls.isLazy());
1140b57cec5SDimitry Andric     Impl.Decls.setLazy(true);
1150b57cec5SDimitry Andric     Impl.addDecl(C, reinterpret_cast<NamedDecl *>(ID << 2), AS);
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric };
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric } // namespace clang
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric #endif // LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
122