[cfe-commits] r90161 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/ExprCXX.h include/clang/AST/Stmt.h include/clang/AST/StmtNodes.def include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Expr.cpp lib/AST/ExprCXX.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtProfile.cpp lib/Sema/Lookup.h lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/TreeTransform.h test/SemaCXX/qual-id-test.cpp test/SemaTemplate/instantiate-method.cpp

John McCall rjmccall at apple.com
Mon Nov 30 14:42:36 PST 2009


Author: rjmccall
Date: Mon Nov 30 16:42:35 2009
New Revision: 90161

URL: http://llvm.org/viewvc/llvm-project?rev=90161&view=rev
Log:
Eliminate the use of OverloadedFunctionDecl in member expressions.
Create a new UnresolvedMemberExpr for these lookups.  Assorted hackery
around qualified member expressions;  this will all go away when we
implement the correct (i.e. extremely delayed) implicit-member semantics.


Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/AST/StmtNodes.def
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/Sema/Lookup.h
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaCXX/qual-id-test.cpp
    cfe/trunk/test/SemaTemplate/instantiate-method.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Nov 30 16:42:35 2009
@@ -73,6 +73,8 @@
     return false;
   }
 
+  unsigned size() const { return Decls.size(); }
+
   typedef DeclsTy::const_iterator iterator;
   iterator begin() const { return Decls.begin(); }
   iterator end() const { return Decls.end(); }

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

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Nov 30 16:42:35 2009
@@ -1617,6 +1617,179 @@
   virtual child_iterator child_end();
 };
 
+/// \brief Represents a C++ member access expression for which lookup
+/// produced a set of overloaded functions.  These are replaced with
+/// MemberExprs in the final AST.
+class UnresolvedMemberExpr : public Expr {
+  /// The results.  These are undesugared, which is to say, they may
+  /// include UsingShadowDecls.
+  UnresolvedSet Results;
+
+  /// \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 : 1;
+
+  /// \brief Whether the lookup results contain an unresolved using
+  /// declaration.
+  bool HasUnresolvedUsing : 1;
+
+  /// \brief Whether this member expression has explicitly-specified template
+  /// arguments.
+  bool HasExplicitTemplateArgs : 1;
+
+  /// \brief The location of the '->' or '.' operator.
+  SourceLocation OperatorLoc;
+
+  /// \brief The nested-name-specifier that precedes the member name, if any.
+  NestedNameSpecifier *Qualifier;
+
+  /// \brief The source range covering the nested name specifier.
+  SourceRange QualifierRange;
+
+  /// \brief The member to which this member expression refers, which
+  /// can be a name or an overloaded operator.
+  DeclarationName MemberName;
+
+  /// \brief The location of the member name.
+  SourceLocation MemberLoc;
+
+  /// \brief Retrieve the explicit template argument list that followed the
+  /// member template name.
+  ExplicitTemplateArgumentList *getExplicitTemplateArgs() {
+    assert(HasExplicitTemplateArgs);
+    return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+  }
+
+  /// \brief Retrieve the explicit template argument list that followed the
+  /// member template name, if any.
+  const ExplicitTemplateArgumentList *getExplicitTemplateArgs() const {
+    return const_cast<UnresolvedMemberExpr*>(this)->getExplicitTemplateArgs();
+  }
+
+  UnresolvedMemberExpr(QualType T, bool Dependent,
+                       bool HasUnresolvedUsing,
+                       Expr *Base, bool IsArrow,
+                       SourceLocation OperatorLoc,
+                       NestedNameSpecifier *Qualifier,
+                       SourceRange QualifierRange,
+                       DeclarationName Member,
+                       SourceLocation MemberLoc,
+                       const TemplateArgumentListInfo *TemplateArgs);
+
+public:
+  static UnresolvedMemberExpr *
+  Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing,
+         Expr *Base, bool IsArrow,
+         SourceLocation OperatorLoc,
+         NestedNameSpecifier *Qualifier,
+         SourceRange QualifierRange,
+         DeclarationName Member,
+         SourceLocation MemberLoc,
+         const TemplateArgumentListInfo *TemplateArgs);
+
+  /// Adds a declaration to the unresolved set.  By assumption, all of
+  /// these happen at initialization time and properties like
+  /// 'Dependent' and 'HasUnresolvedUsing' take them into account.
+  void addDecl(NamedDecl *Decl) {
+    Results.addDecl(Decl);
+  }
+
+  typedef UnresolvedSet::iterator decls_iterator;
+  decls_iterator decls_begin() const { return Results.begin(); }
+  decls_iterator decls_end() const { return Results.end(); }
+
+  unsigned getNumDecls() const { return Results.size(); }
+
+  /// \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 nested-name-specifier that qualifies the member
+  /// name.
+  NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+  /// \brief Retrieve the source range covering the nested-name-specifier
+  /// that qualifies the member name.
+  SourceRange getQualifierRange() const { return QualifierRange; }
+
+  /// \brief Retrieve the name of the member that this expression
+  /// refers to.
+  DeclarationName getMemberName() const { return MemberName; }
+  void setMemberName(DeclarationName N) { MemberName = 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; }
+
+  /// \brief Determines whether this member expression actually had a C++
+  /// template argument list explicitly specified, e.g., x.f<int>.
+  bool hasExplicitTemplateArgs() const {
+    return HasExplicitTemplateArgs;
+  }
+
+  /// \brief Copies the template arguments into the given structure.
+  void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+    getExplicitTemplateArgs()->copyInto(List);
+  }
+
+  /// \brief Retrieve the location of the left angle bracket following
+  /// the member name ('<').
+  SourceLocation getLAngleLoc() const {
+    return getExplicitTemplateArgs()->LAngleLoc;
+  }
+
+  /// \brief Retrieve the template arguments provided as part of this
+  /// template-id.
+  const TemplateArgumentLoc *getTemplateArgs() const {
+    return getExplicitTemplateArgs()->getTemplateArgs();
+  }
+
+  /// \brief Retrieve the number of template arguments provided as
+  /// part of this template-id.
+  unsigned getNumTemplateArgs() const {
+    return getExplicitTemplateArgs()->NumTemplateArgs;
+  }
+
+  /// \brief Retrieve the location of the right angle bracket
+  /// following the template arguments ('>').
+  SourceLocation getRAngleLoc() const {
+    return getExplicitTemplateArgs()->RAngleLoc;
+  }
+
+  virtual SourceRange getSourceRange() const {
+    SourceRange Range = Base->getSourceRange();
+    if (hasExplicitTemplateArgs())
+      Range.setEnd(getRAngleLoc());
+    else
+      Range.setEnd(MemberLoc);
+    return Range;
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == UnresolvedMemberExprClass;
+  }
+  static bool classof(const UnresolvedMemberExpr *) { return true; }
+
+  // Iterators
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+};
+
 }  // end namespace clang
 
 #endif

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

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Mon Nov 30 16:42:35 2009
@@ -171,6 +171,14 @@
   }
   virtual ~Stmt() {}
 
+#ifndef NDEBUG
+  /// \brief True if this statement's refcount is in a valid state.
+  /// Should be used only in assertions.
+  bool isRetained() const {
+    return (RefCount >= 1);
+  }
+#endif
+
   /// \brief Destroy the current statement and its children.
   void Destroy(ASTContext &Ctx) {
     assert(RefCount >= 1);

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

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Mon Nov 30 16:42:35 2009
@@ -133,6 +133,7 @@
 EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
 EXPR(CXXUnresolvedConstructExpr, Expr)
 EXPR(CXXDependentScopeMemberExpr, Expr)
+EXPR(UnresolvedMemberExpr   , Expr)
 
 // Obj-C Expressions.
 EXPR(ObjCStringLiteral    , Expr)

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=90161&r1=90160&r2=90161&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Nov 30 16:42:35 2009
@@ -2085,6 +2085,8 @@
   "inherited virtual base class">;
 def err_not_direct_base_or_virtual : Error<
   "type %0 is not a direct or virtual base of '%1'">;
+def err_not_direct_base_or_virtual_multi : Error<
+  "type %0 is not a direct or virtual base of '%1'">;
 
 def err_in_class_initializer_non_integral_type : Error<
   "in-class initializer has non-integral, non-enumeration type %0">;

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

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Nov 30 16:42:35 2009
@@ -1525,6 +1525,7 @@
   case Expr::CXXTemporaryObjectExprClass:
   case Expr::CXXUnresolvedConstructExprClass:
   case Expr::CXXDependentScopeMemberExprClass:
+  case Expr::UnresolvedMemberExprClass:
   case Expr::ObjCStringLiteralClass:
   case Expr::ObjCEncodeExprClass:
   case Expr::ObjCMessageExprClass:

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

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Nov 30 16:42:35 2009
@@ -573,3 +573,52 @@
 Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() {
   return child_iterator(&Base + 1);
 }
+
+UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent,
+                                           bool HasUnresolvedUsing,
+                                           Expr *Base, bool IsArrow,
+                                           SourceLocation OperatorLoc,
+                                           NestedNameSpecifier *Qualifier,
+                                           SourceRange QualifierRange,
+                                           DeclarationName MemberName,
+                                           SourceLocation MemberLoc,
+                                   const TemplateArgumentListInfo *TemplateArgs)
+  : Expr(UnresolvedMemberExprClass, T, Dependent, Dependent),
+    Base(Base), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
+    HasExplicitTemplateArgs(TemplateArgs != 0),
+    OperatorLoc(OperatorLoc),
+    Qualifier(Qualifier), QualifierRange(QualifierRange),
+    MemberName(MemberName), MemberLoc(MemberLoc) {
+  if (TemplateArgs)
+    getExplicitTemplateArgs()->initializeFrom(*TemplateArgs);
+}
+
+UnresolvedMemberExpr *
+UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent,
+                             bool HasUnresolvedUsing,
+                             Expr *Base, bool IsArrow,
+                             SourceLocation OperatorLoc,
+                             NestedNameSpecifier *Qualifier,
+                             SourceRange QualifierRange,
+                             DeclarationName Member,
+                             SourceLocation MemberLoc,
+                             const TemplateArgumentListInfo *TemplateArgs) {
+  std::size_t size = sizeof(UnresolvedMemberExpr);
+  if (TemplateArgs)
+    size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
+
+  void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>());
+  return new (Mem) UnresolvedMemberExpr(
+                             Dependent ? C.DependentTy : C.OverloadTy,
+                             Dependent, HasUnresolvedUsing, Base, IsArrow,
+                             OperatorLoc, Qualifier, QualifierRange,
+                             Member, MemberLoc, TemplateArgs);
+}
+
+Stmt::child_iterator UnresolvedMemberExpr::child_begin() {
+  return child_iterator(&Base);
+}
+
+Stmt::child_iterator UnresolvedMemberExpr::child_end() {
+  return child_iterator(&Base + 1);
+}

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

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Nov 30 16:42:35 2009
@@ -1163,6 +1163,24 @@
   }
 }
 
+void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
+  PrintExpr(Node->getBase());
+  OS << (Node->isArrow() ? "->" : ".");
+  if (NestedNameSpecifier *Qualifier = Node->getQualifier())
+    Qualifier->print(OS, Policy);
+
+  // FIXME: this might originally have been written with 'template'
+
+  OS << Node->getMemberName().getAsString();
+
+  if (Node->hasExplicitTemplateArgs()) {
+    OS << TemplateSpecializationType::PrintTemplateArgumentList(
+                                                    Node->getTemplateArgs(),
+                                                    Node->getNumTemplateArgs(),
+                                                    Policy);
+  }
+}
+
 static const char *getTypeTraitName(UnaryTypeTrait UTT) {
   switch (UTT) {
   default: assert(false && "Unknown type trait");

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

==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Mon Nov 30 16:42:35 2009
@@ -558,6 +558,19 @@
   ID.AddBoolean(S->isArrow());
   VisitNestedNameSpecifier(S->getQualifier());
   VisitName(S->getMember());
+  ID.AddBoolean(S->hasExplicitTemplateArgumentList());
+  if (S->hasExplicitTemplateArgumentList())
+    VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+}
+
+void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) {
+  VisitExpr(S);
+  ID.AddBoolean(S->isArrow());
+  VisitNestedNameSpecifier(S->getQualifier());
+  VisitName(S->getMemberName());
+  ID.AddBoolean(S->hasExplicitTemplateArgs());
+  if (S->hasExplicitTemplateArgs())
+    VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
 }
 
 void StmtProfiler::VisitObjCStringLiteral(ObjCStringLiteral *S) {

Modified: cfe/trunk/lib/Sema/Lookup.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Lookup.h?rev=90161&r1=90160&r2=90161&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Lookup.h (original)
+++ cfe/trunk/lib/Sema/Lookup.h Mon Nov 30 16:42:35 2009
@@ -213,6 +213,10 @@
     return getResultKind() == FoundOverloaded;
   }
 
+  bool isUnresolvableResult() const {
+    return getResultKind() == FoundUnresolvedValue;
+  }
+
   LookupResultKind getResultKind() const {
     sanity();
     return ResultKind;

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=90161&r1=90160&r2=90161&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Nov 30 16:42:35 2009
@@ -459,13 +459,20 @@
   virtual void DeleteExpr(ExprTy *E);
   virtual void DeleteStmt(StmtTy *S);
 
-  OwningExprResult Owned(Expr* E) { return OwningExprResult(*this, E); }
+  OwningExprResult Owned(Expr* E) {
+    assert(!E || E->isRetained());
+    return OwningExprResult(*this, E);
+  }
   OwningExprResult Owned(ExprResult R) {
     if (R.isInvalid())
       return ExprError();
+    assert(!R.get() || ((Expr*) R.get())->isRetained());
     return OwningExprResult(*this, R.get());
   }
-  OwningStmtResult Owned(Stmt* S) { return OwningStmtResult(*this, S); }
+  OwningStmtResult Owned(Stmt* S) {
+    assert(!S || S->isRetained());
+    return OwningStmtResult(*this, S);
+  }
 
   virtual void ActOnEndOfTranslationUnit();
 
@@ -516,7 +523,7 @@
   /// \brief Create a LocInfoType to hold the given QualType and DeclaratorInfo.
   QualType CreateLocInfoType(QualType T, DeclaratorInfo *DInfo);
   DeclarationName GetNameForDeclarator(Declarator &D);
-  DeclarationName GetNameFromUnqualifiedId(UnqualifiedId &Name);
+  DeclarationName GetNameFromUnqualifiedId(const UnqualifiedId &Name);
   static QualType GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo = 0);
   bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
   bool CheckDistantExceptionSpec(QualType T);
@@ -1517,31 +1524,40 @@
                                                    ExprArg Idx,
                                                    SourceLocation RLoc);
 
-  OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
+  OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
                                             SourceLocation OpLoc,
-                                            tok::TokenKind OpKind,
-                                            SourceLocation MemberLoc,
-                                            DeclarationName MemberName,
-                                            DeclPtrTy ImplDecl,
-                                            const CXXScopeSpec *SS = 0,
-                                          NamedDecl *FirstQualifierInScope = 0) {
-    // FIXME: Temporary helper while we migrate existing calls to
-    // BuildMemberReferenceExpr to support explicitly-specified template
-    // arguments.
-    return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc,
-                                    MemberName, 0, ImplDecl, SS,
-                                    FirstQualifierInScope);
-  }
+                                            bool IsArrow,
+                                            const CXXScopeSpec &SS,
+                                            NamedDecl *FirstQualifierInScope,
+                                            DeclarationName Name,
+                                            SourceLocation NameLoc,
+                                const TemplateArgumentListInfo *TemplateArgs);
 
-  OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
+  OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
+                                            SourceLocation OpLoc, bool IsArrow,
+                                            const CXXScopeSpec &SS,
+                                            LookupResult &R,
+                                 const TemplateArgumentListInfo *TemplateArgs);
+
+  OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
+                                    bool IsArrow, SourceLocation OpLoc,
+                                    const CXXScopeSpec &SS,
+                                    NamedDecl *FirstQualifierInScope,
+                                    DeclPtrTy ObjCImpDecl);
+
+  bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
+                                     NestedNameSpecifier *Qualifier,
+                                     SourceRange QualifierRange,
+                                     const LookupResult &R);
+
+  OwningExprResult ActOnDependentMemberExpr(ExprArg Base,
+                                            bool IsArrow,
                                             SourceLocation OpLoc,
-                                            tok::TokenKind OpKind,
-                                            SourceLocation MemberLoc,
-                                            DeclarationName MemberName,
-                        const TemplateArgumentListInfo *ExplicitTemplateArgs,
-                                            DeclPtrTy ImplDecl,
-                                            const CXXScopeSpec *SS,
-                                          NamedDecl *FirstQualifierInScope = 0);
+                                            const CXXScopeSpec &SS,
+                                            NamedDecl *FirstQualifierInScope,
+                                            DeclarationName Name,
+                                            SourceLocation NameLoc,
+                               const TemplateArgumentListInfo *TemplateArgs);
 
   virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
                                                  SourceLocation OpLoc,
@@ -2140,9 +2156,7 @@
                                  FunctionDecl::StorageClass& SC);
   DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
 
-  bool isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
-                                 SourceLocation NameLoc, QualType &ThisType,
-                                 QualType &MemberType);
+  bool isImplicitMemberReference(const LookupResult &R, QualType &ThisType);
   
   //===--------------------------------------------------------------------===//
   // C++ Derived Classes

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Nov 30 16:42:35 2009
@@ -1757,7 +1757,7 @@
 }
 
 /// \brief Retrieves the canonicalized name from a parsed unqualified-id.
-DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) {
+DeclarationName Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
   switch (Name.getKind()) {
     case UnqualifiedId::IK_Identifier:
       return DeclarationName(Name.Identifier);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Nov 30 16:42:35 2009
@@ -617,7 +617,54 @@
   return Owned(Result);
 }
 
-static void DecomposeTemplateName(LookupResult &R, TemplateName TName) {
+/// Decomposes the given name into a DeclarationName, its location, and
+/// possibly a list of template arguments.
+///
+/// If this produces template arguments, it is permitted to call
+/// DecomposeTemplateName.
+///
+/// This actually loses a lot of source location information for
+/// non-standard name kinds; we should consider preserving that in
+/// some way.
+static void DecomposeUnqualifiedId(Sema &SemaRef,
+                                   const UnqualifiedId &Id,
+                                   TemplateArgumentListInfo &Buffer,
+                                   DeclarationName &Name,
+                                   SourceLocation &NameLoc,
+                             const TemplateArgumentListInfo *&TemplateArgs) {
+  if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
+    Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
+    Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
+
+    ASTTemplateArgsPtr TemplateArgsPtr(SemaRef,
+                                       Id.TemplateId->getTemplateArgs(),
+                                       Id.TemplateId->NumArgs);
+    SemaRef.translateTemplateArguments(TemplateArgsPtr, Buffer);
+    TemplateArgsPtr.release();
+
+    TemplateName TName =
+      Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
+
+    Name = SemaRef.Context.getNameForTemplate(TName);
+    NameLoc = Id.TemplateId->TemplateNameLoc;
+    TemplateArgs = &Buffer;
+  } else {
+    Name = SemaRef.GetNameFromUnqualifiedId(Id);
+    NameLoc = Id.StartLocation;
+    TemplateArgs = 0;
+  }
+}
+
+/// Decompose the given template name into a list of lookup results.
+///
+/// The unqualified ID must name a non-dependent template, which can
+/// be more easily tested by checking whether DecomposeUnqualifiedId
+/// found template arguments.
+static void DecomposeTemplateName(LookupResult &R, const UnqualifiedId &Id) {
+  assert(Id.getKind() == UnqualifiedId::IK_TemplateId);
+  TemplateName TName =
+    Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
+
   if (TemplateDecl *TD = TName.getAsTemplateDecl())
     R.addDecl(TD);
   else if (OverloadedFunctionDecl *OD
@@ -628,6 +675,42 @@
   R.resolveKind();
 }
 
+static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) {
+  for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
+         E = Record->bases_end(); I != E; ++I) {
+    CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType());
+    CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>();
+    if (!BaseRT) return false;
+
+    CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
+    if (!BaseRecord->isDefinition() ||
+        !IsFullyFormedScope(SemaRef, BaseRecord))
+      return false;
+  }
+
+  return true;
+}
+
+/// Determines whether the given scope is "fully-formed": i.e. we can
+/// look into it because it's either non-dependent or is the current
+/// instantiation and has no dependent base classes.
+static bool IsFullyFormedScope(Sema &SemaRef, const CXXScopeSpec &SS) {
+  DeclContext *DC = SemaRef.computeDeclContext(SS, false);
+  if (!DC) return false;
+  if (!DC->isDependentContext()) return true;
+  return IsFullyFormedScope(SemaRef, cast<CXXRecordDecl>(DC));
+}
+
+static bool IsFullyFormedScope(Sema &SemaRef, DeclContext *DC) {
+  if (isa<CXXMethodDecl>(DC))
+    return IsFullyFormedScope(SemaRef,
+                  cast<CXXRecordDecl>(cast<CXXMethodDecl>(DC)->getParent()));
+  else if (isa<CXXRecordDecl>(DC))
+    return IsFullyFormedScope(SemaRef, cast<CXXRecordDecl>(DC));
+  else
+    return true;
+}
+
 Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
                                                const CXXScopeSpec &SS,
                                                UnqualifiedId &Id,
@@ -639,33 +722,14 @@
   if (SS.isInvalid())
     return ExprError();
 
-  TemplateArgumentListInfo ExplicitTemplateArgs;
+  TemplateArgumentListInfo TemplateArgsBuffer;
 
   // Decompose the UnqualifiedId into the following data.
   DeclarationName Name;
   SourceLocation NameLoc;
   const TemplateArgumentListInfo *TemplateArgs;
-  if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
-    ExplicitTemplateArgs.setLAngleLoc(Id.TemplateId->LAngleLoc);
-    ExplicitTemplateArgs.setRAngleLoc(Id.TemplateId->RAngleLoc);
-
-    ASTTemplateArgsPtr TemplateArgsPtr(*this,
-                                       Id.TemplateId->getTemplateArgs(),
-                                       Id.TemplateId->NumArgs);
-    translateTemplateArguments(TemplateArgsPtr, ExplicitTemplateArgs);
-    TemplateArgsPtr.release();
-
-    TemplateName TName =
-      TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
-
-    Name = Context.getNameForTemplate(TName);
-    NameLoc = Id.TemplateId->TemplateNameLoc;
-    TemplateArgs = &ExplicitTemplateArgs;
-  } else {
-    Name = GetNameFromUnqualifiedId(Id);
-    NameLoc = Id.StartLocation;
-    TemplateArgs = 0;
-  }
+  DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer,
+                         Name, NameLoc, TemplateArgs);
 
   IdentifierInfo *II = Name.getAsIdentifierInfo();
 
@@ -675,7 +739,8 @@
   //        names a dependent type.
   // Determine whether this is a member of an unknown specialization;
   // we need to handle these differently.
-  if (SS.isSet() && !computeDeclContext(SS, false)) {
+  if (SS.isSet() && !(IsFullyFormedScope(*this, SS) &&
+                      IsFullyFormedScope(*this, CurContext))) {
     bool CheckForImplicitMember = !isAddressOfOperand;
 
     return ActOnDependentIdExpression(SS, Name, NameLoc,
@@ -686,11 +751,8 @@
   // Perform the required lookup.
   LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
   if (TemplateArgs) {
-    TemplateName TName =
-      TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
-
     // Just re-use the lookup done by isTemplateName.
-    DecomposeTemplateName(R, TName);
+    DecomposeTemplateName(R, Id);
   } else {
     LookupParsedName(R, S, &SS, true);
 
@@ -806,9 +868,10 @@
   return BuildDeclarationNameExpr(SS, R, ADL);
 }
 
-/// ActOnDeclarationNameExpr - Build a C++ qualified declaration name,
-/// generally during template instantiation.  There's a large number
-/// of things which don't need to be done along this path.
+/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
+/// declaration name, generally during template instantiation.
+/// There's a large number of things which don't need to be done along
+/// this path.
 Sema::OwningExprResult
 Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
                                         DeclarationName Name,
@@ -959,20 +1022,42 @@
 
 /// \brief Build a MemberExpr AST node.
 static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
-                                   const CXXScopeSpec *SS, NamedDecl *Member,
+                                   const CXXScopeSpec &SS, NamedDecl *Member,
                                    SourceLocation Loc, QualType Ty,
                           const TemplateArgumentListInfo *TemplateArgs = 0) {
   NestedNameSpecifier *Qualifier = 0;
   SourceRange QualifierRange;
-  if (SS && SS->isSet()) {
-    Qualifier = (NestedNameSpecifier *) SS->getScopeRep();
-    QualifierRange = SS->getRange();
+  if (SS.isSet()) {
+    Qualifier = (NestedNameSpecifier *) SS.getScopeRep();
+    QualifierRange = SS.getRange();
   }
 
   return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
                             Member, Loc, TemplateArgs, Ty);
 }
 
+/// Return true if all the decls in the given result are instance
+/// methods.
+static bool IsOnlyInstanceMethods(const LookupResult &R) {
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    NamedDecl *D = (*I)->getUnderlyingDecl();
+
+    CXXMethodDecl *Method;
+    if (isa<FunctionTemplateDecl>(D))
+      Method = cast<CXXMethodDecl>(cast<FunctionTemplateDecl>(D)
+                                   ->getTemplatedDecl());
+    else if (isa<CXXMethodDecl>(D))
+      Method = cast<CXXMethodDecl>(D);
+    else
+      return false;
+
+    if (Method->isStatic())
+      return false;
+  }
+
+  return true;
+}
+
 /// Builds an implicit member access expression from the given
 /// unqualified lookup set, which is known to contain only class
 /// members.
@@ -982,50 +1067,35 @@
                               const TemplateArgumentListInfo *TemplateArgs) {
   assert(!R.empty() && !R.isAmbiguous());
 
-  NamedDecl *D = R.getAsSingleDecl(Context);
   SourceLocation Loc = R.getNameLoc();
 
   // We may have found a field within an anonymous union or struct
   // (C++ [class.union]).
   // FIXME: This needs to happen post-isImplicitMemberReference?
   // FIXME: template-ids inside anonymous structs?
-  if (FieldDecl *FD = dyn_cast<FieldDecl>(D))
+  if (FieldDecl *FD = R.getAsSingle<FieldDecl>())
     if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
       return BuildAnonymousStructUnionMemberReference(Loc, FD);
 
   QualType ThisType;
-  QualType MemberType;
-  if (isImplicitMemberReference(SS, D, Loc, ThisType, MemberType)) {
+  if (isImplicitMemberReference(R, ThisType)) {
     Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType);
-    MarkDeclarationReferenced(Loc, D);
-    if (PerformObjectMemberConversion(This, D))
-      return ExprError();
-
-    bool ShouldCheckUse = true;
-    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
-      // Don't diagnose the use of a virtual member function unless it's
-      // explicitly qualified.
-      if (MD->isVirtual() && !SS.isSet())
-        ShouldCheckUse = false;
-    }
-
-    if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc))
-      return ExprError();
-    return Owned(BuildMemberExpr(Context, This, true, &SS, D, Loc, MemberType,
-                                 TemplateArgs));
+    return BuildMemberReferenceExpr(ExprArg(*this, This),
+                                    /*OpLoc*/ SourceLocation(),
+                                    /*IsArrow*/ true,
+                                    SS, R, TemplateArgs);
   }
 
-  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
-    if (!Method->isStatic())
-      return ExprError(Diag(Loc, diag::err_member_call_without_object));
-  }
+  // Diagnose now if none of the available methods are static.
+  if (IsOnlyInstanceMethods(R))
+    return ExprError(Diag(Loc, diag::err_member_call_without_object));
 
-  if (isa<FieldDecl>(D)) {
+  if (R.getAsSingle<FieldDecl>()) {
     if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
       if (MD->isStatic()) {
         // "invalid use of member 'x' in static member function"
         Diag(Loc, diag::err_invalid_member_use_in_static_method)
-          << D->getDeclName();
+          << R.getLookupName();
         return ExprError();
       }
     }
@@ -1034,7 +1104,7 @@
     // program would have been turned into implicit member expressions
     // above.
     Diag(Loc, diag::err_invalid_non_static_member_use)
-      << D->getDeclName();
+      << R.getLookupName();
     return ExprError();
   }
 
@@ -1876,29 +1946,318 @@
   return GDecl;
 }
 
-Action::OwningExprResult
-Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
-                               tok::TokenKind OpKind, SourceLocation MemberLoc,
-                               DeclarationName MemberName,
-                          const TemplateArgumentListInfo *ExplicitTemplateArgs,
-                               DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS,
-                               NamedDecl *FirstQualifierInScope) {
-  if (SS && SS->isInvalid())
+Sema::OwningExprResult
+Sema::ActOnDependentMemberExpr(ExprArg Base, bool IsArrow, SourceLocation OpLoc,
+                               const CXXScopeSpec &SS,
+                               NamedDecl *FirstQualifierInScope,
+                               DeclarationName Name, SourceLocation NameLoc,
+                               const TemplateArgumentListInfo *TemplateArgs) {
+  Expr *BaseExpr = Base.takeAs<Expr>();
+
+  // Even in dependent contexts, try to diagnose base expressions with
+  // obviously wrong types, e.g.:
+  //
+  // T* t;
+  // t.f;
+  //
+  // In Obj-C++, however, the above expression is valid, since it could be
+  // accessing the 'f' property if T is an Obj-C interface. The extra check
+  // allows this, while still reporting an error if T is a struct pointer.
+  if (!IsArrow) {
+    const PointerType *PT = BaseExpr->getType()->getAs<PointerType>();
+    if (PT && (!getLangOptions().ObjC1 ||
+               PT->getPointeeType()->isRecordType())) {
+      Diag(NameLoc, diag::err_typecheck_member_reference_struct_union)
+        << BaseExpr->getType() << BaseExpr->getSourceRange();
+      return ExprError();
+    }
+  }
+
+  assert(BaseExpr->getType()->isDependentType());
+
+  // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
+  // must have pointer type, and the accessed type is the pointee.
+  return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr,
+                                                   IsArrow, OpLoc,
+                 static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
+                                                   SS.getRange(),
+                                                   FirstQualifierInScope,
+                                                   Name, NameLoc,
+                                                   TemplateArgs));
+}
+
+/// We know that the given qualified member reference points only to
+/// declarations which do not belong to the static type of the base
+/// expression.  Diagnose the problem.
+static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
+                                             Expr *BaseExpr,
+                                             QualType BaseType,
+                                             NestedNameSpecifier *Qualifier,
+                                             SourceRange QualifierRange,
+                                             const LookupResult &R) {
+  DeclContext *DC = R.getRepresentativeDecl()->getDeclContext();
+
+  // FIXME: this is an exceedingly lame diagnostic for some of the more
+  // complicated cases here.
+  SemaRef.Diag(R.getNameLoc(), diag::err_not_direct_base_or_virtual)
+    << QualifierRange << DC << BaseType;
+}
+
+// Check whether the declarations we found through a nested-name
+// specifier in a member expression are actually members of the base
+// type.  The restriction here is:
+//
+//   C++ [expr.ref]p2:
+//     ... In these cases, the id-expression shall name a
+//     member of the class or of one of its base classes.
+//
+// So it's perfectly legitimate for the nested-name specifier to name
+// an unrelated class, and for us to find an overload set including
+// decls from classes which are not superclasses, as long as the decl
+// we actually pick through overload resolution is from a superclass.
+bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
+                                         QualType BaseType,
+                                         NestedNameSpecifier *Qualifier,
+                                         SourceRange QualifierRange,
+                                         const LookupResult &R) {
+  QualType BaseTypeCanon
+    = Context.getCanonicalType(BaseType).getUnqualifiedType();
+
+  bool FoundValid = false;
+
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    TypeDecl* TyD = cast<TypeDecl>((*I)->getUnderlyingDecl()->getDeclContext());
+    CanQualType MemberTypeCanon
+      = Context.getCanonicalType(Context.getTypeDeclType(TyD));
+
+    if (BaseTypeCanon == MemberTypeCanon ||
+        IsDerivedFrom(BaseTypeCanon, MemberTypeCanon)) {
+      FoundValid = true;
+      break;
+    }
+  }
+
+  if (!FoundValid) {
+    DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType,
+                                     Qualifier, QualifierRange, R);
+    return true;
+  }
+
+  return false;
+}
+
+Sema::OwningExprResult
+Sema::BuildMemberReferenceExpr(ExprArg BaseArg,
+                               SourceLocation OpLoc, bool IsArrow,
+                               const CXXScopeSpec &SS,
+                               NamedDecl *FirstQualifierInScope,
+                               DeclarationName Name, SourceLocation NameLoc,
+                               const TemplateArgumentListInfo *TemplateArgs) {
+  Expr *Base = BaseArg.takeAs<Expr>();
+
+  if (Base->getType()->isDependentType())
+    return ActOnDependentMemberExpr(ExprArg(*this, Base),
+                                    IsArrow, OpLoc,
+                                    SS, FirstQualifierInScope,
+                                    Name, NameLoc,
+                                    TemplateArgs);
+
+  LookupResult R(*this, Name, NameLoc, LookupMemberName);
+  OwningExprResult Result =
+    LookupMemberExpr(R, Base, IsArrow, OpLoc,
+                     SS, FirstQualifierInScope,
+                     /*ObjCImpDecl*/ DeclPtrTy());
+
+  if (Result.isInvalid()) {
+    Owned(Base);
     return ExprError();
+  }
 
-  // Since this might be a postfix expression, get rid of ParenListExprs.
-  Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
+  if (Result.get())
+    return move(Result);
+
+  return BuildMemberReferenceExpr(ExprArg(*this, Base), OpLoc,
+                                  IsArrow, SS, R, TemplateArgs);
+}
 
+Sema::OwningExprResult
+Sema::BuildMemberReferenceExpr(ExprArg Base, SourceLocation OpLoc,
+                               bool IsArrow, const CXXScopeSpec &SS,
+                               LookupResult &R,
+                         const TemplateArgumentListInfo *TemplateArgs) {
   Expr *BaseExpr = Base.takeAs<Expr>();
+  QualType BaseType = BaseExpr->getType();
+  if (IsArrow) {
+    assert(BaseType->isPointerType());
+    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+  }
+
+  NestedNameSpecifier *Qualifier =
+    static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+  DeclarationName MemberName = R.getLookupName();
+  SourceLocation MemberLoc = R.getNameLoc();
+
+  if (R.isAmbiguous())
+    return ExprError();
+
+  if (R.empty()) {
+    // Rederive where we looked up.
+    DeclContext *DC = (SS.isSet()
+                       ? computeDeclContext(SS, false)
+                       : BaseType->getAs<RecordType>()->getDecl());
+
+    Diag(R.getNameLoc(), diag::err_no_member)
+      << MemberName << DC << BaseExpr->getSourceRange();
+    return ExprError();
+  }
+
+  // We can't always diagnose the problem yet: it's permitted for
+  // lookup to find things from an invalid context as long as they
+  // don't get picked by overload resolution.
+  if (SS.isSet() && CheckQualifiedMemberReference(BaseExpr, BaseType,
+                                                  Qualifier, SS.getRange(), R))
+    return ExprError();
+
+  // Construct an unresolved result if we in fact got an unresolved
+  // result.
+  if (R.isOverloadedResult() || R.isUnresolvableResult()) {
+    bool Dependent = R.isUnresolvableResult();
+    Dependent = Dependent ||
+                UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(),
+                                                        TemplateArgs);
+
+    UnresolvedMemberExpr *MemExpr
+      = UnresolvedMemberExpr::Create(Context, Dependent,
+                                     R.isUnresolvableResult(),
+                                     BaseExpr, IsArrow, OpLoc,
+                                     Qualifier, SS.getRange(),
+                                     MemberName, MemberLoc,
+                                     TemplateArgs);
+    for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+      MemExpr->addDecl(*I);
+
+    return Owned(MemExpr);
+  }
+
+  assert(R.isSingleResult());  
+  NamedDecl *MemberDecl = R.getFoundDecl();
+
+  // FIXME: diagnose the presence of template arguments now.
+
+  // If the decl being referenced had an error, return an error for this
+  // sub-expr without emitting another error, in order to avoid cascading
+  // error cases.
+  if (MemberDecl->isInvalidDecl())
+    return ExprError();
+
+  bool ShouldCheckUse = true;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+    // Don't diagnose the use of a virtual member function unless it's
+    // explicitly qualified.
+    if (MD->isVirtual() && !SS.isSet())
+      ShouldCheckUse = false;
+  }
+
+  // Check the use of this member.
+  if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) {
+    Owned(BaseExpr);
+    return ExprError();
+  }
+
+  if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
+    // We may have found a field within an anonymous union or struct
+    // (C++ [class.union]).
+    if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
+      return BuildAnonymousStructUnionMemberReference(MemberLoc, FD,
+                                                      BaseExpr, OpLoc);
+
+    // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
+    QualType MemberType = FD->getType();
+    if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
+      MemberType = Ref->getPointeeType();
+    else {
+      Qualifiers BaseQuals = BaseType.getQualifiers();
+      BaseQuals.removeObjCGCAttr();
+      if (FD->isMutable()) BaseQuals.removeConst();
+
+      Qualifiers MemberQuals
+        = Context.getCanonicalType(MemberType).getQualifiers();
+
+      Qualifiers Combined = BaseQuals + MemberQuals;
+      if (Combined != MemberQuals)
+        MemberType = Context.getQualifiedType(MemberType, Combined);
+    }
+
+    MarkDeclarationReferenced(MemberLoc, FD);
+    if (PerformObjectMemberConversion(BaseExpr, FD))
+      return ExprError();
+    return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+                                 FD, MemberLoc, MemberType));
+  }
+
+  if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
+    MarkDeclarationReferenced(MemberLoc, Var);
+    return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+                                 Var, MemberLoc,
+                                 Var->getType().getNonReferenceType()));
+  }
+
+  if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
+    MarkDeclarationReferenced(MemberLoc, MemberDecl);
+    return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+                                 MemberFn, MemberLoc,
+                                 MemberFn->getType()));
+  }
+
+  if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
+    MarkDeclarationReferenced(MemberLoc, MemberDecl);
+    return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+                                 Enum, MemberLoc, Enum->getType()));
+  }
+
+  Owned(BaseExpr);
+
+  if (isa<TypeDecl>(MemberDecl))
+    return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type)
+                     << MemberName << int(IsArrow));
+
+  // We found a declaration kind that we didn't expect. This is a
+  // generic error message that tells the user that she can't refer
+  // to this member with '.' or '->'.
+  return ExprError(Diag(MemberLoc,
+                        diag::err_typecheck_member_reference_unknown)
+      << MemberName << int(IsArrow));
+}
+
+/// Look up the given member of the given non-type-dependent
+/// expression.  This can return in one of two ways:
+///  * If it returns a sentinel null-but-valid result, the caller will
+///    assume that lookup was performed and the results written into
+///    the provided structure.  It will take over from there.
+///  * Otherwise, the returned expression will be produced in place of
+///    an ordinary member expression.
+///
+/// The ObjCImpDecl bit is a gross hack that will need to be properly
+/// fixed for ObjC++.
+Sema::OwningExprResult
+Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
+                       bool IsArrow, SourceLocation OpLoc,
+                       const CXXScopeSpec &SS,
+                       NamedDecl *FirstQualifierInScope,
+                       DeclPtrTy ObjCImpDecl) {
   assert(BaseExpr && "no base expression");
 
   // Perform default conversions.
   DefaultFunctionArrayConversion(BaseExpr);
 
   QualType BaseType = BaseExpr->getType();
+  assert(!BaseType->isDependentType());
+
+  DeclarationName MemberName = R.getLookupName();
+  SourceLocation MemberLoc = R.getNameLoc();
 
   // If the user is trying to apply -> or . to a function pointer
-  // type, it's probably because the forgot parentheses to call that
+  // type, it's probably because they forgot parentheses to call that
   // function. Suggest the addition of those parentheses, build the
   // call, and continue on.
   if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
@@ -1906,8 +2265,8 @@
           = Ptr->getPointeeType()->getAs<FunctionProtoType>()) {
       QualType ResultTy = Fun->getResultType();
       if (Fun->getNumArgs() == 0 &&
-          ((OpKind == tok::period && ResultTy->isRecordType()) ||
-           (OpKind == tok::arrow && ResultTy->isPointerType() &&
+          ((!IsArrow && ResultTy->isRecordType()) ||
+           (IsArrow && ResultTy->isPointerType() &&
             ResultTy->getAs<PointerType>()->getPointeeType()
                                                           ->isRecordType()))) {
         SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
@@ -1916,10 +2275,10 @@
           << CodeModificationHint::CreateInsertion(Loc, "()");
         
         OwningExprResult NewBase
-          = ActOnCallExpr(S, ExprArg(*this, BaseExpr), Loc, 
+          = ActOnCallExpr(0, ExprArg(*this, BaseExpr), Loc, 
                           MultiExprArg(*this, 0, 0), 0, Loc);
         if (NewBase.isInvalid())
-          return move(NewBase);
+          return ExprError();
         
         BaseExpr = NewBase.takeAs<Expr>();
         DefaultFunctionArrayConversion(BaseExpr);
@@ -1938,6 +2297,7 @@
       ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
     }
   }
+
   // If this is an Objective-C pseudo-builtin and a definition is provided then
   // use that.
   if (Context.isObjCSelType(BaseType)) {
@@ -1948,10 +2308,11 @@
       ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
     }
   }
+
   assert(!BaseType.isNull() && "no type for member expression");
 
   // Handle properties on ObjC 'Class' types.
-  if (OpKind == tok::period && BaseType->isObjCClassType()) {
+  if (!IsArrow && BaseType->isObjCClassType()) {
     // Also must look for a getter name which uses property syntax.
     IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
     Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
@@ -2005,68 +2366,21 @@
     BaseType = Context.ObjCClassRedefinitionType;
     ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
   }
-  
-  // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
-  // must have pointer type, and the accessed type is the pointee.
-  if (OpKind == tok::arrow) {
-    if (BaseType->isDependentType()) {
-      NestedNameSpecifier *Qualifier = 0;
-      if (SS) {
-        Qualifier = static_cast<NestedNameSpecifier *>(SS->getScopeRep());
-        if (!FirstQualifierInScope)
-          FirstQualifierInScope = FindFirstQualifierInScope(S, Qualifier);
-      }
 
-      return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, true,
-                                                   OpLoc, Qualifier,
-                                            SS? SS->getRange() : SourceRange(),
-                                                   FirstQualifierInScope,
-                                                   MemberName,
-                                                   MemberLoc,
-                                                   ExplicitTemplateArgs));
-    }
-    else if (const PointerType *PT = BaseType->getAs<PointerType>())
+  if (IsArrow) {
+    if (const PointerType *PT = BaseType->getAs<PointerType>())
       BaseType = PT->getPointeeType();
     else if (BaseType->isObjCObjectPointerType())
       ;
-    else
-      return ExprError(Diag(MemberLoc,
-                            diag::err_typecheck_member_reference_arrow)
-        << BaseType << BaseExpr->getSourceRange());
-  } else if (BaseType->isDependentType()) {
-      // Require that the base type isn't a pointer type
-      // (so we'll report an error for)
-      // T* t;
-      // t.f;
-      //
-      // In Obj-C++, however, the above expression is valid, since it could be
-      // accessing the 'f' property if T is an Obj-C interface. The extra check
-      // allows this, while still reporting an error if T is a struct pointer.
-      const PointerType *PT = BaseType->getAs<PointerType>();
-
-      if (!PT || (getLangOptions().ObjC1 &&
-                  !PT->getPointeeType()->isRecordType())) {
-        NestedNameSpecifier *Qualifier = 0;
-        if (SS) {
-          Qualifier = static_cast<NestedNameSpecifier *>(SS->getScopeRep());
-          if (!FirstQualifierInScope)
-            FirstQualifierInScope = FindFirstQualifierInScope(S, Qualifier);
-        }
-
-        return Owned(CXXDependentScopeMemberExpr::Create(Context,
-                                                     BaseExpr, false,
-                                                     OpLoc,
-                                                     Qualifier,
-                                            SS? SS->getRange() : SourceRange(),
-                                                     FirstQualifierInScope,
-                                                     MemberName,
-                                                     MemberLoc,
-                                                     ExplicitTemplateArgs));
-      }
+    else {
+      Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
+        << BaseType << BaseExpr->getSourceRange();
+      return ExprError();
     }
+  }
 
-  // Handle field access to simple records.  This also handles access to fields
-  // of the ObjC 'id' struct.
+  // Handle field access to simple records.  This also handles access
+  // to fields of the ObjC 'id' struct.
   if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
     RecordDecl *RDecl = RTy->getDecl();
     if (RequireCompleteType(OpLoc, BaseType,
@@ -2075,14 +2389,14 @@
       return ExprError();
 
     DeclContext *DC = RDecl;
-    if (SS && SS->isSet()) {
+    if (SS.isSet()) {
       // If the member name was a qualified-id, look into the
       // nested-name-specifier.
-      DC = computeDeclContext(*SS, false);
+      DC = computeDeclContext(SS, false);
       
       if (!isa<TypeDecl>(DC)) {
         Diag(MemberLoc, diag::err_qualified_member_nonclass)
-          << DC << SS->getRange();
+          << DC << SS.getRange();
         return ExprError();
       }
 
@@ -2092,135 +2406,8 @@
     }
 
     // The record definition is complete, now make sure the member is valid.
-    LookupResult Result(*this, MemberName, MemberLoc, LookupMemberName);
-    LookupQualifiedName(Result, DC);
-
-    if (Result.empty())
-      return ExprError(Diag(MemberLoc, diag::err_no_member)
-               << MemberName << DC << BaseExpr->getSourceRange());
-    if (Result.isAmbiguous())
-      return ExprError();
-
-    NamedDecl *MemberDecl = Result.getAsSingleDecl(Context);
-
-    if (SS && SS->isSet()) {
-      TypeDecl* TyD = cast<TypeDecl>(MemberDecl->getDeclContext());
-      QualType BaseTypeCanon
-        = Context.getCanonicalType(BaseType).getUnqualifiedType();
-      QualType MemberTypeCanon
-        = Context.getCanonicalType(Context.getTypeDeclType(TyD));
-
-      if (BaseTypeCanon != MemberTypeCanon &&
-          !IsDerivedFrom(BaseTypeCanon, MemberTypeCanon))
-        return ExprError(Diag(SS->getBeginLoc(),
-                              diag::err_not_direct_base_or_virtual)
-                         << MemberTypeCanon << BaseTypeCanon);
-    }
-
-    // If the decl being referenced had an error, return an error for this
-    // sub-expr without emitting another error, in order to avoid cascading
-    // error cases.
-    if (MemberDecl->isInvalidDecl())
-      return ExprError();
-
-    bool ShouldCheckUse = true;
-    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) {
-      // Don't diagnose the use of a virtual member function unless it's
-      // explicitly qualified.
-      if (MD->isVirtual() && (!SS || !SS->isSet()))
-        ShouldCheckUse = false;
-    }
-
-    // Check the use of this field
-    if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc))
-      return ExprError();
-
-    if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
-      // We may have found a field within an anonymous union or struct
-      // (C++ [class.union]).
-      if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
-        return BuildAnonymousStructUnionMemberReference(MemberLoc, FD,
-                                                        BaseExpr, OpLoc);
-
-      // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
-      QualType MemberType = FD->getType();
-      if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
-        MemberType = Ref->getPointeeType();
-      else {
-        Qualifiers BaseQuals = BaseType.getQualifiers();
-        BaseQuals.removeObjCGCAttr();
-        if (FD->isMutable()) BaseQuals.removeConst();
-
-        Qualifiers MemberQuals
-          = Context.getCanonicalType(MemberType).getQualifiers();
-
-        Qualifiers Combined = BaseQuals + MemberQuals;
-        if (Combined != MemberQuals)
-          MemberType = Context.getQualifiedType(MemberType, Combined);
-      }
-
-      MarkDeclarationReferenced(MemberLoc, FD);
-      if (PerformObjectMemberConversion(BaseExpr, FD))
-        return ExprError();
-      return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
-                                   FD, MemberLoc, MemberType));
-    }
-
-    if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
-      MarkDeclarationReferenced(MemberLoc, MemberDecl);
-      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(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
-                                   MemberFn, MemberLoc,
-                                   MemberFn->getType()));
-    }
-    if (FunctionTemplateDecl *FunTmpl
-          = dyn_cast<FunctionTemplateDecl>(MemberDecl)) {
-      MarkDeclarationReferenced(MemberLoc, MemberDecl);
-
-      if (ExplicitTemplateArgs)
-        return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow,
-                             (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0),
-                                       SS? SS->getRange() : SourceRange(),
-                                        FunTmpl, MemberLoc,
-                                        ExplicitTemplateArgs,
-                                        Context.OverloadTy));
-
-      return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
-                                   FunTmpl, MemberLoc,
-                                   Context.OverloadTy));
-    }
-    if (OverloadedFunctionDecl *Ovl
-          = dyn_cast<OverloadedFunctionDecl>(MemberDecl)) {
-      if (ExplicitTemplateArgs)
-        return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow,
-                             (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0),
-                                        SS? SS->getRange() : SourceRange(),
-                                        Ovl, MemberLoc, ExplicitTemplateArgs,
-                                        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(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)
-        << MemberName << int(OpKind == tok::arrow));
-
-    // We found a declaration kind that we didn't expect. This is a
-    // generic error message that tells the user that she can't refer
-    // to this member with '.' or '->'.
-    return ExprError(Diag(MemberLoc,
-                          diag::err_typecheck_member_reference_unknown)
-      << MemberName << int(OpKind == tok::arrow));
+    LookupQualifiedName(R, DC);
+    return Owned((Expr*) 0);
   }
 
   // Handle pseudo-destructors (C++ [expr.pseudo]). Since anything referring
@@ -2256,18 +2443,17 @@
     // FIXME: We've lost the precise spelling of the type by going through
     // DeclarationName. Can we do better?
     return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr,
-                                                       OpKind == tok::arrow,
-                                                       OpLoc,
-                            (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0),
-                                            SS? SS->getRange() : SourceRange(),
+                                                       IsArrow, OpLoc,
+                               (NestedNameSpecifier *) SS.getScopeRep(),
+                                                       SS.getRange(),
                                                    MemberName.getCXXNameType(),
                                                        MemberLoc));
   }
 
   // Handle access to Objective-C instance variables, such as "Obj->ivar" and
   // (*Obj).ivar.
-  if ((OpKind == tok::arrow && BaseType->isObjCObjectPointerType()) ||
-      (OpKind == tok::period && BaseType->isObjCInterfaceType())) {
+  if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+      (!IsArrow && BaseType->isObjCInterfaceType())) {
     const ObjCObjectPointerType *OPT = BaseType->getAs<ObjCObjectPointerType>();
     const ObjCInterfaceType *IFaceT =
       OPT ? OPT->getInterfaceType() : BaseType->getAs<ObjCInterfaceType>();
@@ -2322,7 +2508,7 @@
 
         return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
                                                    MemberLoc, BaseExpr,
-                                                   OpKind == tok::arrow));
+                                                   IsArrow));
       }
       return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
                          << IDecl->getDeclName() << MemberName
@@ -2330,8 +2516,8 @@
     }
   }
   // Handle properties on 'id' and qualified "id".
-  if (OpKind == tok::period && (BaseType->isObjCIdType() ||
-                                BaseType->isObjCQualifiedIdType())) {
+  if (!IsArrow && (BaseType->isObjCIdType() ||
+                   BaseType->isObjCQualifiedIdType())) {
     const ObjCObjectPointerType *QIdTy = BaseType->getAs<ObjCObjectPointerType>();
     IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
 
@@ -2364,8 +2550,7 @@
   // Handle Objective-C property access, which is "Obj.property" where Obj is a
   // pointer to a (potentially qualified) interface type.
   const ObjCObjectPointerType *OPT;
-  if (OpKind == tok::period &&
-      (OPT = BaseType->getAsObjCInterfacePointerType())) {
+  if (!IsArrow && (OPT = BaseType->getAsObjCInterfacePointerType())) {
     const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
     ObjCInterfaceDecl *IFace = IFaceT->getDecl();
     IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
@@ -2450,7 +2635,7 @@
   }
 
   // Handle the following exceptional case (*Obj).isa.
-  if (OpKind == tok::period &&
+  if (!IsArrow &&
       BaseType->isSpecificBuiltinType(BuiltinType::ObjCId) &&
       MemberName.getAsIdentifierInfo()->isStr("isa"))
     return Owned(new (Context) ObjCIsaExpr(BaseExpr, false, MemberLoc,
@@ -2472,74 +2657,105 @@
   return ExprError();
 }
 
-Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base,
+static Sema::OwningExprResult DiagnoseDtorReference(Sema &SemaRef,
+                                                    SourceLocation NameLoc,
+                                                    Sema::ExprArg MemExpr) {
+  Expr *E = (Expr *) MemExpr.get();
+  SourceLocation ExpectedLParenLoc = SemaRef.PP.getLocForEndOfToken(NameLoc);
+  SemaRef.Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
+    << isa<CXXPseudoDestructorExpr>(E)
+    << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
+  
+  return SemaRef.ActOnCallExpr(/*Scope*/ 0,
+                               move(MemExpr),
+                               /*LPLoc*/ ExpectedLParenLoc,
+                               Sema::MultiExprArg(SemaRef, 0, 0),
+                               /*CommaLocs*/ 0,
+                               /*RPLoc*/ ExpectedLParenLoc);
+}
+
+/// The main callback when the parser finds something like
+///   expression . [nested-name-specifier] identifier
+///   expression -> [nested-name-specifier] identifier
+/// where 'identifier' encompasses a fairly broad spectrum of
+/// possibilities, including destructor and operator references.
+///
+/// \param OpKind either tok::arrow or tok::period
+/// \param HasTrailingLParen whether the next token is '(', which
+///   is used to diagnose mis-uses of special members that can
+///   only be called
+/// \param ObjCImpDecl the current ObjC @implementation decl;
+///   this is an ugly hack around the fact that ObjC @implementations
+///   aren't properly put in the context chain
+Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
                                                    SourceLocation OpLoc,
                                                    tok::TokenKind OpKind,
                                                    const CXXScopeSpec &SS,
-                                                   UnqualifiedId &Member,
+                                                   UnqualifiedId &Id,
                                                    DeclPtrTy ObjCImpDecl,
                                                    bool HasTrailingLParen) {
-  if (Member.getKind() == UnqualifiedId::IK_TemplateId) {
-    TemplateName Template
-      = TemplateName::getFromVoidPointer(Member.TemplateId->Template);
-    
-    // FIXME: We're going to end up looking up the template based on its name,
-    // twice!
-    DeclarationName Name;
-    if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
-      Name = ActualTemplate->getDeclName();
-    else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl())
-      Name = Ovl->getDeclName();
-    else {
-      DependentTemplateName *DTN = Template.getAsDependentTemplateName();
-      if (DTN->isIdentifier())
-        Name = DTN->getIdentifier();
-      else
-        Name = Context.DeclarationNames.getCXXOperatorName(DTN->getOperator());
+  if (SS.isSet() && SS.isInvalid())
+    return ExprError();
+
+  TemplateArgumentListInfo TemplateArgsBuffer;
+
+  // Decompose the name into its component parts.
+  DeclarationName Name;
+  SourceLocation NameLoc;
+  const TemplateArgumentListInfo *TemplateArgs;
+  DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer,
+                         Name, NameLoc, TemplateArgs);
+
+  bool IsArrow = (OpKind == tok::arrow);
+
+  NamedDecl *FirstQualifierInScope
+    = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S,
+                       static_cast<NestedNameSpecifier*>(SS.getScopeRep())));
+
+  // This is a postfix expression, so get rid of ParenListExprs.
+  BaseArg = MaybeConvertParenListExprToParenExpr(S, move(BaseArg));
+
+  Expr *Base = BaseArg.takeAs<Expr>();
+  OwningExprResult Result(*this);
+  if (Base->getType()->isDependentType()) {
+    Result = ActOnDependentMemberExpr(ExprArg(*this, Base),
+                                      IsArrow, OpLoc,
+                                      SS, FirstQualifierInScope,
+                                      Name, NameLoc,
+                                      TemplateArgs);
+  } else {
+    LookupResult R(*this, Name, NameLoc, LookupMemberName);
+    if (TemplateArgs) {
+      // Re-use the lookup done for the template name.
+      DecomposeTemplateName(R, Id);
+    } else {
+      Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
+                                SS, FirstQualifierInScope,
+                                ObjCImpDecl);
+
+      if (Result.isInvalid()) {
+        Owned(Base);
+        return ExprError();
+      }
+
+      if (Result.get()) {
+        // The only way a reference to a destructor can be used is to
+        // immediately call it, which falls into this case.  If the
+        // next token is not a '(', produce a diagnostic and build the
+        // call now.
+        if (!HasTrailingLParen &&
+            Id.getKind() == UnqualifiedId::IK_DestructorName)
+          return DiagnoseDtorReference(*this, NameLoc, move(Result));
+
+        return move(Result);
+      }
     }
-    
-    // Translate the parser's template argument list in our AST format.
-    ASTTemplateArgsPtr TemplateArgsPtr(*this,
-                                       Member.TemplateId->getTemplateArgs(),
-                                       Member.TemplateId->NumArgs);
-    
-    TemplateArgumentListInfo TemplateArgs;
-    TemplateArgs.setLAngleLoc(Member.TemplateId->LAngleLoc);
-    TemplateArgs.setRAngleLoc(Member.TemplateId->RAngleLoc);
-    translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
-    TemplateArgsPtr.release();
-    
-    // Do we have the save the actual template name? We might need it...
-    return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, 
-                                    Member.TemplateId->TemplateNameLoc,
-                                    Name, &TemplateArgs, DeclPtrTy(),
-                                    &SS);
+
+    Result = BuildMemberReferenceExpr(ExprArg(*this, Base), OpLoc,
+                                      IsArrow, SS, R, TemplateArgs);
   }
-  
-  // FIXME: We lose a lot of source information by mapping directly to the
-  // DeclarationName.
-  OwningExprResult Result
-    = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
-                               Member.getSourceRange().getBegin(),
-                               GetNameFromUnqualifiedId(Member),
-                               ObjCImpDecl, &SS);
-  
-  if (Result.isInvalid() || HasTrailingLParen || 
-      Member.getKind() != UnqualifiedId::IK_DestructorName)
-    return move(Result);
-  
-  // The only way a reference to a destructor can be used is to
-  // immediately call them. Since the next token is not a '(', produce a
-  // diagnostic and build the call now.
-  Expr *E = (Expr *)Result.get();
-  SourceLocation ExpectedLParenLoc
-    = PP.getLocForEndOfToken(Member.getSourceRange().getEnd());
-  Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
-    << isa<CXXPseudoDestructorExpr>(E)
-    << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
-  
-  return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
-                       MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
+
+  return move(Result);
 }
 
 Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
@@ -2820,20 +3036,32 @@
       return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
                                                 CommaLocs, RParenLoc));
 
+    Expr *NakedFn = Fn->IgnoreParens();
+
+    // Determine whether this is a call to an unresolved member function.
+    if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
+      // If lookup was unresolved but not dependent (i.e. didn't find
+      // an unresolved using declaration), it has to be an overloaded
+      // function set, which means it must contain either multiple
+      // declarations (all methods or method templates) or a single
+      // method template.
+      assert((MemE->getNumDecls() > 1) ||
+             isa<FunctionTemplateDecl>(*MemE->decls_begin()));
+
+      return Owned(BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
+                                             CommaLocs, RParenLoc));
+    }
+
     // Determine whether this is a call to a member function.
-    if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens())) {
+    if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) {
       NamedDecl *MemDecl = MemExpr->getMemberDecl();
-      if (isa<OverloadedFunctionDecl>(MemDecl) ||
-          isa<CXXMethodDecl>(MemDecl) ||
-          (isa<FunctionTemplateDecl>(MemDecl) &&
-           isa<CXXMethodDecl>(
-                cast<FunctionTemplateDecl>(MemDecl)->getTemplatedDecl())))
+      if (isa<CXXMethodDecl>(MemDecl))
         return Owned(BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
                                                CommaLocs, RParenLoc));
     }
     
     // Determine whether this is a call to a pointer-to-member function.
-    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Fn->IgnoreParens())) {
+    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) {
       if (BO->getOpcode() == BinaryOperator::PtrMemD ||
           BO->getOpcode() == BinaryOperator::PtrMemI) {
         if (const FunctionProtoType *FPT = 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Nov 30 16:42:35 2009
@@ -2236,9 +2236,6 @@
 ///
 /// FIXME: Should Objective-C also use this approach?
 ///
-/// \param SS if non-NULL, the C++ nested-name-specifier that precedes the 
-/// name of the declaration referenced.
-///
 /// \param D the declaration being referenced from the current scope.
 ///
 /// \param NameLoc the location of the name in the source.
@@ -2247,16 +2244,11 @@
 /// access, will be set to the type of the "this" pointer to be used when
 /// building that implicit member access.
 ///
-/// \param MemberType if the reference to this declaration is an implicit
-/// member access, will be set to the type of the member being referenced
-/// (for use at the type of the resulting member access expression).
-///
 /// \returns true if this is an implicit member reference (in which case 
 /// \p ThisType and \p MemberType will be set), or false if it is not an
 /// implicit member reference.
-bool Sema::isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
-                                     SourceLocation NameLoc, QualType &ThisType,
-                                     QualType &MemberType) {
+bool Sema::isImplicitMemberReference(const LookupResult &R,
+                                     QualType &ThisType) {
   // If this isn't a C++ method, then it isn't an implicit member reference.
   CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
   if (!MD || MD->isStatic())
@@ -2269,33 +2261,21 @@
   //   class member access expression (5.2.5) using (*this) (9.3.2)
   //   as the postfix-expression to the left of the '.' operator.
   DeclContext *Ctx = 0;
-  if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+  if (R.isUnresolvableResult()) {
+    // FIXME: this is just picking one at random
+    Ctx = R.getRepresentativeDecl()->getDeclContext();
+  } else if (FieldDecl *FD = R.getAsSingle<FieldDecl>()) {
     Ctx = FD->getDeclContext();
-    MemberType = FD->getType();
-    
-    if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>())
-      MemberType = RefType->getPointeeType();
-    else if (!FD->isMutable())
-      MemberType
-        = Context.getQualifiedType(MemberType,
-                           Qualifiers::fromCVRMask(MD->getTypeQualifiers()));
-  } else if (isa<UnresolvedUsingValueDecl>(D)) {
-    Ctx = D->getDeclContext();
-    MemberType = Context.DependentTy;
   } else {
-    for (OverloadIterator Ovl(D), OvlEnd; Ovl != OvlEnd; ++Ovl) {
-      CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl);
+    for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+      CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*I);
       FunctionTemplateDecl *FunTmpl = 0;
-      if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)))
+      if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*I)))
         Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
       
       // FIXME: Do we have to know if there are explicit template arguments?
       if (Method && !Method->isStatic()) {
         Ctx = Method->getParent();
-        if (isa<CXXMethodDecl>(D) && !FunTmpl)
-          MemberType = Method->getType();
-        else
-          MemberType = Context.OverloadTy;
         break;
       }
     }
@@ -2307,6 +2287,8 @@
   // Determine whether the declaration(s) we found are actually in a base 
   // class. If not, this isn't an implicit member reference.
   ThisType = MD->getThisType(Context);
+
+  // FIXME: this doesn't really work for overloaded lookups.
   
   QualType CtxType = Context.getTypeDeclType(cast<CXXRecordDecl>(Ctx));
   QualType ClassType

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Nov 30 16:42:35 2009
@@ -4341,9 +4341,7 @@
 
   llvm::SmallVector<NamedDecl*,8> Fns;
   
-  // Try to dig out the overloaded function.
-  OverloadedFunctionDecl *Ovl = 0;
-  FunctionTemplateDecl *FunctionTemplate = 0;
+  // Look into the overloaded expression.
   if (UnresolvedLookupExpr *UL
                = dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
     Fns.append(UL->decls_begin(), UL->decls_end());
@@ -4351,17 +4349,15 @@
       HasExplicitTemplateArgs = true;
       UL->copyTemplateArgumentsInto(ExplicitTemplateArgs);
     }
-  } else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) {
-    Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());
-    FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());
-    HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList();
-    if (HasExplicitTemplateArgs)
+  } else if (UnresolvedMemberExpr *ME
+               = dyn_cast<UnresolvedMemberExpr>(OvlExpr)) {
+    Fns.append(ME->decls_begin(), ME->decls_end());
+    if (ME->hasExplicitTemplateArgs()) {
+      HasExplicitTemplateArgs = true;
       ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+    }
   }
 
-  if (Ovl) Fns.append(Ovl->function_begin(), Ovl->function_end());
-  if (FunctionTemplate) Fns.push_back(FunctionTemplate);
-
   // If we didn't actually find anything, we're done.
   if (Fns.empty())
     return 0;
@@ -5133,29 +5129,34 @@
                                 SourceLocation RParenLoc) {
   // Dig out the member expression. This holds both the object
   // argument and the member function we're referring to.
-  MemberExpr *MemExpr = 0;
-  if (ParenExpr *ParenE = dyn_cast<ParenExpr>(MemExprE))
-    MemExpr = dyn_cast<MemberExpr>(ParenE->getSubExpr());
-  else
-    MemExpr = dyn_cast<MemberExpr>(MemExprE);
-  assert(MemExpr && "Building member call without member expression");
-
+  Expr *NakedMemExpr = MemExprE->IgnoreParens();
+  
   // Extract the object argument.
-  Expr *ObjectArg = MemExpr->getBase();
+  Expr *ObjectArg;
 
+  MemberExpr *MemExpr;
   CXXMethodDecl *Method = 0;
-  if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
-      isa<FunctionTemplateDecl>(MemExpr->getMemberDecl())) {
+  if (isa<MemberExpr>(NakedMemExpr)) {
+    MemExpr = cast<MemberExpr>(NakedMemExpr);
+    ObjectArg = MemExpr->getBase();
+    Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+  } else {
+    UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
+    ObjectArg = UnresExpr->getBase();
+
     // Add overload candidates
     OverloadCandidateSet CandidateSet;
-    DeclarationName DeclName = MemExpr->getMemberDecl()->getDeclName();
 
-    for (OverloadIterator Func(MemExpr->getMemberDecl()), FuncEnd;
-         Func != FuncEnd; ++Func) {
-      if ((Method = dyn_cast<CXXMethodDecl>(*Func))) {
+    for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(),
+           E = UnresExpr->decls_end(); I != E; ++I) {
+
+      // TODO: note if we found something through a using declaration
+      NamedDecl *Func = (*I)->getUnderlyingDecl();
+      
+      if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
         // If explicit template arguments were provided, we can't call a
         // non-template member function.
-        if (MemExpr->hasExplicitTemplateArgumentList())
+        if (UnresExpr->hasExplicitTemplateArgs())
           continue;
         
         AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet,
@@ -5163,11 +5164,11 @@
       } else {
         // FIXME: avoid copy.
         TemplateArgumentListInfo TemplateArgs;
-        if (MemExpr->hasExplicitTemplateArgumentList())
-          MemExpr->copyTemplateArgumentsInto(TemplateArgs);
+        if (UnresExpr->hasExplicitTemplateArgs())
+          UnresExpr->copyTemplateArgumentsInto(TemplateArgs);
 
-        AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
-                                   (MemExpr->hasExplicitTemplateArgumentList()
+        AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
+                                   (UnresExpr->hasExplicitTemplateArgs()
                                       ? &TemplateArgs : 0),
                                    ObjectArg, Args, NumArgs,
                                    CandidateSet,
@@ -5175,14 +5176,16 @@
       }
     }
 
+    DeclarationName DeclName = UnresExpr->getMemberName();
+
     OverloadCandidateSet::iterator Best;
-    switch (BestViableFunction(CandidateSet, MemExpr->getLocStart(), Best)) {
+    switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
     case OR_Success:
       Method = cast<CXXMethodDecl>(Best->Function);
       break;
 
     case OR_No_Viable_Function:
-      Diag(MemExpr->getSourceRange().getBegin(),
+      Diag(UnresExpr->getMemberLoc(),
            diag::err_ovl_no_viable_member_function_in_call)
         << DeclName << MemExprE->getSourceRange();
       PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
@@ -5190,16 +5193,14 @@
       return true;
 
     case OR_Ambiguous:
-      Diag(MemExpr->getSourceRange().getBegin(),
-           diag::err_ovl_ambiguous_member_call)
+      Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
         << DeclName << MemExprE->getSourceRange();
       PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
       // FIXME: Leaking incoming expressions!
       return true;
 
     case OR_Deleted:
-      Diag(MemExpr->getSourceRange().getBegin(),
-           diag::err_ovl_deleted_member_call)
+      Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
         << Best->Function->isDeleted()
         << DeclName << MemExprE->getSourceRange();
       PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
@@ -5208,13 +5209,7 @@
     }
 
     MemExprE = FixOverloadedFunctionReference(MemExprE, Method);
-    if (ParenExpr *ParenE = dyn_cast<ParenExpr>(MemExprE))
-      MemExpr = dyn_cast<MemberExpr>(ParenE->getSubExpr());
-    else
-      MemExpr = dyn_cast<MemberExpr>(MemExprE);
-    
-  } else {
-    Method = dyn_cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+    MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
   }
 
   assert(Method && "Member call to something that isn't a method?");
@@ -5660,15 +5655,10 @@
                                Fn->getType());
   }
 
-  
-  if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {
-    assert((isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
-            isa<FunctionTemplateDecl>(MemExpr->getMemberDecl()) ||
-            isa<FunctionDecl>(MemExpr->getMemberDecl())) &&
-           "Expected member function or member function template");
+  if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
     // FIXME: avoid copy.
     TemplateArgumentListInfo TemplateArgs;
-    if (MemExpr->hasExplicitTemplateArgumentList())
+    if (MemExpr->hasExplicitTemplateArgs())
       MemExpr->copyTemplateArgumentsInto(TemplateArgs);
 
     return MemberExpr::Create(Context, MemExpr->getBase()->Retain(),
@@ -5677,7 +5667,7 @@
                               MemExpr->getQualifierRange(),
                               Fn, 
                               MemExpr->getMemberLoc(),
-                              (MemExpr->hasExplicitTemplateArgumentList()
+                              (MemExpr->hasExplicitTemplateArgs()
                                  ? &TemplateArgs : 0),
                               Fn->getType());
   }

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=90161&r1=90160&r2=90161&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Nov 30 16:42:35 2009
@@ -867,13 +867,10 @@
       = SemaRef.Context.DeclarationNames.getCXXDestructorName(
                                SemaRef.Context.getCanonicalType(DestroyedType));
 
-    return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base),
-                                              OperatorLoc,
-                                              isArrow? tok::arrow : tok::period,
-                                              DestroyedTypeLoc,
-                                              Name,
-                                              Sema::DeclPtrTy::make((Decl *)0),
-                                              &SS);
+    return getSema().BuildMemberReferenceExpr(move(Base), OperatorLoc, isArrow,
+                                              SS, /*FIXME: FirstQualifier*/ 0,
+                                              Name, DestroyedTypeLoc,
+                                              /*TemplateArgs*/ 0);
   }
 
   /// \brief Build a new unary operator expression.
@@ -967,14 +964,10 @@
       SS.setScopeRep(Qualifier);
     }
 
-    return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
-                                              isArrow? tok::arrow : tok::period,
-                                              MemberLoc,
-                                              Member->getDeclName(),
-                                              ExplicitTemplateArgs,
-                                     /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
-                                              &SS,
-                                              FirstQualifierInScope);
+    return getSema().BuildMemberReferenceExpr(move(Base), OpLoc, isArrow,
+                                              SS, FirstQualifierInScope,
+                                              Member->getDeclName(), MemberLoc,
+                                              ExplicitTemplateArgs);
   }
 
   /// \brief Build a new binary operator expression.
@@ -1049,10 +1042,13 @@
                                                SourceLocation OpLoc,
                                                SourceLocation AccessorLoc,
                                                IdentifierInfo &Accessor) {
-    return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
-                                              tok::period, AccessorLoc,
+    CXXScopeSpec SS;
+    return getSema().BuildMemberReferenceExpr(move(Base),
+                                              OpLoc, /*IsArrow*/ false,
+                                              SS, /*FirstQualifierInScope*/ 0,
                                               DeclarationName(&Accessor),
-                                     /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
+                                              AccessorLoc,
+                                              /* TemplateArgs */ 0);
   }
 
   /// \brief Build a new initializer list expression.
@@ -1530,67 +1526,38 @@
                                                   SourceLocation OperatorLoc,
                                               NestedNameSpecifier *Qualifier,
                                                   SourceRange QualifierRange,
+                                            NamedDecl *FirstQualifierInScope,
                                                   DeclarationName Name,
                                                   SourceLocation MemberLoc,
-                                             NamedDecl *FirstQualifierInScope) {
-    OwningExprResult Base = move(BaseE);
-    tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period;
-
+                              const TemplateArgumentListInfo *TemplateArgs) {
     CXXScopeSpec SS;
     SS.setRange(QualifierRange);
     SS.setScopeRep(Qualifier);
 
-    return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0,
-                                            move(Base), OperatorLoc, OpKind,
-                                            MemberLoc,
-                                            Name,
-                                    /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
-                                            &SS,
-                                            FirstQualifierInScope);
+    return SemaRef.BuildMemberReferenceExpr(move(BaseE), OperatorLoc, IsArrow,
+                                            SS, FirstQualifierInScope,
+                                            Name, MemberLoc, TemplateArgs);
   }
 
-  /// \brief Build a new member reference expression with explicit template
-  /// arguments.
+  /// \brief Build a new member reference expression.
   ///
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
-  OwningExprResult RebuildCXXDependentScopeMemberExpr(ExprArg BaseE,
-                                                  bool IsArrow,
-                                                  SourceLocation OperatorLoc,
-                                                NestedNameSpecifier *Qualifier,
-                                                  SourceRange QualifierRange,
-                                                  TemplateName Template,
-                                                SourceLocation TemplateNameLoc,
-                                              NamedDecl *FirstQualifierInScope,
-                                       const TemplateArgumentListInfo &TemplateArgs) {
+  OwningExprResult RebuildUnresolvedMemberExpr(ExprArg BaseE,
+                                               SourceLocation OperatorLoc,
+                                               bool IsArrow,
+                                               NestedNameSpecifier *Qualifier,
+                                               SourceRange QualifierRange,
+                                               LookupResult &R,
+                                const TemplateArgumentListInfo *TemplateArgs) {
     OwningExprResult Base = move(BaseE);
-    tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period;
 
     CXXScopeSpec SS;
     SS.setRange(QualifierRange);
     SS.setScopeRep(Qualifier);
 
-    // FIXME: We're going to end up looking up the template based on its name,
-    // twice! Also, duplicates part of Sema::BuildMemberAccessExpr.
-    DeclarationName Name;
-    if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
-      Name = ActualTemplate->getDeclName();
-    else if (OverloadedFunctionDecl *Ovl
-               = Template.getAsOverloadedFunctionDecl())
-      Name = Ovl->getDeclName();
-    else {
-      DependentTemplateName *DTN = Template.getAsDependentTemplateName();
-      if (DTN->isIdentifier())
-        Name = DTN->getIdentifier();
-      else
-        Name = SemaRef.Context.DeclarationNames.getCXXOperatorName(
-                                                          DTN->getOperator());
-    }
-    return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0, move(Base),
-                                            OperatorLoc, OpKind,
-                                            TemplateNameLoc, Name,
-                                            &TemplateArgs,
-                                            Sema::DeclPtrTy(), &SS);
+    return SemaRef.BuildMemberReferenceExpr(move(Base), OperatorLoc, IsArrow,
+                                            SS, R, TemplateArgs);
   }
 
   /// \brief Build a new Objective-C @encode expression.
@@ -4903,28 +4870,12 @@
                                                        E->getOperatorLoc(),
                                                        Qualifier,
                                                        E->getQualifierRange(),
+                                                       FirstQualifierInScope,
                                                        Name,
                                                        E->getMemberLoc(),
-                                                       FirstQualifierInScope);
+                                                       /*TemplateArgs*/ 0);
   }
 
-  // FIXME: This is an ugly hack, which forces the same template name to
-  // be looked up multiple times. Yuck!
-  TemporaryBase Rebase(*this, E->getMemberLoc(), DeclarationName());
-  TemplateName OrigTemplateName;
-  if (const IdentifierInfo *II = Name.getAsIdentifierInfo())
-    OrigTemplateName = SemaRef.Context.getDependentTemplateName(0, II);
-  else
-    OrigTemplateName 
-      = SemaRef.Context.getDependentTemplateName(0, 
-                                               Name.getCXXOverloadedOperator());
-
-  TemplateName Template
-    = getDerived().TransformTemplateName(OrigTemplateName,
-                                       QualType::getFromOpaquePtr(ObjectType));
-  if (Template.isNull())
-    return SemaRef.ExprError();
-
   TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
   for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
     TemplateArgumentLoc Loc;
@@ -4938,10 +4889,75 @@
                                                      E->getOperatorLoc(),
                                                      Qualifier,
                                                      E->getQualifierRange(),
-                                                     Template,
-                                                     E->getMemberLoc(),
                                                      FirstQualifierInScope,
-                                                     TransArgs);
+                                                     Name,
+                                                     E->getMemberLoc(),
+                                                     &TransArgs);
+}
+
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old,
+                                                      bool isAddressOfOperand) {
+  // Transform the base of the expression.
+  OwningExprResult Base = getDerived().TransformExpr(Old->getBase());
+  if (Base.isInvalid())
+    return SemaRef.ExprError();
+
+  NestedNameSpecifier *Qualifier = 0;
+  if (Old->getQualifier()) {
+    Qualifier
+      = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
+                                                  Old->getQualifierRange());
+    if (Qualifier == 0)
+      return SemaRef.ExprError();
+  }
+
+  LookupResult R(SemaRef, Old->getMemberName(), Old->getMemberLoc(),
+                 Sema::LookupOrdinaryName);
+
+  // Transform all the decls.
+  for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(),
+         E = Old->decls_end(); I != E; ++I) {
+    NamedDecl *InstD = static_cast<NamedDecl*>(getDerived().TransformDecl(*I));
+    if (!InstD)
+      return SemaRef.ExprError();
+
+    // Expand using declarations.
+    if (isa<UsingDecl>(InstD)) {
+      UsingDecl *UD = cast<UsingDecl>(InstD);
+      for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+             E = UD->shadow_end(); I != E; ++I)
+        R.addDecl(*I);
+      continue;
+    }
+
+    R.addDecl(InstD);
+  }
+
+  R.resolveKind();
+
+  TemplateArgumentListInfo TransArgs;
+  if (Old->hasExplicitTemplateArgs()) {
+    TransArgs.setLAngleLoc(Old->getLAngleLoc());
+    TransArgs.setRAngleLoc(Old->getRAngleLoc());
+    for (unsigned I = 0, N = Old->getNumTemplateArgs(); I != N; ++I) {
+      TemplateArgumentLoc Loc;
+      if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I],
+                                                 Loc))
+        return SemaRef.ExprError();
+      TransArgs.addArgument(Loc);
+    }
+  }
+  
+  return getDerived().RebuildUnresolvedMemberExpr(move(Base),
+                                                  Old->getOperatorLoc(),
+                                                  Old->isArrow(),
+                                                  Qualifier,
+                                                  Old->getQualifierRange(),
+                                                  R,
+                                              (Old->hasExplicitTemplateArgs()
+                                                  ? &TransArgs : 0));
 }
 
 template<typename Derived>

Modified: cfe/trunk/test/SemaCXX/qual-id-test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/qual-id-test.cpp?rev=90161&r1=90160&r2=90161&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/qual-id-test.cpp (original)
+++ cfe/trunk/test/SemaCXX/qual-id-test.cpp Mon Nov 30 16:42:35 2009
@@ -48,7 +48,7 @@
         a.A::sub::x();
         a.A::B::base::x();
 
-        a.bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''struct A::sub''}}
+        a.bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''A::sub''}}
 
         a->foo();
         a->member::foo();
@@ -69,7 +69,7 @@
         a->A::sub::x();
         a->A::B::base::x();
 
-        a->bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''struct A::sub''}}
+        a->bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''A::sub''}}
 
         (*a)->foo();
         (*a)->member::foo();

Modified: cfe/trunk/test/SemaTemplate/instantiate-method.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-method.cpp?rev=90161&r1=90160&r2=90161&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-method.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-method.cpp Mon Nov 30 16:42:35 2009
@@ -95,7 +95,9 @@
 template<typename U>
 struct X1 : X0<U> {
   int &f2() { 
-    return X0Base::f(); // expected-error{{call to non-static member function without an object argument}}
+    // FIXME: We should be able to do this lookup and diagnose the error
+    // *despite* the fact that we can't decide the relationship yet.
+    return X0Base::f(); // expected-FIXME-error{{call to non-static member function without an object argument}}
   }
 };
 





More information about the cfe-commits mailing list