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).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60878 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index bedf3f7..31ecfba 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -382,7 +382,7 @@
/// 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 @@
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 @@
Member->setInvalidDecl();
if (isInstField) {
- FieldCollector->Add(cast<CXXFieldDecl>(Member));
+ FieldCollector->Add(cast<FieldDecl>(Member));
return LastInGroup;
}
return Member;
@@ -632,7 +633,10 @@
// 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 @@
// 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);
+ 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());
- 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.
+ // 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;
}