When a member reference expression includes a qualifier on the member
name, e.g.,
  
  x->Base::f()

retain the qualifier (and its source range information) in a new
subclass of MemberExpr called CXXQualifiedMemberExpr. Provide
construction, transformation, profiling, printing, etc., for this new
expression type.

When a virtual function is called via a qualified name, don't emit a
virtual call. Instead, call that function directly. Mike, could you
add a CodeGen test for this, too?



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80167 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7a81898..e737089 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -631,6 +631,7 @@
     if (BaseAddrSpace != MemberType.getAddressSpace())
       MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace);
     MarkDeclarationReferenced(Loc, *FI);
+    // FIXME: Might this end up being a qualified name?
     Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
                                       OpLoc, MemberType);
     BaseObjectIsPointer = false;
@@ -874,6 +875,19 @@
   return false;
 }
 
+/// \brief Build a MemberExpr or CXXQualifiedMemberExpr, as appropriate.
+static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, 
+                                   const CXXScopeSpec *SS, NamedDecl *Member, 
+                                   SourceLocation Loc, QualType Ty) {
+  if (SS && SS->isSet())
+    return new (C) CXXQualifiedMemberExpr(Base, isArrow, 
+                                          (NestedNameSpecifier *)SS->getScopeRep(),
+                                          SS->getRange(),
+                                          Member, Loc, Ty);
+  
+  return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty);
+}
+
 /// \brief Complete semantic analysis for a reference to the given declaration.
 Sema::OwningExprResult
 Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
@@ -985,8 +999,8 @@
             return ExprError();
           if (DiagnoseUseOfDecl(D, Loc))
             return ExprError();
-          return Owned(new (Context) MemberExpr(This, true, D,
-                                                Loc, MemberType));
+          return Owned(BuildMemberExpr(Context, This, true, SS, D,
+                                       Loc, MemberType));
         }
       }
     }
@@ -1953,7 +1967,7 @@
     return FindMethodInNestedImplementations(IFace->getSuperClass(), Sel);
   return Method;
 }
-
+                       
 Action::OwningExprResult 
 Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
                                tok::TokenKind OpKind, SourceLocation MemberLoc,
@@ -2112,37 +2126,37 @@
       MarkDeclarationReferenced(MemberLoc, FD);
       if (PerformObjectMemberConversion(BaseExpr, FD))
         return ExprError();
-      return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, FD,
-                                            MemberLoc, MemberType));
+      return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, 
+                                   FD, MemberLoc, MemberType));
     }
     
     if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
       MarkDeclarationReferenced(MemberLoc, MemberDecl);
-      return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
-                                            Var, MemberLoc,
-                                         Var->getType().getNonReferenceType()));
+      return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
+                                   Var, MemberLoc,
+                                   Var->getType().getNonReferenceType()));
     }
     if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
       MarkDeclarationReferenced(MemberLoc, MemberDecl);
-      return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
-                                            MemberFn, MemberLoc,
-                                            MemberFn->getType()));
+      return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
+                                   MemberFn, MemberLoc,
+                                   MemberFn->getType()));
     }
     if (FunctionTemplateDecl *FunTmpl 
           = dyn_cast<FunctionTemplateDecl>(MemberDecl)) {
       MarkDeclarationReferenced(MemberLoc, MemberDecl);
-      return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
-                                            FunTmpl, MemberLoc,
-                                            Context.OverloadTy));
+      return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
+                                   FunTmpl, MemberLoc,
+                                   Context.OverloadTy));
     }
     if (OverloadedFunctionDecl *Ovl
           = dyn_cast<OverloadedFunctionDecl>(MemberDecl))
-      return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl,
-                                            MemberLoc, Context.OverloadTy));
+      return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
+                                   Ovl, MemberLoc, Context.OverloadTy));
     if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
       MarkDeclarationReferenced(MemberLoc, MemberDecl);
-      return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
-                                            Enum, MemberLoc, Enum->getType()));
+      return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
+                                   Enum, MemberLoc, Enum->getType()));
     }
     if (isa<TypeDecl>(MemberDecl))
       return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type)
@@ -4802,6 +4816,7 @@
   case Stmt::QualifiedDeclRefExprClass:
     return cast<DeclRefExpr>(E)->getDecl();
   case Stmt::MemberExprClass:
+  case Stmt::CXXQualifiedMemberExprClass:
     // If this is an arrow operator, the address is an offset from
     // the base's value, so the object the base refers to is
     // irrelevant.