virtual child_iterator child_end();
};
+/// \brief
+class CXXUnresolvedMemberExpr : public Expr {
+ /// \brief The expression for the base pointer or class reference,
+ /// e.g., the \c x in x.f.
+ Stmt *Base;
+
+ /// \brief Whether this member expression used the '->' operator or
+ /// the '.' operator.
+ bool IsArrow;
+
+ /// \brief The location of the '->' or '.' operator.
+ SourceLocation OperatorLoc;
+
+ /// \brief The member to which this member expression refers, which
+ /// can be name, overloaded operator, or destructor.
+ /// FIXME: could also be a template-id, and we might have a
+ /// nested-name-specifier as well.
+ DeclarationName Member;
+
+ /// \brief The location of the member name.
+ SourceLocation MemberLoc;
+
+public:
+ CXXUnresolvedMemberExpr(ASTContext &C,
+ Expr *Base, bool IsArrow,
+ SourceLocation OperatorLoc,
+ DeclarationName Member,
+ SourceLocation MemberLoc)
+ : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
+ Base(Base), IsArrow(IsArrow), OperatorLoc(OperatorLoc),
+ Member(Member), MemberLoc(MemberLoc) { }
+
+ /// \brief Retrieve the base object of this member expressions,
+ /// e.g., the \c x in \c x.m.
+ Expr *getBase() { return cast<Expr>(Base); }
+ void setBase(Expr *E) { Base = E; }
+
+ /// \brief Determine whether this member expression used the '->'
+ /// operator; otherwise, it used the '.' operator.
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// \brief Retrieve the location of the '->' or '.' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+ void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ DeclarationName getMember() const { return Member; }
+ void setMember(DeclarationName N) { Member = N; }
+
+ // \brief Retrieve the location of the name of the member that this
+ // expression refers to.
+ SourceLocation getMemberLoc() const { return MemberLoc; }
+ void setMemberLoc(SourceLocation L) { MemberLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(Base->getSourceRange().getBegin(),
+ MemberLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXUnresolvedMemberExprClass;
+ }
+ static bool classof(const CXXUnresolvedMemberExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
} // end namespace clang
#endif
EXPR(CXXExprWithTemporaries , Expr)
EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
EXPR(CXXUnresolvedConstructExpr, Expr)
+EXPR(CXXUnresolvedMemberExpr, Expr)
// Obj-C Expressions.
EXPR(ObjCStringLiteral , Expr)
return child_iterator(reinterpret_cast<Stmt **>(this + 1) + NumArgs);
}
+Stmt::child_iterator CXXUnresolvedMemberExpr::child_begin() {
+ return child_iterator(&Base);
+}
+
+Stmt::child_iterator CXXUnresolvedMemberExpr::child_end() {
+ return child_iterator(&Base + 1);
+}
+
//===----------------------------------------------------------------------===//
// Cloners
//===----------------------------------------------------------------------===//
OS << ")";
}
+void StmtPrinter::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *Node) {
+ PrintExpr(Node->getBase());
+ OS << (Node->isArrow() ? "->" : ".");
+ OS << Node->getMember().getAsString();
+}
+
static const char *getTypeTraitName(UnaryTypeTrait UTT) {
switch (UTT) {
default: assert(false && "Unknown type trait");
// must have pointer type, and the accessed type is the pointee.
if (OpKind == tok::arrow) {
if (BaseType->isDependentType())
- // FIXME: This should not return a MemberExpr AST node, but a more
- // specialized one.
- return Owned(new (Context) MemberExpr(BaseExpr, true, 0,
- MemberLoc, Context.DependentTy));
+ return Owned(new (Context) CXXUnresolvedMemberExpr(Context,
+ BaseExpr, true,
+ OpLoc,
+ DeclarationName(&Member),
+ MemberLoc));
else if (const PointerType *PT = BaseType->getAsPointerType())
BaseType = PT->getPointeeType();
else if (getLangOptions().CPlusPlus && BaseType->isRecordType())
if (!PT || (getLangOptions().ObjC1 &&
!PT->getPointeeType()->isRecordType()))
- // FIXME: This should not return a MemberExpr AST node, but a more
- // specialized one.
- return Owned(new (Context) MemberExpr(BaseExpr, false, 0,
- MemberLoc, Context.DependentTy));
+ return Owned(new (Context) CXXUnresolvedMemberExpr(Context,
+ BaseExpr, false,
+ OpLoc,
+ DeclarationName(&Member),
+ MemberLoc));
}
}
OwningExprResult VisitUnaryOperator(UnaryOperator *E);
OwningExprResult VisitArraySubscriptExpr(ArraySubscriptExpr *E);
OwningExprResult VisitCallExpr(CallExpr *E);
- // FIXME: VisitMemberExpr
+ OwningExprResult VisitMemberExpr(MemberExpr *E);
OwningExprResult VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
OwningExprResult VisitBinaryOperator(BinaryOperator *E);
OwningExprResult VisitCompoundAssignOperator(CompoundAssignOperator *E);
OwningExprResult VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E);
OwningExprResult VisitCXXUnresolvedConstructExpr(
CXXUnresolvedConstructExpr *E);
+ OwningExprResult VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *E);
OwningExprResult VisitGNUNullExpr(GNUNullExpr *E);
OwningExprResult VisitUnresolvedFunctionNameExpr(
UnresolvedFunctionNameExpr *E);
E->getRParenLoc());
}
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitMemberExpr(MemberExpr *E) {
+ // Instantiate the base of the expression.
+ OwningExprResult Base = Visit(E->getBase());
+ if (Base.isInvalid())
+ return SemaRef.ExprError();
+
+ // FIXME: Handle declaration names here
+ SourceLocation FakeOperatorLoc =
+ SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
+ return SemaRef.ActOnMemberReferenceExpr(/*Scope=*/0,
+ move(Base),
+ /*FIXME*/FakeOperatorLoc,
+ E->isArrow()? tok::arrow
+ : tok::period,
+ E->getMemberLoc(),
+ /*FIXME:*/*E->getMemberDecl()->getIdentifier(),
+ /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
+}
+
Sema::OwningExprResult
TemplateExprInstantiator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
SourceLocation FakeTypeLoc
E->getRParenLoc());
}
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitCXXUnresolvedMemberExpr(
+ CXXUnresolvedMemberExpr *E) {
+ // Instantiate the base of the expression.
+ OwningExprResult Base = Visit(E->getBase());
+ if (Base.isInvalid())
+ return SemaRef.ExprError();
+
+ // FIXME: Instantiate the declaration name.
+ return SemaRef.ActOnMemberReferenceExpr(/*Scope=*/0,
+ move(Base), E->getOperatorLoc(),
+ E->isArrow()? tok::arrow
+ : tok::period,
+ E->getMemberLoc(),
+ /*FIXME:*/*E->getMember().getAsIdentifierInfo(),
+ /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
+}
+
Sema::OwningExprResult
Sema::InstantiateExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
if (!E)
template struct InitList2<APair, int*, float*>;
template struct InitList2<APair, int*, double*>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// member references
+// ---------------------------------------------------------------------
+template<typename T, typename Result>
+struct DotMemRef0 {
+ void f(T t) {
+ Result result = t.m; // expected-error{{cannot be initialized}}
+ }
+};
+
+struct MemInt {
+ int m;
+};
+
+struct InheritsMemInt : MemInt { };
+
+struct MemIntFunc {
+ static int m(int);
+};
+
+template struct DotMemRef0<MemInt, int&>;
+template struct DotMemRef0<InheritsMemInt, int&>;
+template struct DotMemRef0<MemIntFunc, int (*)(int)>;
+template struct DotMemRef0<MemInt, float&>; // expected-note{{instantiation}}
+
+template<typename T, typename Result>
+struct ArrowMemRef0 {
+ void f(T t) {
+ Result result = t->m; // expected-error 2{{cannot be initialized}}
+ }
+};
+
+template<typename T>
+struct ArrowWrapper {
+ T operator->();
+};
+
+template struct ArrowMemRef0<MemInt*, int&>;
+template struct ArrowMemRef0<InheritsMemInt*, int&>;
+template struct ArrowMemRef0<MemIntFunc*, int (*)(int)>;
+template struct ArrowMemRef0<MemInt*, float&>; // expected-note{{instantiation}}
+
+template struct ArrowMemRef0<ArrowWrapper<MemInt*>, int&>;
+template struct ArrowMemRef0<ArrowWrapper<InheritsMemInt*>, int&>;
+template struct ArrowMemRef0<ArrowWrapper<MemIntFunc*>, int (*)(int)>;
+template struct ArrowMemRef0<ArrowWrapper<MemInt*>, float&>; // expected-note{{instantiation}}
+template struct ArrowMemRef0<ArrowWrapper<ArrowWrapper<MemInt*> >, int&>;
+
+// FIXME: we should be able to return a MemInt without the reference!
+MemInt &createMemInt(int);
+
+template<int N>
+struct NonDepMemberExpr0 {
+ void f() {
+ createMemInt(N).m = N;
+ }
+};
+
+template struct NonDepMemberExpr0<0>;