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) {
return 0;
}
- virtual ExprResult ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ virtual ExprResult ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc,
SourceLocation TypeLoc, TypeTy *Arg1,
OffsetOfComponent *CompPtr,
unsigned NumComponents,
case EnumConstant:
case NonTypeTemplateParm:
case Field:
+ case ObjCAtDefsField:
+ case ObjCIvar:
case ObjCInterface:
case ObjCCompatibleAlias:
case OverloadedFunction:
/// 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
};
/// 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
/// 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>
/// 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()) {
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);
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) {
} U;
};
- virtual ExprResult ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ virtual ExprResult ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc,
SourceLocation TypeLoc, TypeTy *Arg1,
OffsetOfComponent *CompPtr,
unsigned NumComponents,
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
+#include <vector>
using namespace clang;
//===----------------------------------------------------------------------===//
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();
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;
}
}
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) {
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
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);
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;
}
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);
}
}
}
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();
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.
SourceLocation *CommaLocs,
SourceLocation RParenLoc);
- ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
+ ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
SourceLocation MemberLoc,
IdentifierInfo &Member);
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);
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,
// 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,
// 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;
}
}
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,
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
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();
if (OldReturnType != NewReturnType) {
Diag(New->getLocation(), diag::err_ovl_diff_return_type);
Diag(Old->getLocation(), PrevDiag);
+ Redeclaration = true;
return New;
}
#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>
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()) {
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()))
}
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);
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();
// 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);
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,
// 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);
#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
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.
}
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.
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:
#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>
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);
// (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
// (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
/// (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");
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);
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