summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2008-12-11 16:49:14 +0000
committerDouglas Gregor <dgregor@apple.com>2008-12-11 16:49:14 +0000
commit91f84216f78f52f9aae422a2a034c1c7eaa098ce (patch)
treefc0c4c5b68ca37cab2115e3d2564ed36cb016b69 /clang/lib/Sema
parent32bfb5de3408728c5da5101db863098a8f854848 (diff)
downloadbcm5719-llvm-91f84216f78f52f9aae422a2a034c1c7eaa098ce.tar.gz
bcm5719-llvm-91f84216f78f52f9aae422a2a034c1c7eaa098ce.zip
Unifies the name-lookup mechanisms used in various parts of the AST
and separates lexical name lookup from qualified name lookup. In particular: * Make DeclContext the central data structure for storing and looking up declarations within existing declarations, e.g., members of structs/unions/classes, enumerators in C++0x enums, members of C++ namespaces, and (later) members of Objective-C interfaces/implementations. DeclContext uses a lazily-constructed data structure optimized for fast lookup (array for small contexts, hash table for larger contexts). * Implement C++ qualified name lookup in terms of lookup into DeclContext. * Implement C++ unqualified name lookup in terms of qualified+unqualified name lookup (since unqualified lookup is not purely lexical in C++!) * Limit the use of the chains of declarations stored in IdentifierInfo to those names declared lexically. * Eliminate CXXFieldDecl, collapsing its behavior into FieldDecl. (FieldDecl is now a ScopedDecl). * Make RecordDecl into a DeclContext and eliminates its Members/NumMembers fields (since one can just iterate through the DeclContext to get the fields). llvm-svn: 60878
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/CXXFieldCollector.h10
-rw-r--r--clang/lib/Sema/IdentifierResolver.cpp7
-rw-r--r--clang/lib/Sema/IdentifierResolver.h3
-rw-r--r--clang/lib/Sema/Sema.cpp2
-rw-r--r--clang/lib/Sema/Sema.h11
-rw-r--r--clang/lib/Sema/SemaCXXScopeSpec.cpp25
-rw-r--r--clang/lib/Sema/SemaDecl.cpp297
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp6
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp73
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp32
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp7
-rw-r--r--clang/lib/Sema/SemaInit.cpp28
-rw-r--r--clang/lib/Sema/SemaOverload.cpp23
14 files changed, 343 insertions, 183 deletions
diff --git a/clang/lib/Sema/CXXFieldCollector.h b/clang/lib/Sema/CXXFieldCollector.h
index 44d482692b7..69d13515fa6 100644
--- a/clang/lib/Sema/CXXFieldCollector.h
+++ b/clang/lib/Sema/CXXFieldCollector.h
@@ -18,15 +18,15 @@
#include "llvm/ADT/SmallVector.h"
namespace clang {
- class CXXFieldDecl;
+ class FieldDecl;
/// CXXFieldCollector - Used to keep track of CXXFieldDecls during parsing of
/// C++ classes.
class CXXFieldCollector {
- /// Fields - Contains all CXXFieldDecls collected during parsing of a C++
+ /// Fields - Contains all FieldDecls collected during parsing of a C++
/// class. When a nested class is entered, its fields are appended to the
/// fields of its parent class, when it is exited its fields are removed.
- llvm::SmallVector<CXXFieldDecl*, 32> Fields;
+ llvm::SmallVector<FieldDecl*, 32> Fields;
/// FieldCount - Each entry represents the number of fields collected during
/// the parsing of a C++ class. When a nested class is entered, a new field
@@ -52,7 +52,7 @@ public:
void StartClass() { FieldCount.push_back(0); }
/// Add - Called by Sema::ActOnCXXMemberDeclarator.
- void Add(CXXFieldDecl *D) {
+ void Add(FieldDecl *D) {
Fields.push_back(D);
++FieldCount.back();
}
@@ -62,7 +62,7 @@ public:
/// getCurFields - Pointer to array of fields added to the currently parsed
/// class.
- CXXFieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
+ FieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
/// FinishClass - Called by Sema::ActOnFinishCXXClassDef.
void FinishClass() {
diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp
index 5fb18f6cef4..4441503528a 100644
--- a/clang/lib/Sema/IdentifierResolver.cpp
+++ b/clang/lib/Sema/IdentifierResolver.cpp
@@ -51,9 +51,6 @@ public:
DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) {
DeclContext *Ctx;
- if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D))
- return FD->getParent();
-
if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {
Ctx = EnumD->getDeclContext()->getParent();
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
@@ -149,7 +146,7 @@ IdentifierResolver::~IdentifierResolver() {
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
- Scope *S) const {
+ ASTContext &Context, Scope *S) const {
if (Ctx->isFunctionOrMethod()) {
if (S->isDeclScope(D))
return true;
@@ -169,7 +166,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
return false;
}
- return LookupContext(D) == LookupContext(Ctx);
+ return LookupContext(D) == LookupContext(Ctx->getPrimaryContext(Context));
}
/// AddDecl - Link the decl to its shadowed decl chain.
diff --git a/clang/lib/Sema/IdentifierResolver.h b/clang/lib/Sema/IdentifierResolver.h
index 9d785133957..bc9da6126d0 100644
--- a/clang/lib/Sema/IdentifierResolver.h
+++ b/clang/lib/Sema/IdentifierResolver.h
@@ -208,7 +208,8 @@ public:
/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
- bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) const;
+ bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context,
+ Scope *S = 0) const;
/// AddDecl - Link the decl to its shadowed decl chain.
void AddDecl(NamedDecl *D);
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 13226c0b0ea..650b8d7d7dd 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -68,7 +68,7 @@ static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
TUScope = S;
- PushDeclContext(Context.getTranslationUnitDecl());
+ PushDeclContext(S, Context.getTranslationUnitDecl());
if (!PP.getLangOptions().ObjC1) return;
// Synthesize "typedef struct objc_selector *SEL;"
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 4a8f83084dd..97e8507e9b3 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -300,10 +300,10 @@ public:
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr);
- virtual void ActOnDefs(Scope *S, SourceLocation DeclStart,
+ virtual void ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
IdentifierInfo *ClassName,
llvm::SmallVectorImpl<DeclTy*> &Decls);
- virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart,
+ virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
Declarator &D, ExprTy *BitfieldWidth);
virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart,
@@ -326,7 +326,7 @@ public:
DeclContext *getContainingDC(DeclContext *DC);
/// Set the current declaration context until it gets popped.
- void PushDeclContext(DeclContext *DC);
+ void PushDeclContext(Scope *S, DeclContext *DC);
void PopDeclContext();
/// getCurFunctionDecl - If inside of a function body, this returns a pointer
@@ -351,7 +351,7 @@ public:
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) {
- return IdResolver.isDeclInScope(D, Ctx, S);
+ return IdResolver.isDeclInScope(D, Ctx, Context, S);
}
/// Subroutines of ActOnDeclarator().
@@ -478,7 +478,8 @@ public:
/// More parsing and symbol table subroutines...
Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
const DeclContext *LookupCtx = 0,
- bool enableLazyBuiltinCreation = true);
+ bool enableLazyBuiltinCreation = true,
+ bool LookInParent = true);
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Scope *S);
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 1f92b6f6aab..d01552c373b 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -20,7 +20,25 @@ using namespace clang;
namespace {
Decl *LookupNestedName(DeclContext *LookupCtx, bool LookInParentCtx,
- DeclarationName Name, bool &IdIsUndeclared) {
+ DeclarationName Name, bool &IdIsUndeclared,
+ ASTContext &Context) {
+ if (LookupCtx && !LookInParentCtx) {
+ IdIsUndeclared = true;
+ for (DeclContext::lookup_const_result I = LookupCtx->lookup(Context, Name);
+ I.first != I.second; ++I.first) {
+ IdIsUndeclared = false;
+ if (((*I.first)->getIdentifierNamespace() & Decl::IDNS_Tag) &&
+ !isa<EnumDecl>(*I.first))
+ return *I.first;
+ }
+
+ return 0;
+ }
+
+ // FIXME: Decouple this from the IdentifierResolver so that we can
+ // deal with lookups into the semantic parent contexts that aren't
+ // lexical parent contexts.
+
IdentifierResolver::iterator
I = IdentifierResolver::begin(Name, LookupCtx, LookInParentCtx),
E = IdentifierResolver::end();
@@ -73,10 +91,11 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
bool IdIsUndeclared;
if (DC)
- SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared);
+ SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared,
+ Context);
else
SD = LookupNestedName(CurContext, true/*LookInParent*/, &II,
- IdIsUndeclared);
+ IdIsUndeclared, Context);
if (SD) {
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 41587c5aee6..b541f59a223 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -74,14 +74,16 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) {
return DC->getLexicalParent();
}
-void Sema::PushDeclContext(DeclContext *DC) {
+void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
assert(getContainingDC(DC) == CurContext &&
"The next DeclContext should be lexically contained in the current one.");
CurContext = DC;
+ S->setEntity(DC);
}
void Sema::PopDeclContext() {
assert(CurContext && "DeclContext imbalance!");
+
CurContext = getContainingDC(CurContext);
}
@@ -97,53 +99,90 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
// in this case the class name or enumeration name is hidden.
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
// We are pushing the name of a tag (enum or class).
- IdentifierResolver::iterator
- I = IdResolver.begin(TD->getIdentifier(),
- TD->getDeclContext(), false/*LookInParentCtx*/);
- if (I != IdResolver.end() && isDeclInScope(*I, TD->getDeclContext(), S)) {
- // There is already a declaration with the same name in the same
- // scope. It must be found before we find the new declaration,
- // so swap the order on the shadowed declaration chain.
-
- IdResolver.AddShadowedDecl(TD, *I);
- return;
+ if (CurContext == TD->getDeclContext()) {
+ // We're pushing the tag into the current context, which might
+ // require some reshuffling in the identifier resolver.
+ IdentifierResolver::iterator
+ I = IdResolver.begin(TD->getIdentifier(), CurContext,
+ 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,
+ // so swap the order on the shadowed declaration chain.
+ IdResolver.AddShadowedDecl(TD, *I);
+
+ // Add this declaration to the current context.
+ CurContext->addDecl(Context, TD);
+
+ return;
+ }
}
} else if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
- FunctionDecl *FD = cast<FunctionDecl>(D);
// We are pushing the name of a function, which might be an
// overloaded name.
- IdentifierResolver::iterator
- I = IdResolver.begin(FD->getDeclName(),
- FD->getDeclContext(), false/*LookInParentCtx*/);
- if (I != IdResolver.end() &&
- IdResolver.isDeclInScope(*I, FD->getDeclContext(), S) &&
- (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);
+ 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(dyn_cast<FunctionDecl>(*I));
+ Ovl->addOverload(dyn_cast<FunctionDecl>(Prev));
- // Remove the name binding to the existing FunctionDecl...
- IdResolver.RemoveDecl(*I);
-
- // ... and put the OverloadedFunctionDecl in its place.
+ // If there is an name binding for the existing FunctionDecl,
+ // remove it.
+ for (IdentifierResolver::iterator I
+ = IdResolver.begin(FD->getDeclName(), FD->getDeclContext(),
+ false/*LookInParentCtx*/);
+ I != IdResolver.end(); ++I) {
+ if (*I == Prev) {
+ IdResolver.RemoveDecl(*I);
+ S->RemoveDecl(*I);
+ break;
+ }
+ }
+
+ // 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);
- return;
+ // Add this new function declaration to the declaration context.
+ CurContext->addDecl(Context, FD, false);
+
+ return;
}
}
+ if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
+ CurContext->addDecl(Context, SD);
+ else {
+ // Other kinds of declarations don't currently have a context
+ // where they need to be inserted.
+ }
+
+
IdResolver.AddDecl(D);
}
@@ -157,25 +196,13 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
Decl *TmpD = static_cast<Decl*>(*I);
assert(TmpD && "This decl didn't get pushed??");
- if (isa<CXXFieldDecl>(TmpD)) continue;
+ assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
+ NamedDecl *D = cast<NamedDecl>(TmpD);
- assert(isa<ScopedDecl>(TmpD) && "Decl isn't ScopedDecl?");
- ScopedDecl *D = cast<ScopedDecl>(TmpD);
-
- IdentifierInfo *II = D->getIdentifier();
- if (!II) continue;
-
- // We only want to remove the decls from the identifier decl chains for
- // local scopes, when inside a function/method.
- // However, we *always* remove template parameters, since they are
- // purely lexically scoped (and can never be found by qualified
- // name lookup).
- if (S->getFnParent() != 0 || isa<TemplateTypeParmDecl>(D))
- IdResolver.RemoveDecl(D);
-
- // Chain this decl to the containing DeclContext.
- D->setNext(CurContext->getDeclChain());
- CurContext->setDeclChain(D);
+ if (!D->getDeclName()) continue;
+
+ // Remove this name from our lexical scope.
+ IdResolver.RemoveDecl(D);
}
}
@@ -193,21 +220,76 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
/// namespace.
Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
const DeclContext *LookupCtx,
- bool enableLazyBuiltinCreation) {
+ bool enableLazyBuiltinCreation,
+ bool LookInParent) {
if (!Name) return 0;
unsigned NS = NSI;
if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
NS |= Decl::IDNS_Tag;
- IdentifierResolver::iterator
- I = LookupCtx ? IdResolver.begin(Name, LookupCtx, false/*LookInParentCtx*/)
- : IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/);
- // Scan up the scope chain looking for a decl that matches this identifier
- // that is in the appropriate namespace. This search should not take long, as
- // shadowing of names is uncommon, and deep shadowing is extremely uncommon.
- for (; I != IdResolver.end(); ++I)
- if ((*I)->getIdentifierNamespace() & NS)
- return *I;
+ 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.
+ for (DeclContext::lookup_const_result I = LookupCtx->lookup(Context, Name);
+ I.first != I.second; ++I.first)
+ if ((*I.first)->getIdentifierNamespace() & NS)
+ return *I.first;
+ } else if (getLangOptions().CPlusPlus &&
+ (NS & (Decl::IDNS_Ordinary | Decl::IDNS_Tag))) {
+ // Name lookup for ordinary names and tag names in C++ requires
+ // looking into scopes that aren't strictly lexical, and
+ // therefore we walk through the context as well as walking
+ // through the scopes.
+ IdentifierResolver::iterator
+ I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/),
+ IEnd = IdResolver.end();
+ for (; S; S = S->getParent()) {
+ // Check whether the IdResolver has anything in this scope.
+ // FIXME: The isDeclScope check could be expensive. Can we do better?
+ for (; I != IEnd && S->isDeclScope(*I); ++I)
+ if ((*I)->getIdentifierNamespace() & NS)
+ return *I;
+
+ // If there is an entity associated with this scope, it's a
+ // DeclContext. We might need to perform qualified lookup into
+ // it.
+ DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+ while (Ctx && Ctx->isFunctionOrMethod())
+ Ctx = Ctx->getParent();
+ while (Ctx && (Ctx->isNamespace() || Ctx->isCXXRecord())) {
+ // Look for declarations of this name in this scope.
+ for (DeclContext::lookup_const_result I = Ctx->lookup(Context, Name);
+ I.first != I.second; ++I.first) {
+ // FIXME: Cache this result in the IdResolver
+ if ((*I.first)->getIdentifierNamespace() & NS)
+ return *I.first;
+ }
+
+ Ctx = Ctx->getParent();
+ }
+
+ if (!LookInParent)
+ return 0;
+ }
+ } else {
+ // Unqualified name lookup for names in our lexical scope. This
+ // name lookup suffices when all of the potential names are known
+ // to have been pushed onto the IdResolver, as happens in C
+ // (always) and in C++ for names in the "label" namespace.
+ assert(!LookupCtx && "Can't perform qualified name lookup here");
+ IdentifierResolver::iterator I
+ = IdResolver.begin(Name, CurContext, LookInParent);
+
+ // Scan up the scope chain looking for a decl that matches this
+ // identifier that is in the appropriate namespace. This search
+ // should not take long, as shadowing of names is uncommon, and
+ // deep shadowing is extremely uncommon.
+ for (; I != IdResolver.end(); ++I)
+ if ((*I)->getIdentifierNamespace() & NS)
+ return *I;
+ }
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
@@ -826,7 +908,8 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
- while ((S->getFlags() & Scope::DeclScope) == 0)
+ while ((S->getFlags() & Scope::DeclScope) == 0 ||
+ (S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();
DeclContext *DC;
@@ -854,6 +937,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
// No previous declaration in the qualifying scope.
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
<< Name << D.getCXXScopeSpec().getRange();
+ InvalidDecl = true;
} else if (!CurContext->Encloses(DC)) {
// The qualifying scope doesn't enclose the original declaration.
// Emit diagnostic based on current scope.
@@ -865,6 +949,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
Diag(L, diag::err_invalid_declarator_scope)
<< Name << cast<NamedDecl>(DC)->getDeclName() << R;
}
+ InvalidDecl = true;
}
}
@@ -1127,23 +1212,42 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
if (OldDecl == PrevDecl) {
// Remove the name binding for the previous
- // declaration. We'll add the binding back later, but then
- // it will refer to the new declaration (which will
- // contain more information).
- IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl));
+ // declaration.
+ if (S->isDeclScope(PrevDecl)) {
+ IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl));
+ S->RemoveDecl(PrevDecl);
+ }
+
+ // Introduce the new binding for this declaration.
+ IdResolver.AddDecl(NewFD);
+ if (getLangOptions().CPlusPlus && NewFD->getParent())
+ NewFD->getParent()->insert(Context, NewFD);
+
+ // Add the redeclaration to the current scope, since we'll
+ // be skipping PushOnScopeChains.
+ S->AddDecl(NewFD);
} else {
// We need to update the OverloadedFunctionDecl with the
// latest declaration of this function, so that name
// lookup will always refer to the latest declaration of
// this function.
*MatchedDecl = NewFD;
+ }
- // Add the redeclaration to the current scope, since we'll
- // be skipping PushOnScopeChains.
- S->AddDecl(NewFD);
+ if (getLangOptions().CPlusPlus) {
+ // Add this declaration to the current context.
+ CurContext->addDecl(Context, NewFD, false);
- return NewFD;
+ // Check default arguments now that we have merged decls.
+ CheckCXXDefaultArguments(NewFD);
}
+
+ // Set the lexical context. If the declarator has a C++
+ // scope specifier, the lexical context will be different
+ // from the semantic context.
+ NewFD->setLexicalDeclContext(CurContext);
+
+ return NewFD;
}
}
}
@@ -2071,7 +2175,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
parmDeclType = Context.getArrayDecayedType(parmDeclType);
} else if (parmDeclType->isFunctionType())
parmDeclType = Context.getPointerType(parmDeclType);
-
+
ParmVarDecl *New = ParmVarDecl::Create(Context, CurContext,
D.getIdentifierLoc(), II,
parmDeclType, StorageClass,
@@ -2079,9 +2183,11 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (D.getInvalidType())
New->setInvalidDecl();
-
+
+ // Add the parameter declaration into this scope.
+ S->AddDecl(New);
if (II)
- PushOnScopeChains(New, S);
+ IdResolver.AddDecl(New);
ProcessDeclAttributes(New, D);
return New;
@@ -2133,7 +2239,7 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
Diag(Definition->getLocation(), diag::note_previous_definition);
}
- PushDeclContext(FD);
+ PushDeclContext(FnBodyScope, FD);
// Check the validity of our function parameters
CheckParmsForFunctionDef(FD);
@@ -2573,17 +2679,19 @@ Sema::DeclTy *Sema::ActOnTagStruct(Scope *S, TagDecl::TagKind Kind, TagKind TK,
/// Collect the instance variables declared in an Objective-C object. Used in
/// the creation of structures from objects using the @defs directive.
-static void CollectIvars(ObjCInterfaceDecl *Class, ASTContext& Ctx,
+static void CollectIvars(ObjCInterfaceDecl *Class, RecordDecl *Record,
+ ASTContext& Ctx,
llvm::SmallVectorImpl<Sema::DeclTy*> &ivars) {
if (Class->getSuperClass())
- CollectIvars(Class->getSuperClass(), Ctx, ivars);
+ CollectIvars(Class->getSuperClass(), Record, Ctx, ivars);
// For each ivar, create a fresh ObjCAtDefsFieldDecl.
for (ObjCInterfaceDecl::ivar_iterator
I=Class->ivar_begin(), E=Class->ivar_end(); I!=E; ++I) {
ObjCIvarDecl* ID = *I;
- ivars.push_back(ObjCAtDefsFieldDecl::Create(Ctx, ID->getLocation(),
+ ivars.push_back(ObjCAtDefsFieldDecl::Create(Ctx, Record,
+ ID->getLocation(),
ID->getIdentifier(),
ID->getType(),
ID->getBitWidth()));
@@ -2592,7 +2700,7 @@ static void CollectIvars(ObjCInterfaceDecl *Class, ASTContext& Ctx,
/// Called whenever @defs(ClassName) is encountered in the source. Inserts the
/// instance variables of ClassName into Decls.
-void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart,
+void Sema::ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
IdentifierInfo *ClassName,
llvm::SmallVectorImpl<DeclTy*> &Decls) {
// Check that ClassName is a valid class
@@ -2602,7 +2710,17 @@ void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart,
return;
}
// Collect the instance variables
- CollectIvars(Class, Context, Decls);
+ CollectIvars(Class, dyn_cast<RecordDecl>((Decl*)TagD), Context, Decls);
+
+ // Introduce all of these fields into the appropriate scope.
+ for (llvm::SmallVectorImpl<DeclTy*>::iterator D = Decls.begin();
+ D != Decls.end(); ++D) {
+ FieldDecl *FD = cast<FieldDecl>((Decl*)*D);
+ if (getLangOptions().CPlusPlus)
+ PushOnScopeChains(cast<FieldDecl>(FD), S);
+ else if (RecordDecl *Record = dyn_cast<RecordDecl>((Decl*)TagD))
+ Record->addDecl(Context, FD);
+ }
}
/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
@@ -2657,12 +2775,13 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
/// ActOnField - Each field of a struct/union/class is passed into this in order
/// to create a FieldDecl object for it.
-Sema::DeclTy *Sema::ActOnField(Scope *S,
+Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
SourceLocation DeclStart,
Declarator &D, ExprTy *BitfieldWidth) {
IdentifierInfo *II = D.getIdentifier();
Expr *BitWidth = (Expr*)BitfieldWidth;
SourceLocation Loc = DeclStart;
+ RecordDecl *Record = (RecordDecl *)TagD;
if (II) Loc = D.getIdentifierLoc();
// FIXME: Unnamed fields can be handled in various different ways, for
@@ -2699,22 +2818,24 @@ Sema::DeclTy *Sema::ActOnField(Scope *S,
// FIXME: Chain fielddecls together.
FieldDecl *NewFD;
- if (getLangOptions().CPlusPlus) {
- // FIXME: Replace CXXFieldDecls with FieldDecls for simple structs.
- NewFD = CXXFieldDecl::Create(Context, cast<CXXRecordDecl>(CurContext),
- Loc, II, T,
- D.getDeclSpec().getStorageClassSpec() ==
- DeclSpec::SCS_mutable, BitWidth);
- if (II)
- PushOnScopeChains(NewFD, S);
- }
- else
- NewFD = FieldDecl::Create(Context, Loc, II, T, BitWidth);
-
+ // FIXME: We don't want CurContext for C, do we? No, we'll need some
+ // other way to determine the current RecordDecl.
+ NewFD = FieldDecl::Create(Context, Record,
+ Loc, II, T, BitWidth,
+ D.getDeclSpec().getStorageClassSpec() ==
+ DeclSpec::SCS_mutable,
+ /*PrevDecl=*/0);
+
ProcessDeclAttributes(NewFD, D);
if (D.getInvalidType() || InvalidDecl)
NewFD->setInvalidDecl();
+
+ if (II && getLangOptions().CPlusPlus)
+ PushOnScopeChains(NewFD, S);
+ else
+ Record->addDecl(Context, NewFD);
+
return NewFD;
}
@@ -2921,7 +3042,7 @@ void Sema::ActOnFields(Scope* S,
// Okay, we successfully defined 'Record'.
if (Record) {
- Record->defineBody(Context, &RecFields[0], RecFields.size());
+ Record->completeDefinition(Context);
// If this is a C++ record, HandleTagDeclDefinition will be invoked in
// Sema::ActOnFinishCXXClassDef.
if (!isa<CXXRecordDecl>(Record))
@@ -3189,7 +3310,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
ECD->setType(NewTy);
}
- Enum->defineElements(EltList, BestType);
+ Enum->completeDefinition(Context, BestType);
Consumer.HandleTagDeclDefinition(Enum);
}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index bff650db5fe..5c2b49472b1 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -904,8 +904,10 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
// FIXME: This isn't supposed to be restricted to pointers, but otherwise
// we might silently generate incorrect code; see following code
- for (int i = 0; i < RD->getNumMembers(); i++) {
- if (!RD->getMember(i)->getType()->isPointerType()) {
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ if (!Field->getType()->isPointerType()) {
S.Diag(Attr.getLoc(), diag::warn_transparent_union_nonpointer);
return;
}
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index bedf3f7d6b6..31ecfbabd29 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -382,7 +382,7 @@ void Sema::ActOnBaseSpecifiers(DeclTy *ClassDecl, BaseTy **Bases,
/// definition, when on C++.
void Sema::ActOnStartCXXClassDef(Scope *S, DeclTy *D, SourceLocation LBrace) {
CXXRecordDecl *Dcl = cast<CXXRecordDecl>(static_cast<Decl *>(D));
- PushDeclContext(Dcl);
+ PushDeclContext(S, Dcl);
FieldCollector->StartClass();
if (Dcl->getIdentifier()) {
@@ -486,7 +486,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
bool InvalidDecl = false;
if (isInstField)
- Member = static_cast<Decl*>(ActOnField(S, Loc, D, BitWidth));
+ Member = static_cast<Decl*>(ActOnField(S, cast<CXXRecordDecl>(CurContext),
+ Loc, D, BitWidth));
else
Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup));
@@ -593,7 +594,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Member->setInvalidDecl();
if (isInstField) {
- FieldCollector->Add(cast<CXXFieldDecl>(Member));
+ FieldCollector->Add(cast<FieldDecl>(Member));
return LastInGroup;
}
return Member;
@@ -632,7 +633,10 @@ Sema::ActOnMemInitializer(DeclTy *ConstructorD,
// mem-initializer-id for the hidden base class may be specified
// using a qualified name. ]
// Look for a member, first.
- CXXFieldDecl *Member = ClassDecl->getMember(MemberOrBase);
+ FieldDecl *Member = 0;
+ DeclContext::lookup_result Result = ClassDecl->lookup(Context, MemberOrBase);
+ if (Result.first != Result.second)
+ Member = dyn_cast<FieldDecl>(*Result.first);
// FIXME: Handle members of an anonymous union.
@@ -1251,43 +1255,42 @@ Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// in that declarative region, it is treated as an original-namespace-name.
Decl *PrevDecl =
- LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0,
- /*enableLazyBuiltinCreation=*/false);
-
- if (PrevDecl && isDeclInScope(PrevDecl, CurContext, DeclRegionScope)) {
- if (NamespaceDecl *OrigNS = dyn_cast<NamespaceDecl>(PrevDecl)) {
- // This is an extended namespace definition.
- // Attach this namespace decl to the chain of extended namespace
- // definitions.
- NamespaceDecl *NextNS = OrigNS;
- while (NextNS->getNextNamespace())
- NextNS = NextNS->getNextNamespace();
-
- NextNS->setNextNamespace(Namespc);
- Namespc->setOriginalNamespace(OrigNS);
-
- // We won't add this decl to the current scope. We want the namespace
- // name to return the original namespace decl during a name lookup.
- } else {
- // This is an invalid name redefinition.
- Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
- << Namespc->getDeclName();
- Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- Namespc->setInvalidDecl();
- // Continue on to push Namespc as current DeclContext and return it.
+ LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0,
+ /*enableLazyBuiltinCreation=*/false,
+ /*LookupInParent=*/false);
+
+ if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
+ // This is an extended namespace definition.
+ // Attach this namespace decl to the chain of extended namespace
+ // definitions.
+ OrigNS->setNextNamespace(Namespc);
+ Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace());
+
+ // Remove the previous declaration from the scope.
+ if (DeclRegionScope->isDeclScope(OrigNS)) {
+ IdResolver.RemoveDecl(OrigNS);
+ DeclRegionScope->RemoveDecl(OrigNS);
}
- } else {
- // This namespace name is declared for the first time.
- PushOnScopeChains(Namespc, DeclRegionScope);
- }
- }
- else {
+ } else if (PrevDecl) {
+ // This is an invalid name redefinition.
+ Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
+ << Namespc->getDeclName();
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ Namespc->setInvalidDecl();
+ // Continue on to push Namespc as current DeclContext and return it.
+ }
+
+ PushOnScopeChains(Namespc, DeclRegionScope);
+ } else {
// FIXME: Handle anonymous namespaces
}
// Although we could have an invalid decl (i.e. the namespace name is a
// redefinition), push it as current DeclContext and try to continue parsing.
- PushDeclContext(Namespc->getOriginalNamespace());
+ // FIXME: We should be able to push Namespc here, so that the
+ // each DeclContext for the namespace has the declarations
+ // that showed up in that particular namespace definition.
+ PushDeclContext(NamespcScope, Namespc);
return Namespc;
}
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index fa73bcf2591..d1357247709 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -36,7 +36,7 @@ void Sema::ObjCActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {
AddFactoryMethodToGlobalPool(MDecl);
// Allow all of Sema to see that we are entering a method definition.
- PushDeclContext(MDecl);
+ PushDeclContext(FnBodyScope, MDecl);
// Create Decl objects for each parameter, entrring them in the scope for
// binding to their use.
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b2542542417..ba5d28a6334 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -453,13 +453,13 @@ Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
}
}
- if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D)) {
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
if (MD->isStatic())
// "invalid use of member 'x' in static member function"
return Diag(Loc, diag::err_invalid_member_use_in_static_method)
<< FD->getDeclName();
- if (cast<CXXRecordDecl>(MD->getParent()) != FD->getParent())
+ if (MD->getParent() != FD->getDeclContext())
// "invalid use of nonstatic data member 'x'"
return Diag(Loc, diag::err_invalid_non_static_member_use)
<< FD->getDeclName();
@@ -1231,20 +1231,28 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
return Diag(OpLoc, diag::err_typecheck_incomplete_tag)
<< RDecl->getDeclName() << BaseExpr->getSourceRange();
// The record definition is complete, now make sure the member is valid.
- FieldDecl *MemberDecl = RDecl->getMember(&Member);
- if (!MemberDecl)
+ // 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) {
return Diag(MemberLoc, diag::err_typecheck_no_member)
<< &Member << BaseExpr->getSourceRange();
+ }
+
+ FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
+ if (!MemberDecl) {
+ unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error,
+ "Clang only supports references to members");
+ return Diag(MemberLoc, DiagID);
+ }
// Figure out the type of the member; see C99 6.5.2.3p3
// FIXME: Handle address space modifiers
QualType MemberType = MemberDecl->getType();
unsigned combinedQualifiers =
MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
- if (CXXFieldDecl *CXXMember = dyn_cast<CXXFieldDecl>(MemberDecl)) {
- if (CXXMember->isMutable())
- combinedQualifiers &= ~QualType::Const;
- }
+ if (MemberDecl->isMutable())
+ combinedQualifiers &= ~QualType::Const;
MemberType = MemberType.getQualifiedType(combinedQualifiers);
return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl,
@@ -3484,7 +3492,11 @@ Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
// Get the decl corresponding to this.
RecordDecl *RD = RC->getDecl();
- FieldDecl *MemberDecl = RD->getMember(OC.U.IdentInfo);
+ FieldDecl *MemberDecl = 0;
+ DeclContext::lookup_result Lookup = RD->lookup(Context, OC.U.IdentInfo);
+ if (Lookup.first != Lookup.second)
+ MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
+
if (!MemberDecl)
return Diag(BuiltinLoc, diag::err_typecheck_no_member)
<< OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd);
@@ -3552,7 +3564,7 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
BSI->TheScope = BlockScope;
BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc);
- PushDeclContext(BSI->TheDecl);
+ PushDeclContext(BlockScope, BSI->TheDecl);
}
void Sema::ActOnBlockArguments(Declarator &ParamInfo) {
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 27b0ba34d19..a32a6f68fad 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -412,9 +412,8 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,
DeclContext *Ctx, bool AllowMissing,
FunctionDecl *&Operator)
{
- IdentifierResolver::iterator I =
- IdResolver.begin(Name, Ctx, /*LookInParentCtx=*/false);
- if (I == IdResolver.end()) {
+ DeclContext::lookup_result Lookup = Ctx->lookup(Context, Name);
+ if (Lookup.first == Lookup.second) {
if (AllowMissing)
return false;
// FIXME: Bad location information.
@@ -423,7 +422,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,
}
OverloadCandidateSet Candidates;
- NamedDecl *Decl = *I;
+ 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))
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 42f9b14085e..f36d3a504fc 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -15,6 +15,8 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/Diagnostic.h"
+#include <algorithm> // for std::count_if
+#include <functional> // for std::mem_fun
namespace clang {
@@ -39,10 +41,9 @@ int InitListChecker::numArrayElements(QualType DeclType) {
int InitListChecker::numStructUnionElements(QualType DeclType) {
RecordDecl *structDecl = DeclType->getAsRecordType()->getDecl();
- int InitializableMembers = 0;
- for (int i = 0; i < structDecl->getNumMembers(); i++)
- if (structDecl->getMember(i)->getIdentifier())
- ++InitializableMembers;
+ int InitializableMembers
+ = std::count_if(structDecl->field_begin(), structDecl->field_end(),
+ std::mem_fun(&FieldDecl::getDeclName));
if (structDecl->isUnion())
return std::min(InitializableMembers, 1);
return InitializableMembers - structDecl->hasFlexibleArrayMember();
@@ -286,21 +287,28 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
// If structDecl is a forward declaration, this loop won't do anything;
// That's okay, because an error should get printed out elsewhere. It
// might be worthwhile to skip over the rest of the initializer, though.
- int numMembers = DeclType->getAsRecordType()->getDecl()->getNumMembers() -
- structDecl->hasFlexibleArrayMember();
- for (int i = 0; i < numMembers; i++) {
+ RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ // If we've hit the flexible array member at the end, we're done.
+ if (Field->getType()->isIncompleteArrayType())
+ break;
+
// Don't attempt to go past the end of the init list
if (Index >= IList->getNumInits())
break;
- FieldDecl * curField = structDecl->getMember(i);
- if (!curField->getIdentifier()) {
+
+ if (!Field->getIdentifier()) {
// Don't initialize unnamed fields, e.g. "int : 20;"
continue;
}
- CheckSubElementType(IList, curField->getType(), Index);
+
+ CheckSubElementType(IList, Field->getType(), Index);
if (DeclType->isUnionType())
break;
}
+
// FIXME: Implement flexible array initialization GCC extension (it's a
// really messy extension to implement, unfortunately...the necessary
// information isn't actually even here!)
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 8a68d5be5c3..307abe3ac95 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1955,10 +1955,9 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
// (13.3.1.1.1); otherwise, the set of member candidates is
// empty.
if (const RecordType *T1Rec = T1->getAsRecordType()) {
- IdentifierResolver::iterator I
- = IdResolver.begin(OpName, cast<CXXRecordType>(T1Rec)->getDecl(),
- /*LookInParentCtx=*/false);
- NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I;
+ DeclContext::lookup_const_result Lookup
+ = cast<CXXRecordType>(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,
/*SuppressUserConversions=*/false);
@@ -3118,11 +3117,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// ordinary lookup of the name operator() in the context of
// (E).operator().
OverloadCandidateSet CandidateSet;
- IdentifierResolver::iterator I
- = IdResolver.begin(Context.DeclarationNames.getCXXOperatorName(OO_Call),
- cast<CXXRecordType>(Record)->getDecl(),
- /*LookInParentCtx=*/false);
- NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I;
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+ DeclContext::lookup_const_result Lookup
+ = cast<CXXRecordType>(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);
@@ -3315,10 +3313,9 @@ Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
OverloadCandidateSet CandidateSet;
const RecordType *BaseRecord = Base->getType()->getAsRecordType();
- IdentifierResolver::iterator I
- = IdResolver.begin(OpName, cast<CXXRecordType>(BaseRecord)->getDecl(),
- /*LookInParentCtx=*/false);
- NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I;
+ DeclContext::lookup_const_result Lookup
+ = cast<CXXRecordType>(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,
/*SuppressUserConversions=*/false);
OpenPOWER on IntegriCloud