diff options
| author | Douglas Gregor <dgregor@apple.com> | 2009-08-06 03:17:00 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2009-08-06 03:17:00 +0000 |
| commit | d806156d5459555168540fdf3db4f473cd3f81cf (patch) | |
| tree | 60b3a05de9f6f9ff7e8cdf02aec449cdf69eefd6 /clang/lib/Sema/SemaExpr.cpp | |
| parent | 3c7b95d9aaaa06a856aa08a6ebce23d4825b15d9 (diff) | |
| download | bcm5719-llvm-d806156d5459555168540fdf3db4f473cd3f81cf.tar.gz bcm5719-llvm-d806156d5459555168540fdf3db4f473cd3f81cf.zip | |
Support nested-name-specifiers for C++ member access expressions, e.g.,
this->Base::foo
from James Porter!
llvm-svn: 78278
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ffc6d13bb41..76296c690cc 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2103,7 +2103,11 @@ Action::OwningExprResult Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation MemberLoc, IdentifierInfo &Member, - DeclPtrTy ObjCImpDecl) { + DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS) { + // FIXME: handle the CXXScopeSpec for proper lookup of qualified-ids + if (SS && SS->isInvalid()) + return ExprError(); + Expr *BaseExpr = Base.takeAs<Expr>(); assert(BaseExpr && "no record expression"); @@ -2126,9 +2130,6 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, BaseType = PT->getPointeeType(); else if (BaseType->isObjCObjectPointerType()) ; - else if (getLangOptions().CPlusPlus && BaseType->isRecordType()) - return Owned(BuildOverloadedArrowExpr(S, BaseExpr, OpLoc, - MemberLoc, Member)); else return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) @@ -2164,12 +2165,38 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, BaseExpr->getSourceRange())) return ExprError(); + DeclContext *DC = RDecl; + if (SS && SS->isSet()) { + // If the member name was a qualified-id, look into the + // nested-name-specifier. + DC = computeDeclContext(*SS, false); + + // FIXME: If DC is not computable, we should build a + // CXXUnresolvedMemberExpr. + assert(DC && "Cannot handle non-computable dependent contexts in lookup"); + } + // 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. LookupResult Result - = LookupQualifiedName(RDecl, DeclarationName(&Member), + = LookupQualifiedName(DC, DeclarationName(&Member), LookupMemberName, false); + if (SS && SS->isSet()) + { + QualType BaseTypeCanon + = Context.getCanonicalType(BaseType).getUnqualifiedType(); + QualType MemberTypeCanon + = Context.getCanonicalType( + Context.getTypeDeclType( + dyn_cast<TypeDecl>(Result.getAsDecl()->getDeclContext()))); + + if (BaseTypeCanon != MemberTypeCanon && + !IsDerivedFrom(BaseTypeCanon, MemberTypeCanon)) + return ExprError(Diag(SS->getBeginLoc(), + diag::err_not_direct_base_or_virtual) + << MemberTypeCanon << BaseTypeCanon); + } + if (!Result) return ExprError(Diag(MemberLoc, diag::err_typecheck_no_member) << &Member << BaseExpr->getSourceRange()); |

