When building and instantiating a template-id reference expression, such as

  N::f<int>

keep track of the full nested-name-specifier. This is mainly QoI and
relatively hard to test; will try to come up with a printing-based
test once we also retain the explicit template arguments past overload
resolution.

llvm-svn: 84869
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index e636563..074a6fc 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -2529,14 +2529,17 @@
                                             DeclSpec::TST TagSpec,
                                             SourceLocation TagLoc);
 
-  OwningExprResult BuildTemplateIdExpr(TemplateName Template,
+  OwningExprResult BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
+                                       SourceRange QualifierRange,
+                                       TemplateName Template,
                                        SourceLocation TemplateNameLoc,
                                        SourceLocation LAngleLoc,
                                        const TemplateArgument *TemplateArgs,
                                        unsigned NumTemplateArgs,
                                        SourceLocation RAngleLoc);
 
-  virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template,
+  virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
+                                               TemplateTy Template,
                                                SourceLocation TemplateNameLoc,
                                                SourceLocation LAngleLoc,
                                                ASTTemplateArgsPtr TemplateArgs,
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index c691cd9..0f22320 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1251,7 +1251,9 @@
   return ElabType.getAsOpaquePtr();
 }
 
-Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template,
+Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
+                                                 SourceRange QualifierRange,
+                                                 TemplateName Template,
                                                  SourceLocation TemplateNameLoc,
                                                  SourceLocation LAngleLoc,
                                            const TemplateArgument *TemplateArgs,
@@ -1267,28 +1269,30 @@
   if (!D)
     D = Template.getAsOverloadedFunctionDecl();
   
+  CXXScopeSpec SS;
+  SS.setRange(QualifierRange);
+  SS.setScopeRep(Qualifier);
   QualType ThisType, MemberType;
-  if (D && isImplicitMemberReference(/*FIXME:??*/0, D, TemplateNameLoc, 
+  if (D && isImplicitMemberReference(&SS, D, TemplateNameLoc, 
                                      ThisType, MemberType)) {
     Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType);
     return Owned(MemberExpr::Create(Context, This, true,
-                                    /*FIXME:*/0, /*FIXME:*/SourceRange(),
+                                    Qualifier, QualifierRange,
                                     D, TemplateNameLoc, true,
                                     LAngleLoc, TemplateArgs,
                                     NumTemplateArgs, RAngleLoc,
                                     Context.OverloadTy));
   }
   
-  return Owned(TemplateIdRefExpr::Create(Context,
-                                         /*FIXME: New type?*/Context.OverloadTy,
-                                         /*FIXME: Necessary?*/0,
-                                         /*FIXME: Necessary?*/SourceRange(),
+  return Owned(TemplateIdRefExpr::Create(Context, Context.OverloadTy,
+                                         Qualifier, QualifierRange,
                                          Template, TemplateNameLoc, LAngleLoc,
                                          TemplateArgs,
                                          NumTemplateArgs, RAngleLoc));
 }
 
-Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD,
+Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
+                                                 TemplateTy TemplateD,
                                                  SourceLocation TemplateNameLoc,
                                                  SourceLocation LAngleLoc,
                                               ASTTemplateArgsPtr TemplateArgsIn,
@@ -1301,7 +1305,9 @@
   translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
   TemplateArgsIn.release();
 
-  return BuildTemplateIdExpr(Template, TemplateNameLoc, LAngleLoc,
+  return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
+                             SS.getRange(),
+                             Template, TemplateNameLoc, LAngleLoc,
                              TemplateArgs.data(), TemplateArgs.size(),
                              RAngleLoc);
 }
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 53aef9f..5f06ce5 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1445,13 +1445,16 @@
   ///
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
-  OwningExprResult RebuildTemplateIdExpr(TemplateName Template,
+  OwningExprResult RebuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
+                                         SourceRange QualifierRange,
+                                         TemplateName Template,
                                          SourceLocation TemplateLoc,
                                          SourceLocation LAngleLoc,
                                          TemplateArgument *TemplateArgs,
                                          unsigned NumTemplateArgs,
                                          SourceLocation RAngleLoc) {
-    return getSema().BuildTemplateIdExpr(Template, TemplateLoc,
+    return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange,
+                                         Template, TemplateLoc,
                                          LAngleLoc,
                                          TemplateArgs, NumTemplateArgs,
                                          RAngleLoc);
@@ -4369,8 +4372,8 @@
 TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(
                                                     UnresolvedDeclRefExpr *E) {
   NestedNameSpecifier *NNS
-  = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
-                                              E->getQualifierRange());
+    = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+                                                E->getQualifierRange());
   if (!NNS)
     return SemaRef.ExprError();
 
@@ -4399,6 +4402,14 @@
   if (Template.isNull())
     return SemaRef.ExprError();
 
+  NestedNameSpecifier *Qualifier = 0;
+  if (E->getQualifier()) {
+    Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+                                                      E->getQualifierRange());
+    if (!Qualifier)
+      return SemaRef.ExprError();
+  }
+  
   llvm::SmallVector<TemplateArgument, 4> TransArgs;
   for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
     TemplateArgument TransArg
@@ -4415,7 +4426,8 @@
   // 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(Template, E->getTemplateNameLoc(),
+  return getDerived().RebuildTemplateIdExpr(Qualifier, E->getQualifierRange(),
+                                            Template, E->getTemplateNameLoc(),
                                             E->getLAngleLoc(),
                                             TransArgs.data(),
                                             TransArgs.size(),