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/TreeTransform.h b/lib/Sema/TreeTransform.h
index 77d5220..8aabad5 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1421,6 +1421,28 @@
RParenLoc);
}
+ /// \brief Build a new qualified member access expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ OwningExprResult RebuildCXXQualifiedMemberExpr(ExprArg Base,
+ SourceLocation OpLoc,
+ bool isArrow,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ SourceLocation MemberLoc,
+ NamedDecl *Member) {
+ CXXScopeSpec SS;
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(Qualifier);
+ return getSema().ActOnMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
+ isArrow? tok::arrow : tok::period,
+ MemberLoc,
+ /*FIXME*/*Member->getIdentifier(),
+ /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
+ &SS);
+ }
+
/// \brief Build a new member reference expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -3992,6 +4014,44 @@
E->getRParenLoc());
}
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXQualifiedMemberExpr(
+ CXXQualifiedMemberExpr *E) {
+ OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return SemaRef.ExprError();
+
+ NamedDecl *Member
+ = cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getMemberDecl()));
+ if (!Member)
+ return SemaRef.ExprError();
+
+ NestedNameSpecifier *Qualifier
+ = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (Qualifier == 0)
+ return SemaRef.ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Base.get() == E->getBase() &&
+ Member == E->getMemberDecl() &&
+ Qualifier == E->getQualifier())
+ return SemaRef.Owned(E->Retain());
+
+ // FIXME: Bogus source location for the operator
+ SourceLocation FakeOperatorLoc
+ = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
+
+ return getDerived().RebuildCXXQualifiedMemberExpr(move(Base),
+ FakeOperatorLoc,
+ E->isArrow(),
+ Qualifier,
+ E->getQualifierRange(),
+ E->getMemberLoc(),
+ Member);
+}
+
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(