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/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index b254254..ba5d28a 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -453,13 +453,13 @@
}
}
- 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 @@
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 @@
// 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 @@
BSI->TheScope = BlockScope;
BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc);
- PushDeclContext(BSI->TheDecl);
+ PushDeclContext(BlockScope, BSI->TheDecl);
}
void Sema::ActOnBlockArguments(Declarator &ParamInfo) {