summaryrefslogtreecommitdiffstats
path: root/include/clang/AST/DeclContextInternals.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/DeclContextInternals.h')
-rw-r--r--include/clang/AST/DeclContextInternals.h48
1 files changed, 39 insertions, 9 deletions
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index 84f3698..9c626c8 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -18,6 +18,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include <algorithm>
@@ -26,23 +27,29 @@ namespace clang {
class DependentDiagnostic;
-/// StoredDeclsList - This is an array of decls optimized a common case of only
-/// containing one entry.
+/// \brief An array of decls optimized for the common case of only containing
+/// one entry.
struct StoredDeclsList {
- /// DeclsTy - When in vector form, this is what the Data pointer points to.
+ /// \brief When in vector form, this is what the Data pointer points to.
typedef SmallVector<NamedDecl *, 4> DeclsTy;
+ /// \brief A collection of declarations, with a flag to indicate if we have
+ /// further external declarations.
+ typedef llvm::PointerIntPair<DeclsTy *, 1, bool> DeclsAndHasExternalTy;
+
/// \brief The stored data, which will be either a pointer to a NamedDecl,
- /// or a pointer to a vector.
- llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
+ /// or a pointer to a vector with a flag to indicate if there are further
+ /// external declarations.
+ llvm::PointerUnion<NamedDecl*, DeclsAndHasExternalTy> Data;
public:
StoredDeclsList() {}
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
if (DeclsTy *RHSVec = RHS.getAsVector())
- Data = new DeclsTy(*RHSVec);
+ Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec),
+ RHS.hasExternalDecls());
}
~StoredDeclsList() {
@@ -56,7 +63,7 @@ public:
delete Vector;
Data = RHS.Data;
if (DeclsTy *RHSVec = RHS.getAsVector())
- Data = new DeclsTy(*RHSVec);
+ Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), hasExternalDecls());
return *this;
}
@@ -66,8 +73,27 @@ public:
return Data.dyn_cast<NamedDecl *>();
}
+ DeclsAndHasExternalTy getAsVectorAndHasExternal() const {
+ return Data.dyn_cast<DeclsAndHasExternalTy>();
+ }
+
DeclsTy *getAsVector() const {
- return Data.dyn_cast<DeclsTy *>();
+ return getAsVectorAndHasExternal().getPointer();
+ }
+
+ bool hasExternalDecls() const {
+ return getAsVectorAndHasExternal().getInt();
+ }
+
+ void setHasExternalDecls() {
+ if (DeclsTy *Vec = getAsVector())
+ Data = DeclsAndHasExternalTy(Vec, true);
+ else {
+ DeclsTy *VT = new DeclsTy();
+ if (NamedDecl *OldD = getAsDecl())
+ VT->push_back(OldD);
+ Data = DeclsAndHasExternalTy(VT, true);
+ }
}
void setOnlyValue(NamedDecl *ND) {
@@ -110,6 +136,8 @@ public:
Vec.erase(std::remove_if(Vec.begin(), Vec.end(),
std::mem_fun(&Decl::isFromASTFile)),
Vec.end());
+ // Don't have any external decls any more.
+ Data = DeclsAndHasExternalTy(&Vec, false);
}
}
@@ -165,12 +193,14 @@ public:
/// not a redeclaration to merge it into the appropriate place in our list.
///
void AddSubsequentDecl(NamedDecl *D) {
+ assert(!isNull() && "don't AddSubsequentDecl when we have no decls");
+
// If this is the second decl added to the list, convert this to vector
// form.
if (NamedDecl *OldD = getAsDecl()) {
DeclsTy *VT = new DeclsTy();
VT->push_back(OldD);
- Data = VT;
+ Data = DeclsAndHasExternalTy(VT, false);
}
DeclsTy &Vec = *getAsVector();
OpenPOWER on IntegriCloud