[cfe-commits] r72281 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/AST/StmtNodes.def lib/AST/ExprCXX.cpp lib/AST/StmtPrinter.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/instantiate-expr-4.cpp

Douglas Gregor dgregor at apple.com
Fri May 22 14:13:27 PDT 2009


Author: dgregor
Date: Fri May 22 16:13:27 2009
New Revision: 72281

URL: http://llvm.org/viewvc/llvm-project?rev=72281&view=rev
Log:
Representation of and template instantiation for member
expressions. This change introduces another AST node,
CXXUnresolvedMemberExpr, that captures member references (x->m, x.m)
when the base of the expression (the "x") is type-dependent, and we
therefore cannot resolve the member reference yet.

Note that our parsing of member references for C++ is still quite
poor, e.g., we don't handle x->Base::m or x->operator int.


Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/StmtNodes.def
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
    cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=72281&r1=72280&r2=72281&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Fri May 22 16:13:27 2009
@@ -1088,6 +1088,76 @@
   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

Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=72281&r1=72280&r2=72281&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Fri May 22 16:13:27 2009
@@ -127,6 +127,7 @@
 EXPR(CXXExprWithTemporaries , Expr)
 EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
 EXPR(CXXUnresolvedConstructExpr, Expr)
+EXPR(CXXUnresolvedMemberExpr, Expr)
 
 // Obj-C Expressions.
 EXPR(ObjCStringLiteral    , Expr)

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=72281&r1=72280&r2=72281&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Fri May 22 16:13:27 2009
@@ -354,6 +354,14 @@
   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
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=72281&r1=72280&r2=72281&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri May 22 16:13:27 2009
@@ -1125,6 +1125,12 @@
   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");

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=72281&r1=72280&r2=72281&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri May 22 16:13:27 2009
@@ -2031,10 +2031,11 @@
   // 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())
@@ -2058,10 +2059,11 @@
 
       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));
     }
   }
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=72281&r1=72280&r2=72281&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Fri May 22 16:13:27 2009
@@ -48,7 +48,7 @@
     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);
@@ -96,6 +96,7 @@
     OwningExprResult VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E);
     OwningExprResult VisitCXXUnresolvedConstructExpr(
                                                CXXUnresolvedConstructExpr *E);
+    OwningExprResult VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *E);
     OwningExprResult VisitGNUNullExpr(GNUNullExpr *E);
     OwningExprResult VisitUnresolvedFunctionNameExpr(
                                               UnresolvedFunctionNameExpr *E);
@@ -289,6 +290,26 @@
 }
 
 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 
     = SemaRef.PP.getLocForEndOfToken(E->getLParenLoc());
@@ -1159,6 +1180,24 @@
 }
 
 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)
     return Owned((Expr *)0);

Modified: cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp?rev=72281&r1=72280&r2=72281&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp Fri May 22 16:13:27 2009
@@ -178,3 +178,63 @@
 
 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>; 





More information about the cfe-commits mailing list