Rip out TemplateIdRefExpr and make UnresolvedLookupExpr and            
DependentScopeDeclRefExpr support storing templateids.  Unite the common   
code paths between ActOnDeclarationNameExpr and ActOnTemplateIdExpr.

This gets us to a point where we don't need to store function templates in
the AST using TemplateNames, which is critical to ripping out OverloadedFunction.

Also resolves a few FIXMEs.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89785 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 4823c0b..63b153a 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1052,26 +1052,48 @@
   /// trivially rederivable if we urgently need to kill this field.
   bool Overloaded;
 
-  UnresolvedLookupExpr(QualType T,
+  /// True if the name looked up had explicit template arguments.
+  /// This requires all the results to be function templates.  
+  bool HasExplicitTemplateArgs;
+
+  UnresolvedLookupExpr(QualType T, bool Dependent,
                        NestedNameSpecifier *Qualifier, SourceRange QRange,
                        DeclarationName Name, SourceLocation NameLoc,
-                       bool RequiresADL, bool Overloaded)
-    : Expr(UnresolvedLookupExprClass, T, false, false),
+                       bool RequiresADL, bool Overloaded, bool HasTemplateArgs)
+    : Expr(UnresolvedLookupExprClass, T, Dependent, Dependent),
       Name(Name), Qualifier(Qualifier), QualifierRange(QRange),
-      NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded)
+      NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded),
+      HasExplicitTemplateArgs(HasTemplateArgs)
   {}
 
 public:
   static UnresolvedLookupExpr *Create(ASTContext &C,
+                                      bool Dependent,
                                       NestedNameSpecifier *Qualifier,
                                       SourceRange QualifierRange,
                                       DeclarationName Name,
                                       SourceLocation NameLoc,
                                       bool ADL, bool Overloaded) {
-    return new(C) UnresolvedLookupExpr(C.OverloadTy, Qualifier, QualifierRange,
-                                       Name, NameLoc, ADL, Overloaded);
+    return new(C) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy,
+                                       Dependent, Qualifier, QualifierRange,
+                                       Name, NameLoc, ADL, Overloaded, false);
   }
 
+  static UnresolvedLookupExpr *Create(ASTContext &C,
+                                      bool Dependent,
+                                      NestedNameSpecifier *Qualifier,
+                                      SourceRange QualifierRange,
+                                      DeclarationName Name,
+                                      SourceLocation NameLoc,
+                                      bool ADL,
+                                      const TemplateArgumentListInfo &Args);
+
+  /// Computes whether an unresolved lookup on the given declarations
+  /// and optional template arguments is type- and value-dependent.
+  static bool ComputeDependence(NamedDecl * const *Begin,
+                                NamedDecl * const *End,
+                                const TemplateArgumentListInfo *Args);
+
   void addDecl(NamedDecl *Decl) {
     Results.addDecl(Decl);
   }
@@ -1098,11 +1120,47 @@
 
   /// Fetches the range of the nested-name qualifier.
   SourceRange getQualifierRange() const { return QualifierRange; }
+
+  /// Determines whether this lookup had explicit template arguments.
+  bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
+
+  // Note that, inconsistently with the explicit-template-argument AST
+  // nodes, users are *forbidden* from calling these methods on objects
+  // without explicit template arguments.
+
+  /// Gets a reference to the explicit template argument list.
+  const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+    assert(hasExplicitTemplateArgs());
+    return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
+  }
+
+  /// \brief Copies the template arguments (if present) into the given
+  /// structure.
+  void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+    getExplicitTemplateArgs().copyInto(List);
+  }
   
+  SourceLocation getLAngleLoc() const {
+    return getExplicitTemplateArgs().LAngleLoc;
+  }
+
+  SourceLocation getRAngleLoc() const {
+    return getExplicitTemplateArgs().RAngleLoc;
+  }
+
+  TemplateArgumentLoc const *getTemplateArgs() const {
+    return getExplicitTemplateArgs().getTemplateArgs();
+  }
+
+  unsigned getNumTemplateArgs() const {
+    return getExplicitTemplateArgs().NumTemplateArgs;
+  }
 
   virtual SourceRange getSourceRange() const {
-    if (Qualifier) return SourceRange(QualifierRange.getBegin(), NameLoc);
-    return SourceRange(NameLoc, NameLoc);
+    SourceRange Range(NameLoc);
+    if (Qualifier) Range.setBegin(QualifierRange.getBegin());
+    if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
+    return Range;
   }
 
   virtual StmtIterator child_begin();
@@ -1141,19 +1199,30 @@
 
   /// \brief The nested-name-specifier that qualifies this unresolved
   /// declaration name.
-  NestedNameSpecifier *NNS;
+  NestedNameSpecifier *Qualifier;
 
-  /// \brief Whether this expr is an address of (&) operand.
-  /// FIXME: Stash this bit into NNS!
-  bool IsAddressOfOperand;
+  /// \brief Whether the name includes explicit template arguments.
+  bool HasExplicitTemplateArgs;
+
+  DependentScopeDeclRefExpr(QualType T,
+                            NestedNameSpecifier *Qualifier,
+                            SourceRange QualifierRange,
+                            DeclarationName Name,
+                            SourceLocation NameLoc,
+                            bool HasExplicitTemplateArgs)
+    : Expr(DependentScopeDeclRefExprClass, T, true, true),
+      Name(Name), Loc(NameLoc),
+      QualifierRange(QualifierRange), Qualifier(Qualifier),
+      HasExplicitTemplateArgs(HasExplicitTemplateArgs)
+  {}
 
 public:
-  DependentScopeDeclRefExpr(DeclarationName N, QualType T, SourceLocation L,
-                            SourceRange R, NestedNameSpecifier *NNS,
-                            bool IsAddressOfOperand)
-    : Expr(DependentScopeDeclRefExprClass, T, true, true),
-      Name(N), Loc(L), QualifierRange(R), NNS(NNS),
-      IsAddressOfOperand(IsAddressOfOperand) { }
+  static DependentScopeDeclRefExpr *Create(ASTContext &C,
+                                           NestedNameSpecifier *Qualifier,
+                                           SourceRange QualifierRange,
+                                           DeclarationName Name,
+                                           SourceLocation NameLoc,
+                              const TemplateArgumentListInfo *TemplateArgs = 0);
 
   /// \brief Retrieve the name that this expression refers to.
   DeclarationName getDeclName() const { return Name; }
@@ -1166,13 +1235,48 @@
 
   /// \brief Retrieve the nested-name-specifier that qualifies this
   /// declaration.
-  NestedNameSpecifier *getQualifier() const { return NNS; }
+  NestedNameSpecifier *getQualifier() const { return Qualifier; }
 
-  /// \brief Retrieve whether this is an address of (&) operand.
+  /// Determines whether this lookup had explicit template arguments.
+  bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
 
-  bool isAddressOfOperand() const { return IsAddressOfOperand; }
+  // Note that, inconsistently with the explicit-template-argument AST
+  // nodes, users are *forbidden* from calling these methods on objects
+  // without explicit template arguments.
+
+  /// Gets a reference to the explicit template argument list.
+  const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+    assert(hasExplicitTemplateArgs());
+    return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
+  }
+
+  /// \brief Copies the template arguments (if present) into the given
+  /// structure.
+  void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+    getExplicitTemplateArgs().copyInto(List);
+  }
+  
+  SourceLocation getLAngleLoc() const {
+    return getExplicitTemplateArgs().LAngleLoc;
+  }
+
+  SourceLocation getRAngleLoc() const {
+    return getExplicitTemplateArgs().RAngleLoc;
+  }
+
+  TemplateArgumentLoc const *getTemplateArgs() const {
+    return getExplicitTemplateArgs().getTemplateArgs();
+  }
+
+  unsigned getNumTemplateArgs() const {
+    return getExplicitTemplateArgs().NumTemplateArgs;
+  }
+
   virtual SourceRange getSourceRange() const {
-    return SourceRange(QualifierRange.getBegin(), getLocation());
+    SourceRange Range(QualifierRange.getBegin(), getLocation());
+    if (hasExplicitTemplateArgs())
+      Range.setEnd(getRAngleLoc());
+    return Range;
   }
 
   static bool classof(const Stmt *T) {
@@ -1184,105 +1288,6 @@
   virtual StmtIterator child_end();
 };
 
-/// \brief An expression that refers to a C++ template-id, such as
-/// @c isa<FunctionDecl>.
-class TemplateIdRefExpr : public Expr {
-  /// \brief If this template-id was qualified-id, e.g., @c std::sort<int>,
-  /// this nested name specifier contains the @c std::.
-  NestedNameSpecifier *Qualifier;
-
-  /// \brief If this template-id was a qualified-id, e.g., @c std::sort<int>,
-  /// this covers the source code range of the @c std::.
-  SourceRange QualifierRange;
-
-  /// \brief The actual template to which this template-id refers.
-  TemplateName Template;
-
-  /// \brief The source location of the template name.
-  SourceLocation TemplateNameLoc;
-
-  /// \brief The source location of the left angle bracket ('<');
-  SourceLocation LAngleLoc;
-
-  /// \brief The source location of the right angle bracket ('>');
-  SourceLocation RAngleLoc;
-
-  /// \brief The number of template arguments in TemplateArgs.
-  unsigned NumTemplateArgs;
-
-  TemplateIdRefExpr(QualType T,
-                    NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
-                    TemplateName Template, SourceLocation TemplateNameLoc,
-                    const TemplateArgumentListInfo &TemplateArgs);
-
-  virtual void DoDestroy(ASTContext &Context);
-
-public:
-  static TemplateIdRefExpr *
-  Create(ASTContext &Context, QualType T,
-         NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
-         TemplateName Template, SourceLocation TemplateNameLoc,
-         const TemplateArgumentListInfo &TemplateArgs);
-
-  /// \brief Retrieve the nested name specifier used to qualify the name of
-  /// this template-id, e.g., the "std::sort" in @c std::sort<int>, or NULL
-  /// if this template-id was an unqualified-id.
-  NestedNameSpecifier *getQualifier() const { return Qualifier; }
-
-  /// \brief Retrieve the source range describing the nested name specifier
-  /// used to qualified the name of this template-id, if the name was qualified.
-  SourceRange getQualifierRange() const { return QualifierRange; }
-
-  /// \brief Retrieve the name of the template referenced, e.g., "sort" in
-  /// @c std::sort<int>;
-  TemplateName getTemplateName() const { return Template; }
-
-  /// \brief Retrieve the location of the name of the template referenced, e.g.,
-  /// the location of "sort" in @c std::sort<int>.
-  SourceLocation getTemplateNameLoc() const { return TemplateNameLoc; }
-
-  /// \brief Retrieve the location of the left angle bracket following the
-  /// template name ('<').
-  SourceLocation getLAngleLoc() const { return LAngleLoc; }
-
-  /// \brief Retrieve the template arguments provided as part of this
-  /// template-id.
-  const TemplateArgumentLoc *getTemplateArgs() const {
-    return reinterpret_cast<const TemplateArgumentLoc *>(this + 1);
-  }
-
-  /// \brief Retrieve the number of template arguments provided as part of this
-  /// template-id.
-  unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
-
-  /// \brief Copies the template-argument information into the given
-  /// structure.
-  void copyTemplateArgumentsInto(TemplateArgumentListInfo &Info) const {
-    Info.setLAngleLoc(LAngleLoc);
-    Info.setRAngleLoc(RAngleLoc);
-    for (unsigned i = 0; i < NumTemplateArgs; ++i)
-      Info.addArgument(getTemplateArgs()[i]);
-  }
-
-  /// \brief Retrieve the location of the right angle bracket following the
-  /// template arguments ('>').
-  SourceLocation getRAngleLoc() const { return RAngleLoc; }
-
-  virtual SourceRange getSourceRange() const {
-    return SourceRange(Qualifier? QualifierRange.getBegin() : TemplateNameLoc,
-                       RAngleLoc);
-  }
-
-  // Iterators
-  virtual child_iterator child_begin();
-  virtual child_iterator child_end();
-
-  static bool classof(const Stmt *T) {
-    return T->getStmtClass() == TemplateIdRefExprClass;
-  }
-  static bool classof(const TemplateIdRefExpr *) { return true; }
-};
-
 class CXXExprWithTemporaries : public Expr {
   Stmt *SubExpr;
 
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index 31fbae1..dd8a685 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -128,7 +128,6 @@
 EXPR(UnresolvedLookupExpr   , Expr)
 EXPR(UnaryTypeTraitExpr     , Expr)
 EXPR(DependentScopeDeclRefExpr  , Expr)
-EXPR(TemplateIdRefExpr      , Expr)
 EXPR(CXXConstructExpr       , Expr)
 EXPR(CXXBindTemporaryExpr   , Expr)
 EXPR(CXXExprWithTemporaries , Expr)
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 4032285..c3b5045 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1214,6 +1214,10 @@
     "%0 following the 'template' keyword does not refer to a template">;
 def err_template_kw_refers_to_function_template : Error<
     "%0 following the 'template' keyword refers to a function template">;
+def err_template_kw_refers_to_class_template : Error<
+    "'%0%1' instantiated to a class template, not a function template">;
+def note_referenced_class_template : Error<
+    "class template declared here">;
 
 // C++0x Variadic Templates
 def err_template_param_pack_default_arg : Error<
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 34790d2..9f08271 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1178,18 +1178,6 @@
     return LV_Valid;
   }
 
-  case TemplateIdRefExprClass: {
-    const TemplateIdRefExpr *TID = cast<TemplateIdRefExpr>(this);
-    TemplateName Template = TID->getTemplateName();
-    NamedDecl *ND = Template.getAsTemplateDecl();
-    if (!ND)
-      ND = Template.getAsOverloadedFunctionDecl();
-    if (ND && DeclCanBeLvalue(ND, Ctx))
-      return LV_Valid;
-    
-    break;
-  } 
-    
   default:
     break;
   }
@@ -1534,7 +1522,6 @@
   case Expr::CXXPseudoDestructorExprClass:
   case Expr::UnresolvedLookupExprClass:
   case Expr::DependentScopeDeclRefExprClass:
-  case Expr::TemplateIdRefExprClass:
   case Expr::CXXConstructExprClass:
   case Expr::CXXBindTemporaryExprClass:
   case Expr::CXXExprWithTemporariesClass:
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 3f49dc6..8591a4d 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -122,6 +122,40 @@
 }
 
 // UnresolvedLookupExpr
+UnresolvedLookupExpr *
+UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
+                             NestedNameSpecifier *Qualifier,
+                             SourceRange QualifierRange, DeclarationName Name,
+                             SourceLocation NameLoc, bool ADL,
+                             const TemplateArgumentListInfo &Args) 
+{
+  void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + 
+                         ExplicitTemplateArgumentList::sizeFor(Args));
+  UnresolvedLookupExpr *ULE
+    = new (Mem) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy,
+                                     Dependent, Qualifier, QualifierRange,
+                                     Name, NameLoc, ADL,
+                                     /*Overload*/ true,
+                                     /*ExplicitTemplateArgs*/ true);
+
+  reinterpret_cast<ExplicitTemplateArgumentList*>(ULE+1)->initializeFrom(Args);
+
+  return ULE;
+}
+
+bool UnresolvedLookupExpr::ComputeDependence(NamedDecl * const *Begin,
+                                             NamedDecl * const *End,
+                                       const TemplateArgumentListInfo *Args) {
+  for (NamedDecl * const *I = Begin; I != End; ++I)
+    if ((*I)->getDeclContext()->isDependentContext())
+      return true;
+
+  if (Args && TemplateSpecializationType::anyDependentTemplateArguments(*Args))
+    return true;
+
+  return false;
+}
+
 Stmt::child_iterator UnresolvedLookupExpr::child_begin() {
   return child_iterator();
 }
@@ -137,6 +171,30 @@
 }
 
 // DependentScopeDeclRefExpr
+DependentScopeDeclRefExpr *
+DependentScopeDeclRefExpr::Create(ASTContext &C,
+                                  NestedNameSpecifier *Qualifier,
+                                  SourceRange QualifierRange,
+                                  DeclarationName Name,
+                                  SourceLocation NameLoc,
+                                  const TemplateArgumentListInfo *Args) {
+  std::size_t size = sizeof(DependentScopeDeclRefExpr);
+  if (Args) size += ExplicitTemplateArgumentList::sizeFor(*Args);
+  void *Mem = C.Allocate(size);
+
+  DependentScopeDeclRefExpr *DRE
+    = new (Mem) DependentScopeDeclRefExpr(C.DependentTy,
+                                          Qualifier, QualifierRange,
+                                          Name, NameLoc,
+                                          Args != 0);
+
+  if (Args)
+    reinterpret_cast<ExplicitTemplateArgumentList*>(DRE+1)
+      ->initializeFrom(*Args);
+
+  return DRE;
+}
+
 StmtIterator DependentScopeDeclRefExpr::child_begin() {
   return child_iterator();
 }
@@ -145,61 +203,6 @@
   return child_iterator();
 }
 
-TemplateIdRefExpr::TemplateIdRefExpr(QualType T,
-                                     NestedNameSpecifier *Qualifier,
-                                     SourceRange QualifierRange,
-                                     TemplateName Template,
-                                     SourceLocation TemplateNameLoc,
-                                const TemplateArgumentListInfo &TemplateArgs)
-  : Expr(TemplateIdRefExprClass, T,
-         (Template.isDependent() ||
-          TemplateSpecializationType
-             ::anyDependentTemplateArguments(TemplateArgs)),
-         (Template.isDependent() ||
-          TemplateSpecializationType
-             ::anyDependentTemplateArguments(TemplateArgs))),
-    Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template),
-    TemplateNameLoc(TemplateNameLoc),
-    LAngleLoc(TemplateArgs.getLAngleLoc()),
-    RAngleLoc(TemplateArgs.getRAngleLoc()),
-    NumTemplateArgs(TemplateArgs.size()) {
-  TemplateArgumentLoc *StoredTemplateArgs
-    = reinterpret_cast<TemplateArgumentLoc *> (this+1);
-  for (unsigned I = 0; I != NumTemplateArgs; ++I)
-    new (StoredTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]);
-}
-
-TemplateIdRefExpr *
-TemplateIdRefExpr::Create(ASTContext &Context, QualType T,
-                          NestedNameSpecifier *Qualifier,
-                          SourceRange QualifierRange,
-                          TemplateName Template, SourceLocation TemplateNameLoc,
-                          const TemplateArgumentListInfo &TemplateArgs) {
-  void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) +
-                          sizeof(TemplateArgumentLoc) * TemplateArgs.size());
-  return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template,
-                                     TemplateNameLoc, TemplateArgs);
-}
-
-void TemplateIdRefExpr::DoDestroy(ASTContext &Context) {
-  const TemplateArgumentLoc *TemplateArgs = getTemplateArgs();
-  for (unsigned I = 0; I != NumTemplateArgs; ++I)
-    if (Expr *E = TemplateArgs[I].getArgument().getAsExpr())
-      E->Destroy(Context);
-  this->~TemplateIdRefExpr();
-  Context.Deallocate(this);
-}
-
-Stmt::child_iterator TemplateIdRefExpr::child_begin() {
-  // FIXME: Walk the expressions in the template arguments (?)
-  return Stmt::child_iterator();
-}
-
-Stmt::child_iterator TemplateIdRefExpr::child_end() {
-  // FIXME: Walk the expressions in the template arguments (?)
-  return Stmt::child_iterator();
-}
-
 bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
   switch(UTT) {
   default: assert(false && "Unknown type trait or not implemented");
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 34ca798..a7cfed9 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -487,20 +487,22 @@
                                            DependentScopeDeclRefExpr *Node) {
   Node->getQualifier()->print(OS, Policy);
   OS << Node->getDeclName().getAsString();
+  if (Node->hasExplicitTemplateArgs())
+    OS << TemplateSpecializationType::PrintTemplateArgumentList(
+                                                   Node->getTemplateArgs(),
+                                                   Node->getNumTemplateArgs(),
+                                                   Policy);
 }
 
 void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
-  OS << Node->getName().getAsString();
-}
-
-void StmtPrinter::VisitTemplateIdRefExpr(TemplateIdRefExpr *Node) {
   if (Node->getQualifier())
     Node->getQualifier()->print(OS, Policy);
-  Node->getTemplateName().print(OS, Policy, true);
-  OS << TemplateSpecializationType::PrintTemplateArgumentList(
-                                                      Node->getTemplateArgs(),
+  OS << Node->getName().getAsString();
+  if (Node->hasExplicitTemplateArgs())
+    OS << TemplateSpecializationType::PrintTemplateArgumentList(
+                                                   Node->getTemplateArgs(),
                                                    Node->getNumTemplateArgs(),
-                                                              Policy);
+                                                   Policy);
 }
 
 void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index f238451..2699cdf 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -517,7 +517,11 @@
 void
 StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) {
   VisitExpr(S);
+  VisitNestedNameSpecifier(S->getQualifier());
   VisitName(S->getName());
+  ID.AddBoolean(S->hasExplicitTemplateArgs());
+  if (S->hasExplicitTemplateArgs())
+    VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
 }
 
 void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
@@ -531,14 +535,9 @@
   VisitExpr(S);
   VisitName(S->getDeclName());
   VisitNestedNameSpecifier(S->getQualifier());
-  ID.AddBoolean(S->isAddressOfOperand());
-}
-
-void StmtProfiler::VisitTemplateIdRefExpr(TemplateIdRefExpr *S) {
-  VisitExpr(S);
-  VisitNestedNameSpecifier(S->getQualifier());
-  VisitTemplateName(S->getTemplateName());
-  VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+  ID.AddBoolean(S->hasExplicitTemplateArgs());
+  if (S->hasExplicitTemplateArgs())
+    VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
 }
 
 void StmtProfiler::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *S) {
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index b305906..c7b574f 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -379,14 +379,14 @@
   class Filter {
     LookupResult &Results;
     unsigned I;
-    bool ErasedAny;
+    bool Changed;
 #ifndef NDEBUG
     bool CalledDone;
 #endif
     
     friend class LookupResult;
     Filter(LookupResult &Results)
-      : Results(Results), I(0), ErasedAny(false)
+      : Results(Results), I(0), Changed(false)
 #ifndef NDEBUG
       , CalledDone(false)
 #endif
@@ -413,7 +413,12 @@
     void erase() {
       Results.Decls[--I] = Results.Decls.back();
       Results.Decls.pop_back();
-      ErasedAny = true;
+      Changed = true;
+    }
+
+    void replace(NamedDecl *D) {
+      Results.Decls[I-1] = D;
+      Changed = true;
     }
 
     void done() {
@@ -422,7 +427,7 @@
       CalledDone = true;
 #endif
 
-      if (ErasedAny)
+      if (Changed)
         Results.resolveKindAfterFilter();
     }
   };
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 3b3b41b..beaccda 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1389,6 +1389,16 @@
                                              UnqualifiedId &Name,
                                              bool HasTrailingLParen,
                                              bool IsAddressOfOperand);
+
+  OwningExprResult LookupInObjCMethod(LookupResult &R,
+                                      Scope *S,
+                                      IdentifierInfo *II);
+
+  OwningExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
+                                              DeclarationName Name,
+                                              SourceLocation NameLoc,
+                                              bool CheckForImplicitMember,
+                                const TemplateArgumentListInfo *TemplateArgs);
   
   OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty,
                                     SourceLocation Loc,
@@ -1400,26 +1410,25 @@
                                            FieldDecl *Field,
                                            Expr *BaseObjectExpr = 0,
                                       SourceLocation OpLoc = SourceLocation());
-  OwningExprResult ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
-                                            DeclarationName Name,
-                                            bool HasTrailingLParen,
-                                            const CXXScopeSpec *SS,
-                                            bool isAddressOfOperand = false);
-  OwningExprResult BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS,
-                                                    LookupResult &R);
-  bool UseArgumentDependentLookup(const CXXScopeSpec *SS,
+  OwningExprResult BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS,
+                                                    LookupResult &R,
+                                const TemplateArgumentListInfo *TemplateArgs);
+  bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
                                   const LookupResult &R,
                                   bool HasTrailingLParen);
-  OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS,
-                                            LookupResult &R, bool ADL);
-  OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS,
-                                            SourceLocation Loc,
-                                            DeclarationName Name,
-                                            bool NeedsADL,
-                                            bool IsOverloaded,
-                                            NamedDecl * const *Decls,
-                                            unsigned NumDecls);
-  OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+
+  OwningExprResult BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
+                                                     DeclarationName Name,
+                                                     SourceLocation NameLoc);
+  OwningExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+                                             DeclarationName Name,
+                                             SourceLocation NameLoc,
+                                const TemplateArgumentListInfo *TemplateArgs);
+
+  OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                                            LookupResult &R,
+                                            bool ADL);
+  OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
                                             SourceLocation Loc,
                                             NamedDecl *D);
 
@@ -2110,7 +2119,7 @@
                                  FunctionDecl::StorageClass& SC);
   DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
 
-  bool isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D,
+  bool isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
                                  SourceLocation NameLoc, QualType &ThisType,
                                  QualType &MemberType);
   
@@ -2207,6 +2216,9 @@
   //===--------------------------------------------------------------------===//
   // C++ Templates [C++ 14]
   //
+  void LookupTemplateName(LookupResult &R, Scope *S, const CXXScopeSpec &SS,
+                          QualType ObjectType, bool EnteringContext);
+
   virtual TemplateNameKind isTemplateName(Scope *S,
                                           const CXXScopeSpec &SS,
                                           UnqualifiedId &Name,
@@ -2286,18 +2298,14 @@
                                             DeclSpec::TST TagSpec,
                                             SourceLocation TagLoc);
 
-  OwningExprResult BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
-                                       SourceRange QualifierRange,
-                                       TemplateName Template,
-                                       SourceLocation TemplateNameLoc,
+  OwningExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                       LookupResult &R,
+                                       bool RequiresADL,
                                const TemplateArgumentListInfo &TemplateArgs);
-
-  OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
-                                       TemplateTy Template,
-                                       SourceLocation TemplateNameLoc,
-                                       SourceLocation LAngleLoc,
-                                       ASTTemplateArgsPtr TemplateArgs,
-                                       SourceLocation RAngleLoc);
+  OwningExprResult BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS,
+                                                DeclarationName Name,
+                                                SourceLocation NameLoc,
+                               const TemplateArgumentListInfo &TemplateArgs);
 
   virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
                                                 const CXXScopeSpec &SS,
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index a555a64..b494724 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1967,8 +1967,10 @@
   if (!CDecl && FName->isStr("super")) {
     // "super" may be the name of a variable, in which case we are
     // probably calling an instance method.
-    OwningExprResult Super = ActOnDeclarationNameExpr(S, FNameLoc, FName,
-                                                      false, 0, false);
+    CXXScopeSpec SS;
+    UnqualifiedId id;
+    id.setIdentifier(FName, FNameLoc);
+    OwningExprResult Super = ActOnIdExpression(S, SS, id, false, false);
     return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
                                            SelIdents, NumSelIdents);
   }
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 3fa7d9c..2405d52 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -177,9 +177,10 @@
 
   // Special case where the argument is a template id.
   if (Attr.getParameterName()) {
-    sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(),
-                               Attr.getParameterName(),
-                               false, 0, false).takeAs<Expr>();
+    CXXScopeSpec SS;
+    UnqualifiedId id;
+    id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+    sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>();
   } else {
     // check the attribute arguments.
     if (Attr.getNumArgs() != 1) {
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9d7a421..50fd5ec 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -617,202 +617,140 @@
   return Owned(Result);
 }
 
-Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
-                                               const CXXScopeSpec &SS,
-                                               UnqualifiedId &Name,
-                                               bool HasTrailingLParen,
-                                               bool IsAddressOfOperand) {
-  assert(!(IsAddressOfOperand && HasTrailingLParen) &&
-         "cannot be direct & operand and have a trailing lparen");
+static void DecomposeTemplateName(LookupResult &R, TemplateName TName) {
+  if (TemplateDecl *TD = TName.getAsTemplateDecl())
+    R.addDecl(TD);
+  else if (OverloadedFunctionDecl *OD
+             = TName.getAsOverloadedFunctionDecl())
+    for (OverloadIterator I(OD), E; I != E; ++I)
+      R.addDecl(*I);
 
-  if (Name.getKind() == UnqualifiedId::IK_TemplateId) {
-    ASTTemplateArgsPtr TemplateArgsPtr(*this,
-                                       Name.TemplateId->getTemplateArgs(),
-                                       Name.TemplateId->NumArgs);
-    return ActOnTemplateIdExpr(SS, 
-                               TemplateTy::make(Name.TemplateId->Template), 
-                               Name.TemplateId->TemplateNameLoc,
-                               Name.TemplateId->LAngleLoc,
-                               TemplateArgsPtr,
-                               Name.TemplateId->RAngleLoc);
-  }
-  
-  // FIXME: We lose a bunch of source information by doing this. Later,
-  // we'll want to merge ActOnDeclarationNameExpr's logic into 
-  // ActOnIdExpression.
-  return ActOnDeclarationNameExpr(S, 
-                                  Name.StartLocation,
-                                  GetNameFromUnqualifiedId(Name),
-                                  HasTrailingLParen,
-                                  &SS,
-                                  IsAddressOfOperand);
+  R.resolveKind();
 }
 
-/// ActOnDeclarationNameExpr - The parser has read some kind of name
-/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine
-/// performs lookup on that name and returns an expression that refers
-/// to that name. This routine isn't directly called from the parser,
-/// because the parser doesn't know about DeclarationName. Rather,
-/// this routine is called by ActOnIdExpression, which contains a
-/// parsed UnqualifiedId.
-///
-/// HasTrailingLParen indicates whether this identifier is used in a
-/// function call context.  LookupCtx is only used for a C++
-/// qualified-id (foo::bar) to indicate the class or namespace that
-/// the identifier must be a member of.
-///
-/// isAddressOfOperand means that this expression is the direct operand
-/// of an address-of operator. This matters because this is the only
-/// situation where a qualified name referencing a non-static member may
-/// appear outside a member function of this class.
-Sema::OwningExprResult
-Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
-                               DeclarationName Name, bool HasTrailingLParen,
-                               const CXXScopeSpec *SS,
-                               bool isAddressOfOperand) {
-  // Could be enum-constant, value decl, instance variable, etc.
-  if (SS && SS->isInvalid())
+Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
+                                               const CXXScopeSpec &SS,
+                                               UnqualifiedId &Id,
+                                               bool HasTrailingLParen,
+                                               bool isAddressOfOperand) {
+  assert(!(isAddressOfOperand && HasTrailingLParen) &&
+         "cannot be direct & operand and have a trailing lparen");
+
+  if (SS.isInvalid())
     return ExprError();
 
-  // Determine whether this is a member of an unknown specialization.
-  if (SS && SS->isSet() && !computeDeclContext(*SS, false)) {
-    return Owned(new (Context) DependentScopeDeclRefExpr(Name, Context.DependentTy,
-                                                     Loc, SS->getRange(),
-                static_cast<NestedNameSpecifier *>(SS->getScopeRep()),
-                                                     isAddressOfOperand));
+  TemplateArgumentListInfo ExplicitTemplateArgs;
+
+  // 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;
   }
 
-  LookupResult Lookup(*this, Name, Loc, LookupOrdinaryName);
-  LookupParsedName(Lookup, S, SS, true);
-
-  if (Lookup.isAmbiguous())
-    return ExprError();
-
-  // If this reference is in an Objective-C method, then ivar lookup happens as
-  // well.
   IdentifierInfo *II = Name.getAsIdentifierInfo();
-  if (II && getCurMethodDecl()) {
-    // There are two cases to handle here.  1) scoped lookup could have failed,
-    // in which case we should look for an ivar.  2) scoped lookup could have
-    // found a decl, but that decl is outside the current instance method (i.e.
-    // a global variable).  In these two cases, we do a lookup for an ivar with
-    // this name, if the lookup sucedes, we replace it our current decl.
 
-    // FIXME:  we should change lookup to do this.
+  // C++ [temp.dep.expr]p3:
+  //   An id-expression is type-dependent if it contains:
+  //     -- a nested-name-specifier that contains a class-name that
+  //        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)) {
+    bool CheckForImplicitMember = !isAddressOfOperand;
 
-    // If we're in a class method, we don't normally want to look for
-    // ivars.  But if we don't find anything else, and there's an
-    // ivar, that's an error.
-    bool IsClassMethod = getCurMethodDecl()->isClassMethod();
+    return ActOnDependentIdExpression(SS, Name, NameLoc,
+                                      CheckForImplicitMember,
+                                      TemplateArgs);
+  }
 
-    bool LookForIvars;
-    if (Lookup.empty())
-      LookForIvars = true;
-    else if (IsClassMethod)
-      LookForIvars = false;
-    else
-      LookForIvars = (Lookup.isSingleResult() &&
-                      Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+  // Perform the required lookup.
+  LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+  if (TemplateArgs) {
+    TemplateName TName =
+      TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
 
-    if (LookForIvars) {
-      ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
-      ObjCInterfaceDecl *ClassDeclared;
-      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
-        // Diagnose using an ivar in a class method.
-        if (IsClassMethod)
-           return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
-                            << IV->getDeclName());
+    // Just re-use the lookup done by isTemplateName.
+    DecomposeTemplateName(R, TName);
+  } else {
+    LookupParsedName(R, S, &SS, true);
 
-        // If we're referencing an invalid decl, just return this as a silent
-        // error node.  The error diagnostic was already emitted on the decl.
-        if (IV->isInvalidDecl())
-          return ExprError();
+    // If this reference is in an Objective-C method, then we need to do
+    // some special Objective-C lookup, too.
+    if (!SS.isSet() && II && getCurMethodDecl()) {
+      OwningExprResult E(LookupInObjCMethod(R, S, II));
+      if (E.isInvalid())
+        return ExprError();
 
-        // Check if referencing a field with __attribute__((deprecated)).
-        if (DiagnoseUseOfDecl(IV, Loc))
-          return ExprError();
-
-        // Diagnose the use of an ivar outside of the declaring class.
-        if (IV->getAccessControl() == ObjCIvarDecl::Private &&
-            ClassDeclared != IFace)
-          Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
-
-        // FIXME: This should use a new expr for a direct reference, don't
-        // turn this into Self->ivar, just return a BareIVarExpr or something.
-        IdentifierInfo &II = Context.Idents.get("self");
-        UnqualifiedId SelfName;
-        SelfName.setIdentifier(&II, SourceLocation());          
-        CXXScopeSpec SelfScopeSpec;
-        OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
-                                                      SelfName, false, false);
-        MarkDeclarationReferenced(Loc, IV);
-        return Owned(new (Context)
-                     ObjCIvarRefExpr(IV, IV->getType(), Loc,
-                                     SelfExpr.takeAs<Expr>(), true, true));
-      }
-    } else if (getCurMethodDecl()->isInstanceMethod()) {
-      // We should warn if a local variable hides an ivar.
-      ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
-      ObjCInterfaceDecl *ClassDeclared;
-      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
-        if (IV->getAccessControl() != ObjCIvarDecl::Private ||
-            IFace == ClassDeclared)
-          Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
-      }
-    }
-    // Needed to implement property "super.method" notation.
-    if (Lookup.empty() && II->isStr("super")) {
-      QualType T;
-
-      if (getCurMethodDecl()->isInstanceMethod())
-        T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
-                                      getCurMethodDecl()->getClassInterface()));
-      else
-        T = Context.getObjCClassType();
-      return Owned(new (Context) ObjCSuperExpr(Loc, T));
+      Expr *Ex = E.takeAs<Expr>();
+      if (Ex) return Owned(Ex);
     }
   }
 
+  if (R.isAmbiguous())
+    return ExprError();
+
   // Determine whether this name might be a candidate for
   // argument-dependent lookup.
-  bool ADL = UseArgumentDependentLookup(SS, Lookup, HasTrailingLParen);
+  bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
 
-  if (Lookup.empty() && !ADL) {
+  if (R.empty() && !ADL) {
     // Otherwise, this could be an implicitly declared function reference (legal
-    // in C90, extension in C99).
-    if (HasTrailingLParen && II &&
-        !getLangOptions().CPlusPlus) { // Not in C++.
-      NamedDecl *D = ImplicitlyDefineFunction(Loc, *II, S);
-      if (D) Lookup.addDecl(D);
-    } else {
-      // If this name wasn't predeclared and if this is not a function call,
-      // diagnose the problem.
-      if (SS && !SS->isEmpty())
-        return ExprError(Diag(Loc, diag::err_no_member)
-                           << Name << computeDeclContext(*SS, false)
-                           << SS->getRange());
+    // in C90, extension in C99, forbidden in C++).
+    if (HasTrailingLParen && II && !getLangOptions().CPlusPlus) {
+      NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
+      if (D) R.addDecl(D);
+    }
+
+    // If this name wasn't predeclared and if this is not a function
+    // call, diagnose the problem.
+    if (R.empty()) {
+      if (!SS.isEmpty())
+        return ExprError(Diag(NameLoc, diag::err_no_member)
+                           << Name << computeDeclContext(SS, false)
+                           << SS.getRange());
       else if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
                Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
-        return ExprError(Diag(Loc, diag::err_undeclared_use)
-          << Name.getAsString());
+        return ExprError(Diag(NameLoc, diag::err_undeclared_use)
+                           << Name);
       else
-        return ExprError(Diag(Loc, diag::err_undeclared_var_use) << Name);
+        return ExprError(Diag(NameLoc, diag::err_undeclared_var_use) << Name);
     }
   }
 
-  if (VarDecl *Var = Lookup.getAsSingle<VarDecl>()) {
+  // This is guaranteed from this point on.
+  assert(!R.empty() || ADL);
+
+  if (VarDecl *Var = R.getAsSingle<VarDecl>()) {
     // Warn about constructs like:
     //   if (void *X = foo()) { ... } else { X }.
     // In the else block, the pointer is always false.
 
-    // FIXME: In a template instantiation, we don't have scope
-    // information to check this property.
     if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
       Scope *CheckS = S;
       while (CheckS && CheckS->getControlParent()) {
         if (CheckS->isWithinElse() &&
             CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
-          ExprError(Diag(Loc, diag::warn_value_always_zero)
+          ExprError(Diag(NameLoc, diag::warn_value_always_zero)
             << Var->getDeclName()
             << (Var->getType()->isPointerType()? 2 :
                 Var->getType()->isBooleanType()? 1 : 0));
@@ -823,21 +761,21 @@
         CheckS = CheckS->getParent();
       }
     }
-  } else if (FunctionDecl *Func = Lookup.getAsSingle<FunctionDecl>()) {
+  } else if (FunctionDecl *Func = R.getAsSingle<FunctionDecl>()) {
     if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) {
       // C99 DR 316 says that, if a function type comes from a
       // function definition (without a prototype), that type is only
       // used for checking compatibility. Therefore, when referencing
       // the function, we pretend that we don't have the full function
       // type.
-      if (DiagnoseUseOfDecl(Func, Loc))
+      if (DiagnoseUseOfDecl(Func, NameLoc))
         return ExprError();
 
       QualType T = Func->getType();
       QualType NoProtoType = T;
       if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>())
         NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
-      return BuildDeclRefExpr(Func, NoProtoType, Loc, SS);
+      return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS);
     }
   }
 
@@ -853,19 +791,141 @@
   // calculate them both in one pass if that proves important for
   // performance.
   if (!ADL) {
-    bool isAbstractMemberPointer = 
-      (isAddressOfOperand && SS && !SS->isEmpty());
+    bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty());
 
-    if (!isAbstractMemberPointer && !Lookup.empty() &&
-        isa<CXXRecordDecl>((*Lookup.begin())->getDeclContext())) {
-      return BuildImplicitMemberReferenceExpr(SS, Lookup);
+    if (!isAbstractMemberPointer && !R.empty() &&
+        isa<CXXRecordDecl>((*R.begin())->getDeclContext())) {
+      return BuildImplicitMemberReferenceExpr(SS, R, TemplateArgs);
     }
   }
 
-  assert(Lookup.getResultKind() != LookupResult::FoundUnresolvedValue &&
-         "found UnresolvedUsingValueDecl in non-class scope");
+  if (TemplateArgs)
+    return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs);
 
-  return BuildDeclarationNameExpr(SS, Lookup, ADL);
+  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.
+Sema::OwningExprResult
+Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
+                                        DeclarationName Name,
+                                        SourceLocation NameLoc) {
+  DeclContext *DC;
+  if (!(DC = computeDeclContext(SS, false)) ||
+      DC->isDependentContext() ||
+      RequireCompleteDeclContext(SS))
+    return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0);
+
+  LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+  LookupQualifiedName(R, DC);
+
+  if (R.isAmbiguous())
+    return ExprError();
+
+  if (R.empty()) {
+    Diag(NameLoc, diag::err_no_member) << Name << DC << SS.getRange();
+    return ExprError();
+  }
+
+  return BuildDeclarationNameExpr(SS, R, /*ADL*/ false);
+}
+
+/// LookupInObjCMethod - The parser has read a name in, and Sema has
+/// detected that we're currently inside an ObjC method.  Perform some
+/// additional lookup.
+///
+/// Ideally, most of this would be done by lookup, but there's
+/// actually quite a lot of extra work involved.
+///
+/// Returns a null sentinel to indicate trivial success.
+Sema::OwningExprResult
+Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
+                         IdentifierInfo *II) {
+  SourceLocation Loc = Lookup.getNameLoc();
+
+  // There are two cases to handle here.  1) scoped lookup could have failed,
+  // in which case we should look for an ivar.  2) scoped lookup could have
+  // found a decl, but that decl is outside the current instance method (i.e.
+  // a global variable).  In these two cases, we do a lookup for an ivar with
+  // this name, if the lookup sucedes, we replace it our current decl.
+
+  // If we're in a class method, we don't normally want to look for
+  // ivars.  But if we don't find anything else, and there's an
+  // ivar, that's an error.
+  bool IsClassMethod = getCurMethodDecl()->isClassMethod();
+
+  bool LookForIvars;
+  if (Lookup.empty())
+    LookForIvars = true;
+  else if (IsClassMethod)
+    LookForIvars = false;
+  else
+    LookForIvars = (Lookup.isSingleResult() &&
+                    Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+
+  if (LookForIvars) {
+    ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
+    ObjCInterfaceDecl *ClassDeclared;
+    if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+      // Diagnose using an ivar in a class method.
+      if (IsClassMethod)
+        return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+                         << IV->getDeclName());
+
+      // If we're referencing an invalid decl, just return this as a silent
+      // error node.  The error diagnostic was already emitted on the decl.
+      if (IV->isInvalidDecl())
+        return ExprError();
+
+      // Check if referencing a field with __attribute__((deprecated)).
+      if (DiagnoseUseOfDecl(IV, Loc))
+        return ExprError();
+
+      // Diagnose the use of an ivar outside of the declaring class.
+      if (IV->getAccessControl() == ObjCIvarDecl::Private &&
+          ClassDeclared != IFace)
+        Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
+
+      // FIXME: This should use a new expr for a direct reference, don't
+      // turn this into Self->ivar, just return a BareIVarExpr or something.
+      IdentifierInfo &II = Context.Idents.get("self");
+      UnqualifiedId SelfName;
+      SelfName.setIdentifier(&II, SourceLocation());          
+      CXXScopeSpec SelfScopeSpec;
+      OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
+                                                    SelfName, false, false);
+      MarkDeclarationReferenced(Loc, IV);
+      return Owned(new (Context)
+                   ObjCIvarRefExpr(IV, IV->getType(), Loc,
+                                   SelfExpr.takeAs<Expr>(), true, true));
+    }
+  } else if (getCurMethodDecl()->isInstanceMethod()) {
+    // We should warn if a local variable hides an ivar.
+    ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
+    ObjCInterfaceDecl *ClassDeclared;
+    if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+      if (IV->getAccessControl() != ObjCIvarDecl::Private ||
+          IFace == ClassDeclared)
+        Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
+    }
+  }
+
+  // Needed to implement property "super.method" notation.
+  if (Lookup.empty() && II->isStr("super")) {
+    QualType T;
+    
+    if (getCurMethodDecl()->isInstanceMethod())
+      T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
+                                    getCurMethodDecl()->getClassInterface()));
+    else
+      T = Context.getObjCClassType();
+    return Owned(new (Context) ObjCSuperExpr(Loc, T));
+  }
+
+  // Sentinel value saying that we didn't do anything special.
+  return Owned((Expr*) 0);
 }
 
 /// \brief Cast member's object to its own class if necessary.
@@ -899,29 +959,35 @@
 /// \brief Build a MemberExpr AST node.
 static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
                                    const CXXScopeSpec *SS, NamedDecl *Member,
-                                   SourceLocation Loc, QualType Ty) {
-  if (SS && SS->isSet())
-    return MemberExpr::Create(C, Base, isArrow,
-                              (NestedNameSpecifier *)SS->getScopeRep(),
-                              SS->getRange(), Member, Loc,
-                              // FIXME: Explicit template argument lists
-                              0, Ty);
+                                   SourceLocation Loc, QualType Ty,
+                          const TemplateArgumentListInfo *TemplateArgs = 0) {
+  NestedNameSpecifier *Qualifier = 0;
+  SourceRange QualifierRange;
+  if (SS && SS->isSet()) {
+    Qualifier = (NestedNameSpecifier *) SS->getScopeRep();
+    QualifierRange = SS->getRange();
+  }
 
-  return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty);
+  return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
+                            Member, Loc, TemplateArgs, Ty);
 }
 
 /// Builds an implicit member access expression from the given
 /// unqualified lookup set, which is known to contain only class
 /// members.
 Sema::OwningExprResult
-Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS,
-                                       LookupResult &R) {
+Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS,
+                                       LookupResult &R,
+                              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 (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
       return BuildAnonymousStructUnionMemberReference(Loc, FD);
@@ -938,13 +1004,14 @@
     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 || !SS->isSet()))
+      if (MD->isVirtual() && !SS.isSet())
         ShouldCheckUse = false;
     }
 
     if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc))
       return ExprError();
-    return Owned(BuildMemberExpr(Context, This, true, SS, D, Loc, MemberType));
+    return Owned(BuildMemberExpr(Context, This, true, &SS, D, Loc, MemberType,
+                                 TemplateArgs));
   }
 
   if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
@@ -973,10 +1040,13 @@
   // We're not in an implicit member-reference context, but the lookup
   // results might not require an instance.  Try to build a non-member
   // decl reference.
+  if (TemplateArgs)
+    return BuildTemplateIdExpr(SS, R, /* ADL */ false, *TemplateArgs);
+
   return BuildDeclarationNameExpr(SS, R, /*ADL*/ false);
 }
 
-bool Sema::UseArgumentDependentLookup(const CXXScopeSpec *SS,
+bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
                                       const LookupResult &R,
                                       bool HasTrailingLParen) {
   // Only when used directly as the postfix-expression of a call.
@@ -984,7 +1054,7 @@
     return false;
 
   // Never if a scope specifier was provided.
-  if (SS && SS->isSet())
+  if (SS.isSet())
     return false;
 
   // Only in C++ or ObjC++.
@@ -1056,11 +1126,13 @@
 }
 
 Sema::OwningExprResult
-Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
                                LookupResult &R,
                                bool NeedsADL) {
   assert(R.getResultKind() != LookupResult::FoundUnresolvedValue);
 
+  // If this isn't an overloaded result and we don't need ADL, just
+  // build an ordinary singleton decl ref.
   if (!NeedsADL && !R.isOverloadedResult())
     return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl());
 
@@ -1071,10 +1143,12 @@
       CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
     return ExprError();
 
+  bool Dependent
+    = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), 0);
   UnresolvedLookupExpr *ULE
-    = UnresolvedLookupExpr::Create(Context,
-                    SS ? (NestedNameSpecifier *)SS->getScopeRep() : 0,
-                                   SS ? SS->getRange() : SourceRange(),
+    = UnresolvedLookupExpr::Create(Context, Dependent,
+                                   (NestedNameSpecifier*) SS.getScopeRep(),
+                                   SS.getRange(),
                                    R.getLookupName(), R.getNameLoc(),
                                    NeedsADL, R.isOverloadedResult());
   for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
@@ -1086,7 +1160,7 @@
 
 /// \brief Complete semantic analysis for a reference to the given declaration.
 Sema::OwningExprResult
-Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
                                SourceLocation Loc, NamedDecl *D) {
   assert(D && "Cannot refer to a NULL declaration");
   assert(!isa<FunctionTemplateDecl>(D) &&
@@ -1134,7 +1208,7 @@
   // If this reference is not in a block or if the referenced variable is
   // within the block, create a normal DeclRefExpr.
 
-  return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, SS);
+  return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, &SS);
 }
 
 Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
@@ -2640,14 +2714,10 @@
   Name = DeclarationName();
   Qualifier = 0;
   QualifierRange = SourceRange();
-  ArgumentDependentLookup = getLangOptions().CPlusPlus;
+  ArgumentDependentLookup = false;
   Overloaded = false;
   HasExplicitTemplateArguments = false;
 
-  // Most of the explicit tracking of ArgumentDependentLookup in this
-  // function can disappear when we handle unresolved
-  // TemplateIdRefExprs properly.
-  
   // If we're directly calling a function, get the appropriate declaration.
   // Also, in C++, keep track of whether we should perform argument-dependent
   // lookup and whether there were any explicitly-specified template arguments.
@@ -2655,9 +2725,6 @@
     if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr))
       FnExpr = IcExpr->getSubExpr();
     else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) {
-      // Parentheses around a function disable ADL
-      // (C++0x [basic.lookup.argdep]p1).
-      ArgumentDependentLookup = false;
       FnExpr = PExpr->getSubExpr();
     } else if (isa<UnaryOperator>(FnExpr) &&
                cast<UnaryOperator>(FnExpr)->getOpcode()
@@ -2677,49 +2744,12 @@
       Overloaded = UnresLookup->isOverloaded();
       if ((Qualifier = UnresLookup->getQualifier()))
         QualifierRange = UnresLookup->getQualifierRange();
-      break;
-    } else if (TemplateIdRefExpr *TemplateIdRef
-               = dyn_cast<TemplateIdRefExpr>(FnExpr)) {
-      if (NamedDecl *Function
-          = TemplateIdRef->getTemplateName().getAsTemplateDecl()) {
-        Name = Function->getDeclName();
-        Fns.push_back(Function);
-      }
-      else {
-        OverloadedFunctionDecl *Overload
-          = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl();
-        Name = Overload->getDeclName();
-        Fns.append(Overload->function_begin(), Overload->function_end());
-      }
-      Overloaded = true;
-      HasExplicitTemplateArguments = true;
-      TemplateIdRef->copyTemplateArgumentsInto(ExplicitTemplateArgs);
-      
-      // C++ [temp.arg.explicit]p6:
-      //   [Note: For simple function names, argument dependent lookup (3.4.2)
-      //   applies even when the function name is not visible within the
-      //   scope of the call. This is because the call still has the syntactic
-      //   form of a function call (3.4.1). But when a function template with
-      //   explicit template arguments is used, the call does not have the
-      //   correct syntactic form unless there is a function template with
-      //   that name visible at the point of the call. If no such name is
-      //   visible, the call is not syntactically well-formed and
-      //   argument-dependent lookup does not apply. If some such name is
-      //   visible, argument dependent lookup applies and additional function
-      //   templates may be found in other namespaces.
-      //
-      // The summary of this paragraph is that, if we get to this point and the
-      // template-id was not a qualified name, then argument-dependent lookup
-      // is still possible.
-      if ((Qualifier = TemplateIdRef->getQualifier())) {
-        ArgumentDependentLookup = false;
-        QualifierRange = TemplateIdRef->getQualifierRange();
+      if (UnresLookup->hasExplicitTemplateArgs()) {
+        HasExplicitTemplateArguments = true;
+        UnresLookup->copyTemplateArgumentsInto(ExplicitTemplateArgs);
       }
       break;
     } else {
-      // Any kind of name that does not refer to a declaration (or
-      // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3).
-      ArgumentDependentLookup = false;
       break;
     }
   }
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 4aa928a..4800a1d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2306,7 +2306,7 @@
 /// \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,
+bool Sema::isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
                                      SourceLocation NameLoc, QualType &ThisType,
                                      QualType &MemberType) {
   // If this isn't a C++ method, then it isn't an implicit member reference.
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 08e9dc3..8f09827 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1544,11 +1544,7 @@
 
     if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg))
       Functions.append(ULE->decls_begin(), ULE->decls_end());
-    else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(Arg)) {
-      TemplateName TName = TIRE->getTemplateName();
-      OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl();
-      Functions.append(Ovl->function_begin(), Ovl->function_end());
-    } else
+    else
       continue;
 
     for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Functions.begin(),
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 7366ec9..49050be 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -4345,29 +4345,19 @@
   // Try to dig out the overloaded function.
   OverloadedFunctionDecl *Ovl = 0;
   FunctionTemplateDecl *FunctionTemplate = 0;
-  if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) {
-    assert(!isa<OverloadedFunctionDecl>(DR->getDecl()));
-    FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl());
-    HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList();
-    if (HasExplicitTemplateArgs)
-      DR->copyTemplateArgumentsInto(ExplicitTemplateArgs);
-  } else if (UnresolvedLookupExpr *UL
+  if (UnresolvedLookupExpr *UL
                = dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
     Fns.append(UL->decls_begin(), UL->decls_end());
+    if (UL->hasExplicitTemplateArgs()) {
+      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)
       ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
-  } else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) {
-    TemplateName Name = TIRE->getTemplateName();
-    Ovl = Name.getAsOverloadedFunctionDecl();
-    FunctionTemplate = 
-      dyn_cast_or_null<FunctionTemplateDecl>(Name.getAsTemplateDecl());
-    
-    HasExplicitTemplateArgs = true;
-    TIRE->copyTemplateArgumentsInto(ExplicitTemplateArgs);
   }
 
   if (Ovl) Fns.append(Ovl->function_begin(), Ovl->function_end());
@@ -4693,7 +4683,8 @@
 
   if (Input->isTypeDependent()) {
     UnresolvedLookupExpr *Fn
-      = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, OpLoc,
+      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
+                                     0, SourceRange(), OpName, OpLoc,
                                      /*ADL*/ true, IsOverloaded(Functions));
     for (FunctionSet::iterator Func = Functions.begin(),
                             FuncEnd = Functions.end();
@@ -4849,7 +4840,8 @@
     }
     
     UnresolvedLookupExpr *Fn
-      = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, OpLoc,
+      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
+                                     0, SourceRange(), OpName, OpLoc,
                                      /* ADL */ true, IsOverloaded(Functions));
                                      
     for (FunctionSet::iterator Func = Functions.begin(),
@@ -5014,9 +5006,10 @@
   if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
 
     UnresolvedLookupExpr *Fn
-      = UnresolvedLookupExpr::Create(Context, 0, SourceRange(), OpName, LLoc,
+      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
+                                     0, SourceRange(), OpName, LLoc,
                                      /*ADL*/ true, /*Overloaded*/ false);
-    // Can't add an actual overloads yet
+    // Can't add any actual overloads yet
 
     Base.release();
     Idx.release();
@@ -5611,10 +5604,9 @@
         // Do nothing: static member functions aren't any different
         // from non-member functions.
       } else {
-        // Fix the sub expression, which really has to be one of:
-        //   * a DeclRefExpr holding a member function template
-        //   * a TemplateIdRefExpr, also holding a member function template
-        //   * an UnresolvedLookupExpr holding an overloaded member function
+        // Fix the sub expression, which really has to be an
+        // UnresolvedLookupExpr holding an overloaded member function
+        // or template.
         Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
         if (SubExpr == UnOp->getSubExpr())
           return UnOp->Retain();
@@ -5635,9 +5627,6 @@
         return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf,
                                            MemPtrType, UnOp->getOperatorLoc());
       }
-
-      // FIXME: TemplateIdRefExpr referring to a member function template
-      // specialization!
     }
     Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
     if (SubExpr == UnOp->getSubExpr())
@@ -5646,28 +5635,24 @@
     return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf,
                                      Context.getPointerType(SubExpr->getType()),
                                        UnOp->getOperatorLoc());
-  }
-  
-  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
-    assert((isa<FunctionTemplateDecl>(DRE->getDecl()) ||
-            isa<FunctionDecl>(DRE->getDecl())) &&
-           "Expected function or function template");
-    // FIXME: avoid copy.
-    TemplateArgumentListInfo TemplateArgs;
-    if (DRE->hasExplicitTemplateArgumentList())
-      DRE->copyTemplateArgumentsInto(TemplateArgs);
-
-    return DeclRefExpr::Create(Context,
-                               DRE->getQualifier(),
-                               DRE->getQualifierRange(),
-                               Fn,
-                               DRE->getLocation(),
-                               Fn->getType(),
-                               (DRE->hasExplicitTemplateArgumentList()
-                                  ? &TemplateArgs : 0));
   } 
 
   if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+    if (ULE->hasExplicitTemplateArgs()) {
+      // FIXME: avoid copy.
+      TemplateArgumentListInfo TemplateArgs;
+      if (ULE->hasExplicitTemplateArgs())
+        ULE->copyTemplateArgumentsInto(TemplateArgs);
+
+      return DeclRefExpr::Create(Context,
+                                 ULE->getQualifier(),
+                                 ULE->getQualifierRange(),
+                                 Fn,
+                                 ULE->getNameLoc(),
+                                 Fn->getType(),
+                                 &TemplateArgs);
+    }
+
     return DeclRefExpr::Create(Context,
                                ULE->getQualifier(),
                                ULE->getQualifierRange(),
@@ -5698,22 +5683,6 @@
                               Fn->getType());
   }
   
-  if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) {
-    // FIXME: Don't destroy TID here, since we need its template arguments
-    // to survive.
-    // TID->Destroy(Context);
-
-    // FIXME: avoid copy.
-    TemplateArgumentListInfo TemplateArgs;
-    TID->copyTemplateArgumentsInto(TemplateArgs);
-
-    return DeclRefExpr::Create(Context, 
-                               TID->getQualifier(), TID->getQualifierRange(),
-                               Fn, TID->getTemplateNameLoc(), 
-                               Fn->getType(),
-                               &TemplateArgs);
-  } 
-  
   assert(false && "Invalid reference to overloaded function");
   return E->Retain();
 }
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index a37a731..0e680f6 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -99,6 +99,19 @@
   return 0;
 }
 
+static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
+  LookupResult::Filter filter = R.makeFilter();
+  while (filter.hasNext()) {
+    NamedDecl *Orig = filter.next();
+    NamedDecl *Repl = isAcceptableTemplateName(C, Orig->getUnderlyingDecl());
+    if (!Repl)
+      filter.erase();
+    else if (Repl != Orig)
+      filter.replace(Repl);
+  }
+  filter.done();
+}
+
 TemplateNameKind Sema::isTemplateName(Scope *S,
                                       const CXXScopeSpec &SS,
                                       UnqualifiedId &Name,
@@ -120,109 +133,16 @@
   default:
     return TNK_Non_template;
   }
-  
-  // Determine where to perform name lookup
-  DeclContext *LookupCtx = 0;
-  bool isDependent = false;
-  if (ObjectTypePtr) {
-    // This nested-name-specifier occurs in a member access expression, e.g.,
-    // x->B::f, and we are looking into the type of the object.
-    assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
-    QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
-    LookupCtx = computeDeclContext(ObjectType);
-    isDependent = ObjectType->isDependentType();
-    assert((isDependent || !ObjectType->isIncompleteType()) && 
-           "Caller should have completed object type");
-  } else if (SS.isSet()) {
-    // This nested-name-specifier occurs after another nested-name-specifier,
-    // so long into the context associated with the prior nested-name-specifier.
-    LookupCtx = computeDeclContext(SS, EnteringContext);
-    isDependent = isDependentScopeSpecifier(SS);
-    
-    // The declaration context must be complete.
-    if (LookupCtx && RequireCompleteDeclContext(SS))
-      return TNK_Non_template;
-  }
 
-  LookupResult Found(*this, TName, SourceLocation(), LookupOrdinaryName);
-  bool ObjectTypeSearchedInScope = false;
-  if (LookupCtx) {
-    // Perform "qualified" name lookup into the declaration context we
-    // computed, which is either the type of the base of a member access
-    // expression or the declaration context associated with a prior
-    // nested-name-specifier.
-    LookupQualifiedName(Found, LookupCtx);
+  QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
 
-    if (ObjectTypePtr && Found.empty()) {
-      // C++ [basic.lookup.classref]p1:
-      //   In a class member access expression (5.2.5), if the . or -> token is
-      //   immediately followed by an identifier followed by a <, the
-      //   identifier must be looked up to determine whether the < is the
-      //   beginning of a template argument list (14.2) or a less-than operator.
-      //   The identifier is first looked up in the class of the object
-      //   expression. If the identifier is not found, it is then looked up in
-      //   the context of the entire postfix-expression and shall name a class
-      //   or function template.
-      //
-      // FIXME: When we're instantiating a template, do we actually have to
-      // look in the scope of the template? Seems fishy...
-      LookupName(Found, S);
-      ObjectTypeSearchedInScope = true;
-    }
-  } else if (isDependent) {
-    // We cannot look into a dependent object type or
-    return TNK_Non_template;
-  } else {
-    // Perform unqualified name lookup in the current scope.
-    LookupName(Found, S);
-  }
-
-  // FIXME: Cope with ambiguous name-lookup results.
-  assert(!Found.isAmbiguous() &&
-         "Cannot handle template name-lookup ambiguities");
-
-  NamedDecl *Template
-    = isAcceptableTemplateName(Context, Found.getAsSingleDecl(Context));
-  if (!Template)
+  LookupResult R(*this, TName, SourceLocation(), LookupOrdinaryName);
+  R.suppressDiagnostics();
+  LookupTemplateName(R, S, SS, ObjectType, EnteringContext);
+  if (R.empty())
     return TNK_Non_template;
 
-  if (ObjectTypePtr && !ObjectTypeSearchedInScope) {
-    // C++ [basic.lookup.classref]p1:
-    //   [...] If the lookup in the class of the object expression finds a
-    //   template, the name is also looked up in the context of the entire
-    //   postfix-expression and [...]
-    //
-    LookupResult FoundOuter(*this, TName, SourceLocation(), LookupOrdinaryName);
-    LookupName(FoundOuter, S);
-    // FIXME: Handle ambiguities in this lookup better
-    NamedDecl *OuterTemplate
-      = isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context));
-
-    if (!OuterTemplate) {
-      //   - if the name is not found, the name found in the class of the
-      //     object expression is used, otherwise
-    } else if (!isa<ClassTemplateDecl>(OuterTemplate)) {
-      //   - if the name is found in the context of the entire
-      //     postfix-expression and does not name a class template, the name
-      //     found in the class of the object expression is used, otherwise
-    } else {
-      //   - if the name found is a class template, it must refer to the same
-      //     entity as the one found in the class of the object expression,
-      //     otherwise the program is ill-formed.
-      if (OuterTemplate->getCanonicalDecl() != Template->getCanonicalDecl()) {
-        Diag(Name.getSourceRange().getBegin(), 
-             diag::err_nested_name_member_ref_lookup_ambiguous)
-          << TName
-          << Name.getSourceRange();
-        Diag(Template->getLocation(), diag::note_ambig_member_ref_object_type)
-          << QualType::getFromOpaquePtr(ObjectTypePtr);
-        Diag(OuterTemplate->getLocation(), diag::note_ambig_member_ref_scope);
-
-        // Recover by taking the template that we found in the object
-        // expression's type.
-      }
-    }
-  }
+  NamedDecl *Template = R.getAsSingleDecl(Context);
 
   if (SS.isSet() && !SS.isInvalid()) {
     NestedNameSpecifier *Qualifier
@@ -251,7 +171,250 @@
   assert((isa<FunctionTemplateDecl>(Template) ||
           isa<OverloadedFunctionDecl>(Template)) &&
          "Unhandled template kind in Sema::isTemplateName");
-  return TNK_Function_template;
+  return TNK_Function_template;  
+}
+
+void Sema::LookupTemplateName(LookupResult &Found,
+                              Scope *S, const CXXScopeSpec &SS,
+                              QualType ObjectType,
+                              bool EnteringContext) {
+  // Determine where to perform name lookup
+  DeclContext *LookupCtx = 0;
+  bool isDependent = false;
+  if (!ObjectType.isNull()) {
+    // This nested-name-specifier occurs in a member access expression, e.g.,
+    // x->B::f, and we are looking into the type of the object.
+    assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
+    LookupCtx = computeDeclContext(ObjectType);
+    isDependent = ObjectType->isDependentType();
+    assert((isDependent || !ObjectType->isIncompleteType()) && 
+           "Caller should have completed object type");
+  } else if (SS.isSet()) {
+    // This nested-name-specifier occurs after another nested-name-specifier,
+    // so long into the context associated with the prior nested-name-specifier.
+    LookupCtx = computeDeclContext(SS, EnteringContext);
+    isDependent = isDependentScopeSpecifier(SS);
+    
+    // The declaration context must be complete.
+    if (LookupCtx && RequireCompleteDeclContext(SS))
+      return;
+  }
+
+  bool ObjectTypeSearchedInScope = false;
+  if (LookupCtx) {
+    // Perform "qualified" name lookup into the declaration context we
+    // computed, which is either the type of the base of a member access
+    // expression or the declaration context associated with a prior
+    // nested-name-specifier.
+    LookupQualifiedName(Found, LookupCtx);
+
+    if (!ObjectType.isNull() && Found.empty()) {
+      // C++ [basic.lookup.classref]p1:
+      //   In a class member access expression (5.2.5), if the . or -> token is
+      //   immediately followed by an identifier followed by a <, the
+      //   identifier must be looked up to determine whether the < is the
+      //   beginning of a template argument list (14.2) or a less-than operator.
+      //   The identifier is first looked up in the class of the object
+      //   expression. If the identifier is not found, it is then looked up in
+      //   the context of the entire postfix-expression and shall name a class
+      //   or function template.
+      //
+      // FIXME: When we're instantiating a template, do we actually have to
+      // look in the scope of the template? Seems fishy...
+      if (S) LookupName(Found, S);
+      ObjectTypeSearchedInScope = true;
+    }
+  } else if (isDependent) {
+    // We cannot look into a dependent object type or
+    return;
+  } else {
+    // Perform unqualified name lookup in the current scope.
+    LookupName(Found, S);
+  }
+
+  // FIXME: Cope with ambiguous name-lookup results.
+  assert(!Found.isAmbiguous() &&
+         "Cannot handle template name-lookup ambiguities");
+
+  FilterAcceptableTemplateNames(Context, Found);
+  if (Found.empty())
+    return;
+
+  if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) {
+    // C++ [basic.lookup.classref]p1:
+    //   [...] If the lookup in the class of the object expression finds a
+    //   template, the name is also looked up in the context of the entire
+    //   postfix-expression and [...]
+    //
+    LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
+                            LookupOrdinaryName);
+    LookupName(FoundOuter, S);
+    FilterAcceptableTemplateNames(Context, FoundOuter);
+    // FIXME: Handle ambiguities in this lookup better
+
+    if (FoundOuter.empty()) {
+      //   - if the name is not found, the name found in the class of the
+      //     object expression is used, otherwise
+    } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>()) {
+      //   - if the name is found in the context of the entire
+      //     postfix-expression and does not name a class template, the name
+      //     found in the class of the object expression is used, otherwise
+    } else {
+      //   - if the name found is a class template, it must refer to the same
+      //     entity as the one found in the class of the object expression,
+      //     otherwise the program is ill-formed.
+      if (!Found.isSingleResult() ||
+          Found.getFoundDecl()->getCanonicalDecl()
+            != FoundOuter.getFoundDecl()->getCanonicalDecl()) {
+        Diag(Found.getNameLoc(), 
+             diag::err_nested_name_member_ref_lookup_ambiguous)
+          << Found.getLookupName();
+        Diag(Found.getRepresentativeDecl()->getLocation(),
+             diag::note_ambig_member_ref_object_type)
+          << ObjectType;
+        Diag(FoundOuter.getFoundDecl()->getLocation(),
+             diag::note_ambig_member_ref_scope);
+
+        // Recover by taking the template that we found in the object
+        // expression's type.
+      }
+    }
+  }
+}
+
+/// Constructs a full type for the given nested-name-specifier.
+static QualType GetTypeForQualifier(ASTContext &Context,
+                                    NestedNameSpecifier *Qualifier) {
+  // Three possibilities:
+
+  // 1.  A namespace (global or not).
+  assert(!Qualifier->getAsNamespace() && "can't construct type for namespace");
+
+  // 2.  A type (templated or not).
+  Type *Ty = Qualifier->getAsType();
+  if (Ty) return QualType(Ty, 0);
+
+  // 3.  A dependent identifier.
+  assert(Qualifier->getAsIdentifier());
+  return Context.getTypenameType(Qualifier->getPrefix(),
+                                 Qualifier->getAsIdentifier());
+}
+
+static bool HasDependentTypeAsBase(ASTContext &Context,
+                                   CXXRecordDecl *Record,
+                                   CanQualType T) {
+  for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
+         E = Record->bases_end(); I != E; ++I) {
+    CanQualType BaseT = Context.getCanonicalType((*I).getType());
+    if (BaseT == T)
+      return true;
+
+    // We have to recurse here to cover some really bizarre cases.
+    // Obviously, we can only have the dependent type as an indirect
+    // base class through a dependent base class, and usually it's
+    // impossible to know which instantiation a dependent base class
+    // will have.  But!  If we're actually *inside* the dependent base
+    // class, then we know its instantiation and can therefore be
+    // reasonably expected to look into it.
+
+    // template <class T> class A : Base<T> {
+    //   class Inner : A<T> {
+    //     void foo() {
+    //       Base<T>::foo(); // statically known to be an implicit member
+    //                          reference
+    //     }
+    //   };
+    // };
+
+    CanQual<RecordType> RT = BaseT->getAs<RecordType>();
+    assert(RT && "base is not a record type");
+    CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
+    if (BaseRecord->isDefinition() &&
+        HasDependentTypeAsBase(Context, BaseRecord, T))
+      return true;
+  }
+
+  return false;
+}
+
+/// Checks whether the given dependent nested-name specifier
+/// introduces an implicit member reference.  This is only true if the
+/// nested-name specifier names a type identical to one of the current
+/// instance method's context's (possibly indirect) base classes.
+static bool IsImplicitDependentMemberReference(Sema &SemaRef,
+                                               NestedNameSpecifier *Qualifier,
+                                               QualType &ThisType) {
+  // If the context isn't a C++ method, then it isn't an implicit
+  // member reference.
+  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext);
+  if (!MD || MD->isStatic())
+    return false;
+
+  ASTContext &Context = SemaRef.Context;
+
+  // We want to check whether the method's context is known to inherit
+  // from the type named by the nested name specifier.  The trivial
+  // case here is:
+  //   template <class T> class Base { ... };
+  //   template <class T> class Derived : Base<T> {
+  //     void foo() {
+  //       Base<T>::foo();
+  //     }
+  //   };
+
+  QualType QT = GetTypeForQualifier(Context, Qualifier);
+  CanQualType T = Context.getCanonicalType(QT);
+  
+  // And now, just walk the non-dependent type hierarchy, trying to
+  // find the given type as a literal base class.
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(MD->getParent());
+  if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
+    return true;
+
+  return HasDependentTypeAsBase(Context, Record, T);
+}
+
+/// ActOnDependentIdExpression - Handle a dependent declaration name
+/// that was just parsed.
+Sema::OwningExprResult
+Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
+                                 DeclarationName Name,
+                                 SourceLocation NameLoc,
+                                 bool CheckForImplicitMember,
+                           const TemplateArgumentListInfo *TemplateArgs) {
+  NestedNameSpecifier *Qualifier
+    = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+    
+  QualType ThisType;
+  if (CheckForImplicitMember &&
+      IsImplicitDependentMemberReference(*this, Qualifier, ThisType)) {
+    Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType);
+
+    // Since the 'this' expression is synthesized, we don't need to
+    // perform the double-lookup check.
+    NamedDecl *FirstQualifierInScope = 0;
+
+    return Owned(CXXDependentScopeMemberExpr::Create(Context, This, true,
+                                                     /*Op*/ SourceLocation(),
+                                                     Qualifier, SS.getRange(),
+                                                     FirstQualifierInScope,
+                                                     Name, NameLoc,
+                                                     TemplateArgs));
+  }
+
+  return BuildDependentDeclRefExpr(SS, Name, NameLoc, TemplateArgs);
+}
+
+Sema::OwningExprResult
+Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+                                DeclarationName Name,
+                                SourceLocation NameLoc,
+                                const TemplateArgumentListInfo *TemplateArgs) {
+  return Owned(DependentScopeDeclRefExpr::Create(Context,
+               static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
+                                                 SS.getRange(),
+                                                 Name, NameLoc,
+                                                 TemplateArgs));
 }
 
 /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
@@ -1311,56 +1474,72 @@
   return ElabType.getAsOpaquePtr();
 }
 
-Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
-                                                 SourceRange QualifierRange,
-                                                 TemplateName Template,
-                                                 SourceLocation TemplateNameLoc,
+Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                                 LookupResult &R,
+                                                 bool RequiresADL,
                                  const TemplateArgumentListInfo &TemplateArgs) {
   // FIXME: Can we do any checking at this point? I guess we could check the
   // template arguments that we have against the template name, if the template
   // name refers to a single template. That's not a terribly common case,
   // though.
-  
-  // Cope with an implicit member access in a C++ non-static member function.
-  NamedDecl *D = Template.getAsTemplateDecl();
-  if (!D)
-    D = Template.getAsOverloadedFunctionDecl();
-  
-  CXXScopeSpec SS;
-  SS.setRange(QualifierRange);
-  SS.setScopeRep(Qualifier);
-  QualType ThisType, MemberType;
-  if (D && isImplicitMemberReference(&SS, D, TemplateNameLoc, 
-                                     ThisType, MemberType)) {
-    Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType);
-    return Owned(MemberExpr::Create(Context, This, true,
-                                    Qualifier, QualifierRange,
-                                    D, TemplateNameLoc, &TemplateArgs,
-                                    Context.OverloadTy));
+
+  // These should be filtered out by our callers.
+  assert(!R.empty() && "empty lookup results when building templateid");
+  assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
+
+  NestedNameSpecifier *Qualifier = 0;
+  SourceRange QualifierRange;
+  if (SS.isSet()) {
+    Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+    QualifierRange = SS.getRange();
   }
   
-  return Owned(TemplateIdRefExpr::Create(Context, Context.OverloadTy,
-                                         Qualifier, QualifierRange,
-                                         Template, TemplateNameLoc,
-                                         TemplateArgs));
+  bool Dependent
+    = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(),
+                                              &TemplateArgs);
+  UnresolvedLookupExpr *ULE
+    = UnresolvedLookupExpr::Create(Context, Dependent,
+                                   Qualifier, QualifierRange,
+                                   R.getLookupName(), R.getNameLoc(),
+                                   RequiresADL, TemplateArgs);
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+    ULE->addDecl(*I);
+
+  return Owned(ULE);
 }
 
-Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
-                                                 TemplateTy TemplateD,
-                                                 SourceLocation TemplateNameLoc,
-                                                 SourceLocation LAngleLoc,
-                                              ASTTemplateArgsPtr TemplateArgsIn,
-                                                 SourceLocation RAngleLoc) {
-  TemplateName Template = TemplateD.getAsVal<TemplateName>();
+// We actually only call this from template instantiation.
+Sema::OwningExprResult
+Sema::BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS,
+                                   DeclarationName Name,
+                                   SourceLocation NameLoc,
+                             const TemplateArgumentListInfo &TemplateArgs) {
+  DeclContext *DC;
+  if (!(DC = computeDeclContext(SS, false)) ||
+      DC->isDependentContext() ||
+      RequireCompleteDeclContext(SS))
+    return BuildDependentDeclRefExpr(SS, Name, NameLoc, &TemplateArgs);
 
-  // Translate the parser's template argument list in our AST format.
-  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
-  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
-  TemplateArgsIn.release();
+  LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+  LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false);
 
-  return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
-                             SS.getRange(),
-                             Template, TemplateNameLoc, TemplateArgs);
+  if (R.isAmbiguous())
+    return ExprError();
+  
+  if (R.empty()) {
+    Diag(NameLoc, diag::err_template_kw_refers_to_non_template)
+      << Name << SS.getRange();
+    return ExprError();
+  }
+
+  if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) {
+    Diag(NameLoc, diag::err_template_kw_refers_to_class_template)
+      << (NestedNameSpecifier*) SS.getScopeRep() << Name << SS.getRange();
+    Diag(Temp->getLocation(), diag::note_referenced_class_template);
+    return ExprError();
+  }
+
+  return BuildTemplateIdExpr(SS, R, /* ADL */ false, TemplateArgs);
 }
 
 /// \brief Form a dependent template name.
@@ -1673,12 +1852,11 @@
         // parsed as a template template argument. However, since we now
         // know that we need a non-type template argument, convert this
         // template name into an expression.          
-        Expr *E = new (Context) DependentScopeDeclRefExpr(DTN->getIdentifier(),
-                                                      Context.DependentTy,
-                                                      Arg.getTemplateNameLoc(),
+        Expr *E = DependentScopeDeclRefExpr::Create(Context,
+                                                    DTN->getQualifier(),
                                                Arg.getTemplateQualifierRange(),
-                                                      DTN->getQualifier(),
-                                                  /*isAddressOfOperand=*/false);
+                                                    DTN->getIdentifier(),
+                                                    Arg.getTemplateNameLoc());
         
         TemplateArgument Result;
         if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 502c151..dd92218 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -557,9 +557,6 @@
                                                    bool isAddressOfOperand);
     Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E,
                                                 bool isAddressOfOperand);
-    Sema::OwningExprResult TransformUnresolvedLookupExpr(
-                                                UnresolvedLookupExpr *E,
-                                                bool isAddressOfOperand);
 
     Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E,
                                                       bool isAddressOfOperand);
@@ -698,49 +695,6 @@
 }
 
 Sema::OwningExprResult
-TemplateInstantiator::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old,
-                                                    bool isAddressOfOperand) {
-  LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
-                 Sema::LookupOrdinaryName);
-
-  for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(),
-         E = Old->decls_end(); I != E; ++I) {
-    NamedDecl *InstD = SemaRef.FindInstantiatedDecl(*I, TemplateArgs);
-    if (!InstD)
-      return SemaRef.ExprError();
-
-    // The lookup values can never instantiate to a UsingDecl, because
-    // only UnresolvedUsingValueDecls do that, and those can never
-    // appear in UnresolvedLookupExprs (only UnresolvedMemberLookupExprs).
-    assert(!isa<UsingDecl>(InstD));
-
-    // Analogously.
-    assert(!isa<UnresolvedUsingValueDecl>(InstD->getUnderlyingDecl()));
-
-    R.addDecl(InstD);
-  }
-
-  R.resolveKind();
-
-  // This shouldn't be possible.
-  assert(!R.isAmbiguous());
-
-  CXXScopeSpec SS;
-  NestedNameSpecifier *Qualifier = 0;
-  if (Old->getQualifier()) {
-    Qualifier = TransformNestedNameSpecifier(Old->getQualifier(),
-                                             Old->getQualifierRange());
-    if (!Qualifier)
-      return SemaRef.ExprError();
-    
-    SS.setScopeRep(Qualifier);
-    SS.setRange(Old->getQualifierRange());
-  }
-
-  return SemaRef.BuildDeclarationNameExpr(&SS, R, Old->requiresADL());
-}
-
-Sema::OwningExprResult
 TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
                                            bool isAddressOfOperand) {
   // FIXME: Clean this up a bit
@@ -847,7 +801,7 @@
     SS.setRange(E->getQualifierRange());
   }
   
-  return SemaRef.BuildDeclarationNameExpr(&SS, E->getLocation(), InstD);
+  return SemaRef.BuildDeclarationNameExpr(SS, E->getLocation(), InstD);
 }
 
 Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index a7a9cfa..e1d0bba 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -14,6 +14,7 @@
 #define LLVM_CLANG_SEMA_TREETRANSFORM_H
 
 #include "Sema.h"
+#include "Lookup.h"
 #include "clang/Sema/SemaDiagnostic.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
@@ -581,16 +582,6 @@
                                    bool TemplateKW,
                                    TemplateDecl *Template);
 
-  /// \brief Build a new template name given a nested name specifier, a flag
-  /// indicating whether the "template" keyword was provided, and a set of
-  /// overloaded function templates.
-  ///
-  /// By default, builds the new template name directly. Subclasses may override
-  /// this routine to provide different behavior.
-  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
-                                   bool TemplateKW,
-                                   OverloadedFunctionDecl *Ovl);
-
   /// \brief Build a new template name given a nested name specifier and the
   /// name that is referred to as a template.
   ///
@@ -815,6 +806,17 @@
   ///
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
+  OwningExprResult RebuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                                              LookupResult &R,
+                                              bool RequiresADL) {
+    return getSema().BuildDeclarationNameExpr(SS, R, RequiresADL);
+  }
+
+
+  /// \brief Build a new expression that references a declaration.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
   OwningExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier,
                                       SourceRange QualifierRange,
                                       NamedDecl *ND, SourceLocation Loc,
@@ -1449,29 +1451,27 @@
                                                 SourceRange QualifierRange,
                                                 DeclarationName Name,
                                                 SourceLocation Location,
-                                                bool IsAddressOfOperand) {
+                              const TemplateArgumentListInfo *TemplateArgs) {
     CXXScopeSpec SS;
     SS.setRange(QualifierRange);
     SS.setScopeRep(NNS);
-    return getSema().ActOnDeclarationNameExpr(/*Scope=*/0,
-                                              Location,
-                                              Name,
-                                              /*Trailing lparen=*/false,
-                                              &SS,
-                                              IsAddressOfOperand);
+
+    if (TemplateArgs)
+      return getSema().BuildQualifiedTemplateIdExpr(SS, Name, Location,
+                                                    *TemplateArgs);
+
+    return getSema().BuildQualifiedDeclarationNameExpr(SS, Name, Location);
   }
 
   /// \brief Build a new template-id expression.
   ///
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
-  OwningExprResult RebuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
-                                         SourceRange QualifierRange,
-                                         TemplateName Template,
-                                         SourceLocation TemplateLoc,
+  OwningExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                         LookupResult &R,
+                                         bool RequiresADL,
                               const TemplateArgumentListInfo &TemplateArgs) {
-    return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange,
-                                         Template, TemplateLoc, TemplateArgs);
+    return getSema().BuildTemplateIdExpr(SS, R, RequiresADL, TemplateArgs);
   }
 
   /// \brief Build a new object-construction expression.
@@ -1857,20 +1857,8 @@
                                               TransTemplate);
     }
 
-    OverloadedFunctionDecl *Ovl = QTN->getOverloadedFunctionDecl();
-    assert(Ovl && "Not a template name or an overload set?");
-    OverloadedFunctionDecl *TransOvl
-      = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl));
-    if (!TransOvl)
-      return TemplateName();
-
-    if (!getDerived().AlwaysRebuild() &&
-        NNS == QTN->getQualifier() &&
-        TransOvl == Ovl)
-      return Name;
-
-    return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
-                                            TransOvl);
+    // These should be getting filtered out before they make it into the AST.
+    assert(false && "overloaded template name survived to here");
   }
 
   if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
@@ -1906,18 +1894,9 @@
     return TemplateName(TransTemplate);
   }
 
-  OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl();
-  assert(Ovl && "Not a template name or an overload set?");
-  OverloadedFunctionDecl *TransOvl
-    = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl));
-  if (!TransOvl)
-    return TemplateName();
-
-  if (!getDerived().AlwaysRebuild() &&
-      TransOvl == Ovl)
-    return Name;
-
-  return TemplateName(TransOvl);
+  // These should be getting filtered out before they reach the AST.
+  assert(false && "overloaded function decl survived to here");
+  return TemplateName();
 }
 
 template<typename Derived>
@@ -4562,10 +4541,65 @@
 template<typename Derived>
 Sema::OwningExprResult
 TreeTransform<Derived>::TransformUnresolvedLookupExpr(
-                                                  UnresolvedLookupExpr *E,
+                                                  UnresolvedLookupExpr *Old,
                                                   bool isAddressOfOperand) {
-  // There is no transformation we can apply to an unresolved lookup.
-  return SemaRef.Owned(E->Retain());
+  TemporaryBase Rebase(*this, Old->getNameLoc(), DeclarationName());
+
+  LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
+                 Sema::LookupOrdinaryName);
+
+  // Transform all the decls.
+  for (UnresolvedLookupExpr::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);
+  }
+
+  // Resolve a kind, but don't do any further analysis.  If it's
+  // ambiguous, the callee needs to deal with it.
+  R.resolveKind();
+
+  // Rebuild the nested-name qualifier, if present.
+  CXXScopeSpec SS;
+  NestedNameSpecifier *Qualifier = 0;
+  if (Old->getQualifier()) {
+    Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
+                                                    Old->getQualifierRange());
+    if (!Qualifier)
+      return SemaRef.ExprError();
+    
+    SS.setScopeRep(Qualifier);
+    SS.setRange(Old->getQualifierRange());
+  }
+
+  // If we have no template arguments, it's a normal declaration name.
+  if (!Old->hasExplicitTemplateArgs())
+    return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());
+
+  // If we have template arguments, rebuild them, then rebuild the
+  // templateid expression.
+  TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), 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().RebuildTemplateIdExpr(SS, R, Old->requiresADL(),
+                                            TransArgs);
 }
 
 template<typename Derived>
@@ -4609,35 +4643,16 @@
   if (!Name)
     return SemaRef.ExprError();
 
-  if (!getDerived().AlwaysRebuild() &&
-      NNS == E->getQualifier() &&
-      Name == E->getDeclName())
-    return SemaRef.Owned(E->Retain());
+  if (!E->hasExplicitTemplateArgs()) {
+    if (!getDerived().AlwaysRebuild() &&
+        NNS == E->getQualifier() &&
+        Name == E->getDeclName())
+      return SemaRef.Owned(E->Retain());
 
-  return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
-                                                   E->getQualifierRange(),
-                                                   Name,
-                                                   E->getLocation(),
-                                                   isAddressOfOperand);
-}
-
-template<typename Derived>
-Sema::OwningExprResult
-TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E,
-                                                   bool isAddressOfOperand) {
-  TemporaryBase Rebase(*this, E->getTemplateNameLoc(), DeclarationName());
-  
-  TemplateName Template
-    = getDerived().TransformTemplateName(E->getTemplateName());
-  if (Template.isNull())
-    return SemaRef.ExprError();
-
-  NestedNameSpecifier *Qualifier = 0;
-  if (E->getQualifier()) {
-    Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
-                                                      E->getQualifierRange());
-    if (!Qualifier)
-      return SemaRef.ExprError();
+    return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
+                                                         E->getQualifierRange(),
+                                                         Name, E->getLocation(),
+                                                         /*TemplateArgs*/ 0);
   }
 
   TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
@@ -4648,15 +4663,10 @@
     TransArgs.addArgument(Loc);
   }
 
-  // FIXME: Would like to avoid rebuilding if nothing changed, but we can't
-  // compare template arguments (yet).
-
-  // FIXME: It's possible that we'll find out now that the template name
-  // actually refers to a type, in which case the caller is actually dealing
-  // with a functional cast. Give a reasonable error message!
-  return getDerived().RebuildTemplateIdExpr(Qualifier, E->getQualifierRange(),
-                                            Template, E->getTemplateNameLoc(),
-                                            TransArgs);
+  return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
+                                                       E->getQualifierRange(),
+                                                       Name, E->getLocation(),
+                                                       &TransArgs);
 }
 
 template<typename Derived>
@@ -5325,14 +5335,6 @@
 template<typename Derived>
 TemplateName
 TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
-                                            bool TemplateKW,
-                                            OverloadedFunctionDecl *Ovl) {
-  return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, Ovl);
-}
-
-template<typename Derived>
-TemplateName
-TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
                                             const IdentifierInfo &II,
                                             QualType ObjectType) {
   CXXScopeSpec SS;