aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/DeclBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/DeclBase.cpp')
-rw-r--r--lib/AST/DeclBase.cpp163
1 files changed, 95 insertions, 68 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 5d70493d1d..87ebf85b41 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
+#include <vector>
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -375,21 +376,15 @@ const DeclContext *DeclContext::getLexicalParent() const {
return getParent();
}
-/// TwoNamedDecls - Stores up to two NamedDecls. The first
-/// declaration, if any, is in the ordinary identifier namespace, and
-/// corresponds to values (functions, variables, etc.). The second
-/// declaration, if any, is in the tag identifier namespace, and
-/// corresponds to tag types (classes, enums).
-struct TwoNamedDecls {
- NamedDecl* Decls[2];
-};
-
// FIXME: We really want to use a DenseSet here to eliminate the
// redundant storage of the declaration names, but (1) it doesn't give
// us the ability to search based on DeclarationName, (2) we really
// need something more like a DenseMultiSet, and (3) it's
-// implemented in terms of DenseMap anyway.
-typedef llvm::DenseMap<DeclarationName, TwoNamedDecls> StoredDeclsMap;
+// implemented in terms of DenseMap anyway. However, this data
+// structure is really space-inefficient, so we'll have to do
+// something.
+typedef llvm::DenseMap<DeclarationName, std::vector<ScopedDecl*> >
+ StoredDeclsMap;
DeclContext::~DeclContext() {
unsigned Size = LookupPtr.getInt();
@@ -397,7 +392,7 @@ DeclContext::~DeclContext() {
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
delete Map;
} else {
- NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
+ ScopedDecl **Array = static_cast<ScopedDecl**>(LookupPtr.getPointer());
delete [] Array;
}
}
@@ -497,7 +492,7 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
if (PrimaryContext != this)
return PrimaryContext->lookup(Context, Name);
- /// If there is no lookup data structure, build one now by talking
+ /// If there is no lookup data structure, build one now by walking
/// all of the linked DeclContexts (in declaration order!) and
/// inserting their values.
if (LookupPtr.getPointer() == 0) {
@@ -506,32 +501,27 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
insertImpl(*D);
}
- lookup_result Result(0, 0);
if (isLookupMap()) {
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
StoredDeclsMap::iterator Pos = Map->find(Name);
- if (Pos != Map->end()) {
- Result.first = Pos->second.Decls[0]? &Pos->second.Decls[0]
- : &Pos->second.Decls[1];
- Result.second = Pos->second.Decls[1]? &Pos->second.Decls[2]
- : &Pos->second.Decls[1];
- }
- return Result;
+ if (Pos != Map->end())
+ return lookup_result(&Pos->second.front(),
+ &Pos->second.front() + Pos->second.size());
+ return lookup_result(0, 0);
}
// We have a small array. Look into it.
unsigned Size = LookupPtr.getInt();
- NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
+ ScopedDecl **Array = static_cast<ScopedDecl**>(LookupPtr.getPointer());
for (unsigned Idx = 0; Idx != Size; ++Idx)
if (Array[Idx]->getDeclName() == Name) {
- Result.first = &Array[Idx];
- Result.second = Result.first + 1;
- if (Idx + 1 < Size && Array[Idx + 1]->getDeclName() == Name)
- ++Result.second;
- break;
+ unsigned Last = Idx + 1;
+ while (Last != Size && Array[Last]->getDeclName() == Name)
+ ++Last;
+ return lookup_result(&Array[Idx], &Array[Last]);
}
- return Result;
+ return lookup_result(0, 0);
}
DeclContext::lookup_const_result
@@ -539,7 +529,7 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) const {
return const_cast<DeclContext*>(this)->lookup(Context, Name);
}
-void DeclContext::insert(ASTContext &Context, NamedDecl *D) {
+void DeclContext::insert(ASTContext &Context, ScopedDecl *D) {
DeclContext *PrimaryContext = getPrimaryContext(Context);
if (PrimaryContext != this) {
PrimaryContext->insert(Context, D);
@@ -553,60 +543,80 @@ void DeclContext::insert(ASTContext &Context, NamedDecl *D) {
insertImpl(D);
}
-void DeclContext::insertImpl(NamedDecl *D) {
+static bool isRedeclarationOf(ScopedDecl *D, ScopedDecl *OldD) {
+ assert(D->getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ // For function declarations, we keep track of redeclarations.
+ return FD->getPreviousDeclaration() == OldD;
+
+ // For non-function declarations, if the declarations are of the
+ // same kind then this must be a redeclaration, or semantic analysis
+ // would not have given us the new declaration.
+ return D->getKind() == OldD->getKind();
+}
+
+void DeclContext::insertImpl(ScopedDecl *D) {
+ bool MayBeRedeclaration = true;
+
if (!isLookupMap()) {
unsigned Size = LookupPtr.getInt();
// The lookup data is stored as an array. Search through the array
// to find the insertion location.
- NamedDecl **Array;
+ ScopedDecl **Array;
if (Size == 0) {
- Array = new NamedDecl*[LookupIsMap - 1];
+ Array = new ScopedDecl*[LookupIsMap - 1];
LookupPtr.setPointer(Array);
} else {
- Array = static_cast<NamedDecl **>(LookupPtr.getPointer());
+ Array = static_cast<ScopedDecl **>(LookupPtr.getPointer());
}
// We always keep declarations of the same name next to each other
// in the array, so that it is easy to return multiple results
- // from lookup(). There will be zero, one, or two declarations of
- // the same name.
- unsigned Match;
- for (Match = 0; Match != Size; ++Match)
- if (Array[Match]->getDeclName() == D->getDeclName())
+ // from lookup().
+ unsigned FirstMatch;
+ for (FirstMatch = 0; FirstMatch != Size; ++FirstMatch)
+ if (Array[FirstMatch]->getDeclName() == D->getDeclName())
break;
- if (Match != Size) {
- // We found another declaration with the same name. If it's also
- // in the same identifier namespace, update the declaration in
- // place.
- Decl::IdentifierNamespace NS = D->getIdentifierNamespace();
- if (Array[Match]->getIdentifierNamespace() == NS) {
- Array[Match] = D;
- return;
- }
- if (Match + 1 < Size && Array[Match + 1]->getIdentifierNamespace() == NS) {
- Array[Match + 1] = D;
- return;
+ unsigned InsertPos = FirstMatch;
+ if (FirstMatch != Size) {
+ // We found another declaration with the same name. First
+ // determine whether this is a redeclaration of an existing
+ // declaration in this scope, in which case we will replace the
+ // existing declaration.
+ unsigned LastMatch = FirstMatch;
+ for (; LastMatch != Size; ++LastMatch) {
+ if (Array[LastMatch]->getDeclName() != D->getDeclName())
+ break;
+
+ if (isRedeclarationOf(D, Array[LastMatch])) {
+ // D is a redeclaration of an existing element in the
+ // array. Replace that element with D.
+ Array[LastMatch] = D;
+ return;
+ }
}
- // If there is an existing declaration in the namespace of
- // ordinary identifiers, then it must precede the tag
- // declaration for C++ name lookup to operate properly. Therefore,
- // if our match is an ordinary name and the new name is in the
- // tag namespace, we'll insert the new declaration after it.
- if (Match != Size && (NS == Decl::IDNS_Tag) &&
- (Array[Match]->getIdentifierNamespace() & Decl::IDNS_Ordinary))
- ++Match;
+ // [FirstMatch, LastMatch) contains the set of declarations that
+ // have the same name as this declaration. Determine where the
+ // declaration D will be inserted into this range.
+ if (D->getIdentifierNamespace() == Decl::IDNS_Tag)
+ InsertPos = LastMatch;
+ else if (Array[LastMatch-1]->getIdentifierNamespace() == Decl::IDNS_Tag)
+ InsertPos = LastMatch - 1;
+ else
+ InsertPos = LastMatch;
}
if (Size < LookupIsMap - 1) {
// The new declaration will fit in the array. Insert the new
// declaration at the position Match in the array.
- for (unsigned Idx = Size; Idx > Match; --Idx)
+ for (unsigned Idx = Size; Idx > InsertPos; --Idx)
Array[Idx] = Array[Idx-1];
- Array[Match] = D;
+ Array[InsertPos] = D;
LookupPtr.setInt(Size + 1);
return;
}
@@ -621,20 +631,37 @@ void DeclContext::insertImpl(NamedDecl *D) {
delete [] Array;
// Fall through to perform insertion into the map.
- }
+ MayBeRedeclaration = false;
+ }
// Insert this declaration into the map.
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
StoredDeclsMap::iterator Pos = Map->find(D->getDeclName());
- unsigned IndexOfD = D->getIdentifierNamespace() & Decl::IDNS_Ordinary? 0 : 1;
+ if (Pos != Map->end()) {
+ if (MayBeRedeclaration) {
+ // Determine if this declaration is actually a redeclaration.
+ for (std::vector<ScopedDecl *>::iterator I = Pos->second.begin(),
+ IEnd = Pos->second.end();
+ I != IEnd; ++I) {
+ if (isRedeclarationOf(D, *I)) {
+ // D is a redeclaration of *I. Replace *I with D and we're
+ // done.
+ *I = D;
+ return;
+ }
+ }
+ }
- if (Pos == Map->end()) {
// Put this declaration into the appropriate slot.
- TwoNamedDecls Val;
- Val.Decls[IndexOfD] = D;
- Val.Decls[!IndexOfD] = 0;
- Map->insert(std::make_pair(D->getDeclName(),Val)).first;
+ if (D->getIdentifierNamespace() == Decl::IDNS_Tag || Pos->second.empty())
+ Pos->second.push_back(D);
+ else if (Pos->second.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
+ ScopedDecl *TagD = Pos->second.back();
+ Pos->second.back() = D;
+ Pos->second.push_back(TagD);
+ } else
+ Pos->second.push_back(D);
} else {
- Pos->second.Decls[IndexOfD] = D;
+ (*Map)[D->getDeclName()].push_back(D);
}
}