Support nested-name-specifiers for C++ member access expressions, e.g.,

  this->Base::foo

from James Porter!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78278 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index ffc6d13..76296c6 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2103,7 +2103,11 @@
 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 @@
       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 @@
                                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());