Don't explicitly represent OverloadedFunctionDecls within
DeclContext. Instead, just keep the list of currently-active
declarations and only build the OverloadedFunctionDecl when we
absolutely need it.
This is a half-step toward eliminating the need to explicitly build
OverloadedFunctionDecls that store sets of overloaded
functions. This was suggested by Argiris a while back, and it's a good
thing for several reasons: first, it eliminates the messy logic that
currently tries to keep the OverloadedFunctionDecl in sync with the
declarations that are being added. Second, it will (eventually)
eliminate the need to allocate memory for overload sets, which could
help performance. Finally, it helps set us up for when name lookup can
return multiple (possibly ambiguous) results, as can happen with
lookup of class members in C++.
Next steps: make the IdentifierResolver store overloads as separate
entries in its list rather than replacing them with an
OverloadedFunctionDecl now, then see how far we can go toward
eliminating OverloadedFunctionDecl entirely.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61357 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/PrintParserCallbacks.cpp b/Driver/PrintParserCallbacks.cpp
index 3f65628..c97e95a 100644
--- a/Driver/PrintParserCallbacks.cpp
+++ b/Driver/PrintParserCallbacks.cpp
@@ -483,7 +483,8 @@
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
- virtual ExprResult ActOnMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc,
+ virtual ExprResult ActOnMemberReferenceExpr(Scope *S, ExprTy *Base,
+ SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
IdentifierInfo &Member) {
@@ -565,7 +566,7 @@
return 0;
}
- virtual ExprResult ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ virtual ExprResult ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc,
SourceLocation TypeLoc, TypeTy *Arg1,
OffsetOfComponent *CompPtr,
unsigned NumComponents,
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 68a4846..9ceb780 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -191,6 +191,8 @@
case EnumConstant:
case NonTypeTemplateParm:
case Field:
+ case ObjCAtDefsField:
+ case ObjCIvar:
case ObjCInterface:
case ObjCCompatibleAlias:
case OverloadedFunction:
@@ -267,8 +269,7 @@
/// LookupPtrKind - Describes what kind of pointer LookupPtr
/// actually is.
enum LookupPtrKind {
- /// LookupIsMap - Indicates that LookupPtr is actually a
- /// DenseMap<DeclarationName, TwoNamedDecls> pointer.
+ /// LookupIsMap - Indicates that LookupPtr is actually a map.
LookupIsMap = 7
};
@@ -276,9 +277,10 @@
/// declarations within this context. If the context contains fewer
/// than seven declarations, the number of declarations is provided
/// in the 3 lowest-order bits and the upper bits are treated as a
- /// pointer to an array of NamedDecl pointers. If the context
+ /// pointer to an array of ScopedDecl pointers. If the context
/// contains seven or more declarations, the upper bits are treated
- /// as a pointer to a DenseMap<DeclarationName, TwoNamedDecls>.
+ /// as a pointer to a DenseMap<DeclarationName, std::vector<ScopedDecl>>.
+ /// FIXME: We need a better data structure for this.
llvm::PointerIntPair<void*, 3> LookupPtr;
/// Decls - Contains all of the declarations that are defined inside
@@ -440,11 +442,11 @@
/// lookup_iterator - An iterator that provides access to the results
/// of looking up a name within this context.
- typedef NamedDecl **lookup_iterator;
+ typedef ScopedDecl **lookup_iterator;
/// lookup_const_iterator - An iterator that provides non-mutable
/// access to the results of lookup up a name within this context.
- typedef NamedDecl * const * lookup_const_iterator;
+ typedef ScopedDecl * const * lookup_const_iterator;
typedef std::pair<lookup_iterator, lookup_iterator> lookup_result;
typedef std::pair<lookup_const_iterator, lookup_const_iterator>
@@ -471,7 +473,7 @@
/// that this replacement is semantically correct, e.g., that
/// declarations are only replaced by later declarations of the same
/// entity and not a declaration of some other kind of entity.
- void insert(ASTContext &Context, NamedDecl *D);
+ void insert(ASTContext &Context, ScopedDecl *D);
static bool classof(const Decl *D) {
switch (D->getKind()) {
@@ -503,7 +505,7 @@
static bool classof(const BlockDecl *D) { return true; }
private:
- void insertImpl(NamedDecl *D);
+ void insertImpl(ScopedDecl *D);
void EmitOutRec(llvm::Serializer& S) const;
void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 249f122..39de870 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -569,7 +569,8 @@
ExprTy *Idx, SourceLocation RLoc) {
return 0;
}
- virtual ExprResult ActOnMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc,
+ virtual ExprResult ActOnMemberReferenceExpr(Scope *S, ExprTy *Base,
+ SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
IdentifierInfo &Member) {
@@ -650,7 +651,7 @@
} U;
};
- virtual ExprResult ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ virtual ExprResult ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc,
SourceLocation TypeLoc, TypeTy *Arg1,
OffsetOfComponent *CompPtr,
unsigned NumComponents,
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 5d70493..87ebf85 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
}
}
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 127ddf4..0c25fab 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -745,8 +745,8 @@
}
if (!LHS.isInvalid()) {
- LHS = Actions.ActOnMemberReferenceExpr(LHS.release(), OpLoc, OpKind,
- Tok.getLocation(),
+ LHS = Actions.ActOnMemberReferenceExpr(CurScope, LHS.release(), OpLoc,
+ OpKind, Tok.getLocation(),
*Tok.getIdentifierInfo());
}
ConsumeToken();
@@ -920,8 +920,9 @@
Comps.back().LocEnd =
MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
} else if (Tok.is(tok::r_paren)) {
- Res = Actions.ActOnBuiltinOffsetOf(StartLoc, TypeLoc, Ty, &Comps[0],
- Comps.size(), ConsumeParen());
+ Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc, Ty,
+ &Comps[0], Comps.size(),
+ ConsumeParen());
break;
} else {
// Error occurred.
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 48af5af..2664c57 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -479,7 +479,7 @@
SourceLocation *CommaLocs,
SourceLocation RParenLoc);
- ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
+ ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
SourceLocation MemberLoc,
IdentifierInfo &Member);
@@ -696,7 +696,8 @@
virtual ExprResult ActOnArraySubscriptExpr(Scope *S, ExprTy *Base,
SourceLocation LLoc, ExprTy *Idx,
SourceLocation RLoc);
- virtual ExprResult ActOnMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc,
+ virtual ExprResult ActOnMemberReferenceExpr(Scope *S, ExprTy *Base,
+ SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
IdentifierInfo &Member);
@@ -747,7 +748,8 @@
SourceLocation RPLoc); // "({..})"
/// __builtin_offsetof(type, a.b[123][456].c)
- virtual ExprResult ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ virtual ExprResult ActOnBuiltinOffsetOf(Scope *S,
+ SourceLocation BuiltinLoc,
SourceLocation TypeLoc, TypeTy *Arg1,
OffsetOfComponent *CompPtr,
unsigned NumComponents,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 024ca81..270de55 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -106,7 +106,7 @@
// require some reshuffling in the identifier resolver.
IdentifierResolver::iterator
I = IdResolver.begin(TD->getIdentifier(), CurContext,
- false/*LookInParentCtx*/);
+ false/*LookInParentCtx*/);
if (I != IdResolver.end()) {
// There is already a declaration with the same name in the same
// scope. It must be found before we find the new declaration,
@@ -123,57 +123,47 @@
// We are pushing the name of a function, which might be an
// overloaded name.
FunctionDecl *FD = cast<FunctionDecl>(D);
- Decl *Prev = LookupDecl(FD->getDeclName(), Decl::IDNS_Ordinary, S,
- FD->getDeclContext(), false, false);
- if (Prev && (isa<OverloadedFunctionDecl>(Prev) || isa<FunctionDecl>(Prev))) {
- // There is already a declaration with the same name in
- // the same scope. It must be a function or an overloaded
- // function.
- OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(Prev);
- if (!Ovl) {
- // We haven't yet overloaded this function. Take the existing
- // FunctionDecl and put it into an OverloadedFunctionDecl.
- Ovl = OverloadedFunctionDecl::Create(Context,
- FD->getDeclContext(),
- FD->getDeclName());
- Ovl->addOverload(cast<FunctionDecl>(Prev));
+ if (CurContext == FD->getDeclContext()) {
+ IdentifierResolver::iterator
+ I = IdResolver.begin(FD->getDeclName(), CurContext,
+ false/*LookInParentCtx*/);
+ if (I != IdResolver.end() &&
+ (isa<OverloadedFunctionDecl>(*I) || isa<FunctionDecl>(*I))) {
+ // There is already a declaration with the same name in
+ // the same scope. It must be a function or an overloaded
+ // function.
+ OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(*I);
+ if (!Ovl) {
+ // We haven't yet overloaded this function. Take the existing
+ // FunctionDecl and put it into an OverloadedFunctionDecl.
+ Ovl = OverloadedFunctionDecl::Create(Context,
+ FD->getDeclContext(),
+ FD->getDeclName());
+ Ovl->addOverload(cast<FunctionDecl>(*I));
+
+ IdResolver.RemoveDecl(*I);
+ S->RemoveDecl(*I);
- // If there is a name binding for the existing FunctionDecl,
- // remove it.
- for (IdentifierResolver::iterator I
- = IdResolver.begin(FD->getDeclName(), FD->getDeclContext(),
- false/*LookInParentCtx*/),
- E = IdResolver.end(); I != E; ++I) {
- if (*I == Prev) {
- IdResolver.RemoveDecl(*I);
- S->RemoveDecl(*I);
- break;
- }
+ // Add the name binding for the OverloadedFunctionDecl.
+ IdResolver.AddDecl(Ovl);
+
+ S->AddDecl(Ovl);
}
-
- // Add the name binding for the OverloadedFunctionDecl.
- IdResolver.AddDecl(Ovl);
- // Update the context with the newly-created overloaded
- // function set.
- FD->getDeclContext()->insert(Context, Ovl);
-
- S->AddDecl(Ovl);
+ // We added this function declaration to the scope earlier, but
+ // we don't want it there because it is part of the overloaded
+ // function declaration.
+ S->RemoveDecl(FD);
+
+ // We have an OverloadedFunctionDecl. Add the new FunctionDecl
+ // to its list of overloads.
+ Ovl->addOverload(FD);
+
+ // Add this new function declaration to the declaration context.
+ CurContext->addDecl(Context, FD);
+
+ return;
}
-
- // We added this function declaration to the scope earlier, but
- // we don't want it there because it is part of the overloaded
- // function declaration.
- S->RemoveDecl(FD);
-
- // We have an OverloadedFunctionDecl. Add the new FunctionDecl
- // to its list of overloads.
- Ovl->addOverload(FD);
-
- // Add this new function declaration to the declaration context.
- CurContext->addDecl(Context, FD, false);
-
- return;
}
}
@@ -216,6 +206,52 @@
return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
}
+/// MaybeConstructOverloadSet - Name lookup has determined that the
+/// elements in [I, IEnd) have the name that we are looking for, and
+/// *I is a match for the namespace. This routine returns an
+/// appropriate Decl for name lookup, which may either be *I or an
+/// OverloadeFunctionDecl that represents the overloaded functions in
+/// [I, IEnd).
+///
+/// The existance of this routine is temporary; LookupDecl should
+/// probably be able to return multiple results, to deal with cases of
+/// ambiguity and overloaded functions without needing to create a
+/// Decl node.
+static Decl *
+MaybeConstructOverloadSet(ASTContext &Context, const DeclContext *DC,
+ DeclContext::lookup_const_iterator I,
+ DeclContext::lookup_const_iterator IEnd) {
+ assert(I != IEnd && "Iterator range cannot be empty");
+ assert(!isa<OverloadedFunctionDecl>(*I) &&
+ "Cannot have an overloaded function");
+
+ if (isa<FunctionDecl>(*I)) {
+ // If we found a function, there might be more functions. If
+ // so, collect them into an overload set.
+ DeclContext::lookup_const_iterator Last = I;
+ OverloadedFunctionDecl *Ovl = 0;
+ for (++Last; Last != IEnd && isa<FunctionDecl>(*Last); ++Last) {
+ if (!Ovl) {
+ // FIXME: We leak this overload set. Eventually, we want to
+ // stop building the declarations for these overload sets, so
+ // there will be nothing to leak.
+ Ovl = OverloadedFunctionDecl::Create(Context,
+ const_cast<DeclContext *>(DC),
+ (*I)->getDeclName());
+ Ovl->addOverload(cast<FunctionDecl>(*I));
+ }
+ Ovl->addOverload(cast<FunctionDecl>(*Last));
+ }
+
+ // If we had more than one function, we built an overload
+ // set. Return it.
+ if (Ovl)
+ return Ovl;
+ }
+
+ return *I;
+}
+
/// LookupDecl - Look up the inner-most declaration in the specified
/// namespace.
Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
@@ -244,14 +280,12 @@
if ((*I)->getIdentifierNamespace() & NS)
return *I;
} else if (LookupCtx) {
- assert(getLangOptions().CPlusPlus && "No qualified name lookup in C");
-
// Perform qualified name lookup into the LookupCtx.
// FIXME: Will need to look into base classes and such.
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I)
if ((*I)->getIdentifierNamespace() & NS)
- return *I;
+ return MaybeConstructOverloadSet(Context, LookupCtx, I, E);
} else {
// Name lookup for ordinary names and tag names in C++ requires
// looking into scopes that aren't strictly lexical, and
@@ -279,7 +313,7 @@
for (llvm::tie(I, E) = Ctx->lookup(Context, Name); I != E; ++I) {
// FIXME: Cache this result in the IdResolver
if ((*I)->getIdentifierNamespace() & NS)
- return *I;
+ return MaybeConstructOverloadSet(Context, LookupCtx, I, E);
}
Ctx = Ctx->getParent();
@@ -533,6 +567,7 @@
if (OldReturnType != NewReturnType) {
Diag(New->getLocation(), diag::err_ovl_diff_return_type);
Diag(Old->getLocation(), PrevDiag);
+ Redeclaration = true;
return New;
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8a37bbb..918fd2a 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -20,6 +20,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/DeclSpec.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include <algorithm> // for std::equal
#include <map>
@@ -844,23 +845,7 @@
CopyConstructor->setParams(&FromParam, 1);
ClassDecl->addedConstructor(Context, CopyConstructor);
- DeclContext::lookup_result Lookup = ClassDecl->lookup(Context, Name);
- if (Lookup.first == Lookup.second
- || (!isa<CXXConstructorDecl>(*Lookup.first) &&
- !isa<OverloadedFunctionDecl>(*Lookup.first)))
- ClassDecl->addDecl(Context, CopyConstructor);
- else {
- OverloadedFunctionDecl *Ovl
- = dyn_cast<OverloadedFunctionDecl>(*Lookup.first);
- if (!Ovl) {
- Ovl = OverloadedFunctionDecl::Create(Context, ClassDecl, Name);
- Ovl->addOverload(cast<CXXConstructorDecl>(*Lookup.first));
- ClassDecl->insert(Context, Ovl);
- }
-
- Ovl->addOverload(CopyConstructor);
- ClassDecl->addDecl(Context, CopyConstructor, false);
- }
+ ClassDecl->addDecl(Context, CopyConstructor);
}
if (!ClassDecl->hasUserDeclaredDestructor()) {
@@ -1470,23 +1455,10 @@
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType.getUnqualifiedType()));
- DeclContext::lookup_const_result Lookup
- = ClassDecl->lookup(Context, ConstructorName);
- if (Lookup.first == Lookup.second)
- /* No constructors */;
- else if (OverloadedFunctionDecl *Constructors
- = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
- for (OverloadedFunctionDecl::function_iterator Con
- = Constructors->function_begin();
- Con != Constructors->function_end(); ++Con) {
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
- if ((Kind == IK_Direct) ||
- (Kind == IK_Copy && Constructor->isConvertingConstructor()) ||
- (Kind == IK_Default && Constructor->isDefaultConstructor()))
- AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
- }
- } else if (CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(Context, ConstructorName);
+ Con != ConEnd; ++Con) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
if ((Kind == IK_Direct) ||
(Kind == IK_Copy && Constructor->isConvertingConstructor()) ||
(Kind == IK_Default && Constructor->isDefaultConstructor()))
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 307e1ad..4088f44 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1254,7 +1254,7 @@
}
Action::ExprResult Sema::
-ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
+ActOnMemberReferenceExpr(Scope *S, ExprTy *Base, SourceLocation OpLoc,
tok::TokenKind OpKind, SourceLocation MemberLoc,
IdentifierInfo &Member) {
Expr *BaseExpr = static_cast<Expr *>(Base);
@@ -1272,7 +1272,7 @@
if (const PointerType *PT = BaseType->getAsPointerType())
BaseType = PT->getPointeeType();
else if (getLangOptions().CPlusPlus && BaseType->isRecordType())
- return BuildOverloadedArrowExpr(BaseExpr, OpLoc, MemberLoc, Member);
+ return BuildOverloadedArrowExpr(S, BaseExpr, OpLoc, MemberLoc, Member);
else
return Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
<< BaseType << BaseExpr->getSourceRange();
@@ -1288,42 +1288,42 @@
// The record definition is complete, now make sure the member is valid.
// FIXME: Qualified name lookup for C++ is a bit more complicated
// than this.
- DeclContext::lookup_result Lookup = RDecl->lookup(Context, &Member);
- if (Lookup.first == Lookup.second) {
+ Decl *MemberDecl = LookupDecl(DeclarationName(&Member), Decl::IDNS_Ordinary,
+ S, RDecl, false, false);
+ if (!MemberDecl)
return Diag(MemberLoc, diag::err_typecheck_no_member)
<< &Member << BaseExpr->getSourceRange();
- }
- if (FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*Lookup.first)) {
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
// Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
// FIXME: Handle address space modifiers
- QualType MemberType = MemberDecl->getType();
+ QualType MemberType = FD->getType();
if (const ReferenceType *Ref = MemberType->getAsReferenceType())
MemberType = Ref->getPointeeType();
else {
unsigned combinedQualifiers =
MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
- if (MemberDecl->isMutable())
+ if (FD->isMutable())
combinedQualifiers &= ~QualType::Const;
MemberType = MemberType.getQualifiedType(combinedQualifiers);
}
- return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl,
+ return new MemberExpr(BaseExpr, OpKind == tok::arrow, FD,
MemberLoc, MemberType);
- } else if (CXXClassVarDecl *Var = dyn_cast<CXXClassVarDecl>(*Lookup.first))
+ } else if (CXXClassVarDecl *Var = dyn_cast<CXXClassVarDecl>(MemberDecl))
return new MemberExpr(BaseExpr, OpKind == tok::arrow, Var, MemberLoc,
Var->getType().getNonReferenceType());
- else if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(*Lookup.first))
+ else if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl))
return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberFn, MemberLoc,
MemberFn->getType());
else if (OverloadedFunctionDecl *Ovl
- = dyn_cast<OverloadedFunctionDecl>(*Lookup.first))
+ = dyn_cast<OverloadedFunctionDecl>(MemberDecl))
return new MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl, MemberLoc,
Context.OverloadTy);
- else if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(*Lookup.first))
+ else if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl))
return new MemberExpr(BaseExpr, OpKind == tok::arrow, Enum, MemberLoc,
Enum->getType());
- else if (isa<TypeDecl>(*Lookup.first))
+ else if (isa<TypeDecl>(MemberDecl))
return Diag(MemberLoc, diag::err_typecheck_member_reference_type)
<< DeclarationName(&Member) << int(OpKind == tok::arrow);
@@ -3573,7 +3573,8 @@
return new StmtExpr(Compound, Ty, LPLoc, RPLoc);
}
-Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+Sema::ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
+ SourceLocation BuiltinLoc,
SourceLocation TypeLoc,
TypeTy *argty,
OffsetOfComponent *CompPtr,
@@ -3628,11 +3629,10 @@
// Get the decl corresponding to this.
RecordDecl *RD = RC->getDecl();
- FieldDecl *MemberDecl = 0;
- DeclContext::lookup_result Lookup = RD->lookup(Context, OC.U.IdentInfo);
- if (Lookup.first != Lookup.second)
- MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
-
+ FieldDecl *MemberDecl
+ = dyn_cast_or_null<FieldDecl>(LookupDecl(OC.U.IdentInfo,
+ Decl::IDNS_Ordinary,
+ S, RD, false, false));
if (!MemberDecl)
return Diag(BuiltinLoc, diag::err_typecheck_no_member)
<< OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd);
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index e18f143..eb2e647 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -18,6 +18,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/STLExtras.h"
using namespace clang;
/// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
@@ -412,8 +413,9 @@
DeclContext *Ctx, bool AllowMissing,
FunctionDecl *&Operator)
{
- DeclContext::lookup_result Lookup = Ctx->lookup(Context, Name);
- if (Lookup.first == Lookup.second) {
+ DeclContext::lookup_iterator Alloc, AllocEnd;
+ llvm::tie(Alloc, AllocEnd) = Ctx->lookup(Context, Name);
+ if (Alloc == AllocEnd) {
if (AllowMissing)
return false;
// FIXME: Bad location information.
@@ -422,21 +424,12 @@
}
OverloadCandidateSet Candidates;
- NamedDecl *Decl = *Lookup.first;
- // Even member operator new/delete are implicitly treated as static, so don't
- // use AddMemberCandidate.
- if (FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Decl))
- AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
- /*SuppressUserConversions=*/false);
- else if (OverloadedFunctionDecl *Ovl
- = dyn_cast_or_null<OverloadedFunctionDecl>(Decl)) {
- for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
- FEnd = Ovl->function_end();
- F != FEnd; ++F) {
- if (FunctionDecl *Fn = *F)
- AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
- /*SuppressUserConversions=*/false);
- }
+ for (; Alloc != AllocEnd; ++Alloc) {
+ // Even member operator new/delete are implicitly treated as
+ // static, so don't use AddMemberCandidate.
+ if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(*Alloc))
+ AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
+ /*SuppressUserConversions=*/false);
}
// Do the resolution.
@@ -555,7 +548,7 @@
0, Argument, VarDecl::None, 0, 0);
Alloc->setParams(&Param, 1);
- PushOnScopeChains(Alloc, TUScope);
+ ((DeclContext *)TUScope->getEntity())->addDecl(Context, Alloc);
}
/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 8365349..8463c5d 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeOrdering.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
@@ -1106,22 +1107,10 @@
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ToType));
- DeclContext::lookup_result Lookup
- = ToRecordDecl->lookup(Context, ConstructorName);
- if (Lookup.first == Lookup.second)
- /* No constructors. FIXME: Implicit copy constructor? */;
- else if (OverloadedFunctionDecl *Constructors
- = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
- for (OverloadedFunctionDecl::function_const_iterator func
- = Constructors->function_begin();
- func != Constructors->function_end(); ++func) {
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*func);
- if (Constructor->isConvertingConstructor())
- AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
- /*SuppressUserConversions=*/true);
- }
- } else if (CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
+ DeclContext::lookup_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = ToRecordDecl->lookup(Context, ConstructorName);
+ Con != ConEnd; ++Con) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
if (Constructor->isConvertingConstructor())
AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
/*SuppressUserConversions=*/true);
@@ -2142,22 +2131,12 @@
// (13.3.1.1.1); otherwise, the set of member candidates is
// empty.
if (const RecordType *T1Rec = T1->getAsRecordType()) {
- DeclContext::lookup_const_result Lookup
- = T1Rec->getDecl()->lookup(Context, OpName);
- NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
- if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
- AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet,
+ DeclContext::lookup_const_iterator Oper, OperEnd;
+ for (llvm::tie(Oper, OperEnd) = T1Rec->getDecl()->lookup(Context, OpName);
+ Oper != OperEnd; ++Oper)
+ AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Args[0],
+ Args+1, NumArgs - 1, CandidateSet,
/*SuppressUserConversions=*/false);
- else if (OverloadedFunctionDecl *Ovl
- = dyn_cast_or_null<OverloadedFunctionDecl>(MemberOps)) {
- for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
- FEnd = Ovl->function_end();
- F != FEnd; ++F) {
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*F))
- AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet,
- /*SuppressUserConversions=*/false);
- }
- }
}
// -- The set of non-member candidates is the result of the
@@ -3405,22 +3384,11 @@
// (E).operator().
OverloadCandidateSet CandidateSet;
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
- DeclContext::lookup_const_result Lookup
- = Record->getDecl()->lookup(Context, OpName);
- NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
- if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
- AddMethodCandidate(Method, Object, Args, NumArgs, CandidateSet,
- /*SuppressUserConversions=*/false);
- else if (OverloadedFunctionDecl *Ovl
- = dyn_cast_or_null<OverloadedFunctionDecl>(MemberOps)) {
- for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
- FEnd = Ovl->function_end();
- F != FEnd; ++F) {
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*F))
- AddMethodCandidate(Method, Object, Args, NumArgs, CandidateSet,
- /*SuppressUserConversions=*/false);
- }
- }
+ DeclContext::lookup_const_iterator Oper, OperEnd;
+ for (llvm::tie(Oper, OperEnd) = Record->getDecl()->lookup(Context, OpName);
+ Oper != OperEnd; ++Oper)
+ AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs,
+ CandidateSet, /*SuppressUserConversions=*/false);
// C++ [over.call.object]p2:
// In addition, for each conversion function declared in T of the
@@ -3585,7 +3553,7 @@
/// (if one exists), where @c Base is an expression of class type and
/// @c Member is the name of the member we're trying to find.
Action::ExprResult
-Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
+Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
SourceLocation MemberLoc,
IdentifierInfo &Member) {
assert(Base->getType()->isRecordType() && "left-hand side must have class type");
@@ -3600,22 +3568,12 @@
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
OverloadCandidateSet CandidateSet;
const RecordType *BaseRecord = Base->getType()->getAsRecordType();
- DeclContext::lookup_const_result Lookup
- = BaseRecord->getDecl()->lookup(Context, OpName);
- NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
- if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
- AddMethodCandidate(Method, Base, 0, 0, CandidateSet,
+
+ DeclContext::lookup_const_iterator Oper, OperEnd;
+ for (llvm::tie(Oper, OperEnd) = BaseRecord->getDecl()->lookup(Context, OpName);
+ Oper != OperEnd; ++Oper)
+ AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Base, 0, 0, CandidateSet,
/*SuppressUserConversions=*/false);
- else if (OverloadedFunctionDecl *Ovl
- = dyn_cast_or_null<OverloadedFunctionDecl>(MemberOps)) {
- for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
- FEnd = Ovl->function_end();
- F != FEnd; ++F) {
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*F))
- AddMethodCandidate(Method, Base, 0, 0, CandidateSet,
- /*SuppressUserConversions=*/false);
- }
- }
llvm::OwningPtr<Expr> BasePtr(Base);
@@ -3658,7 +3616,7 @@
Base = new CXXOperatorCallExpr(FnExpr, &Base, 1,
Method->getResultType().getNonReferenceType(),
OpLoc);
- return ActOnMemberReferenceExpr(Base, OpLoc, tok::arrow, MemberLoc, Member);
+ return ActOnMemberReferenceExpr(S, Base, OpLoc, tok::arrow, MemberLoc, Member);
}
/// FixOverloadedFunctionReference - E is an expression that refers to