Added source location for the template keyword in AST template-id expressions.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149127 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index f6c0ae2..87c392f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -3939,11 +3939,13 @@
       else
         AllowConstructorName = (D.getContext() == Declarator::MemberContext);
 
+      SourceLocation TemplateKWLoc;
       if (ParseUnqualifiedId(D.getCXXScopeSpec(), 
                              /*EnteringContext=*/true, 
                              /*AllowDestructorName=*/true, 
                              AllowConstructorName,
                              ParsedType(),
+                             TemplateKWLoc,
                              D.getName()) ||
           // Once we're past the identifier, if the scope was bad, mark the
           // whole declarator bad.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 92a501a..d102fb3 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -461,12 +461,14 @@
   // Parse the unqualified-id. We allow parsing of both constructor and
   // destructor names and allow the action module to diagnose any semantic
   // errors.
+  SourceLocation TemplateKWLoc;
   UnqualifiedId Name;
   if (ParseUnqualifiedId(SS,
                          /*EnteringContext=*/false,
                          /*AllowDestructorName=*/true,
                          /*AllowConstructorName=*/true,
                          ParsedType(),
+                         TemplateKWLoc,
                          Name)) {
     SkipUntil(tok::semi);
     return 0;
@@ -835,8 +837,8 @@
     TemplateName.setIdentifier(Id, IdLoc);
 
     // Parse the full template-id, then turn it into a type.
-    if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
-                                SourceLocation(), true))
+    if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
+                                TemplateName, true))
       return true;
     if (TNK == TNK_Dependent_template_name)
       AnnotateTemplateIdTokenAsType();
@@ -1692,8 +1694,10 @@
                                      /*EnteringContext=*/false);
 
       // Try to parse an unqualified-id.
+      SourceLocation TemplateKWLoc;
       UnqualifiedId Name;
-      if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) {
+      if (ParseUnqualifiedId(SS, false, true, true, ParsedType(),
+                             TemplateKWLoc, Name)) {
         SkipUntil(tok::semi);
         return;
       }
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 22c5841..3f80309 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -795,12 +795,13 @@
     // not.
     UnqualifiedId Name;
     CXXScopeSpec ScopeSpec;
+    SourceLocation TemplateKWLoc;
     CastExpressionIdValidator Validator(isTypeCast != NotTypeCast,
                                         isTypeCast != IsTypeCast);
     Name.setIdentifier(&II, ILoc);
-    Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, Name, 
-                                    Tok.is(tok::l_paren), isAddressOfOperand,
-                                    &Validator);
+    Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc,
+                                    Name, Tok.is(tok::l_paren),
+                                    isAddressOfOperand, &Validator);
     break;
   }
   case tok::char_constant:     // constant: character-constant
@@ -1403,19 +1404,19 @@
       // names a real destructor.
       // Allow explicit constructor calls in Microsoft mode.
       // FIXME: Add support for explicit call of template constructor.
+      SourceLocation TemplateKWLoc;
       UnqualifiedId Name;
       if (ParseUnqualifiedId(SS, 
                              /*EnteringContext=*/false, 
                              /*AllowDestructorName=*/true,
                              /*AllowConstructorName=*/ getLang().MicrosoftExt, 
-                             ObjectType,
-                             Name))
+                             ObjectType, TemplateKWLoc, Name))
         LHS = ExprError();
       
       if (!LHS.isInvalid())
         LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.take(), OpLoc, 
-                                            OpKind, SS, Name, ObjCImpDecl,
-                                            Tok.is(tok::l_paren));
+                                            OpKind, SS, TemplateKWLoc, Name,
+                                            ObjCImpDecl, Tok.is(tok::l_paren));
       break;
     }
     case tok::plusplus:    // postfix-expression: postfix-expression '++'
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index d35203e..2f37383 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -264,15 +264,13 @@
       // Commit to parsing the template-id.
       TPA.Commit();
       TemplateTy Template;
-      if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(getCurScope(), 
-                                                                TemplateKWLoc, 
-                                                                    SS, 
-                                                                  TemplateName,
-                                                                    ObjectType, 
-                                                                EnteringContext,
-                                                                    Template)) {
-        if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, 
-                                    TemplateKWLoc, false))
+      if (TemplateNameKind TNK
+          = Actions.ActOnDependentTemplateName(getCurScope(),
+                                               SS, TemplateKWLoc, TemplateName,
+                                               ObjectType, EnteringContext,
+                                               Template)) {
+        if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateKWLoc,
+                                    TemplateName, false))
           return true;
       } else
         return true;
@@ -307,8 +305,8 @@
                                          TemplateId->NumArgs);
       
       if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(),
-                                              /*FIXME:*/SourceLocation(),
-                                              SS, 
+                                              SS,
+                                              TemplateId->TemplateKWLoc,
                                               TemplateId->Template,
                                               TemplateId->TemplateNameLoc,
                                               TemplateId->LAngleLoc,
@@ -404,8 +402,8 @@
         // specializations) still want to see the original template-id
         // token.
         ConsumeToken();
-        if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, 
-                                    SourceLocation(), false))
+        if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
+                                    TemplateName, false))
           return true;
         continue;
       } 
@@ -426,14 +424,14 @@
         
         if (TemplateNameKind TNK 
               = Actions.ActOnDependentTemplateName(getCurScope(), 
-                                                   Tok.getLocation(), SS, 
+                                                   SS, SourceLocation(),
                                                    TemplateName, ObjectType,
                                                    EnteringContext, Template)) {
           // Consume the identifier.
           ConsumeToken();
-          if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, 
-                                      SourceLocation(), false))
-            return true;                
+          if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
+                                      TemplateName, false))
+            return true;
         }
         else
           return true;     
@@ -505,13 +503,15 @@
   //
   CXXScopeSpec SS;
   ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
-  
+
+  SourceLocation TemplateKWLoc;
   UnqualifiedId Name;
-  if (ParseUnqualifiedId(SS, 
-                         /*EnteringContext=*/false, 
-                         /*AllowDestructorName=*/false, 
-                         /*AllowConstructorName=*/false, 
+  if (ParseUnqualifiedId(SS,
+                         /*EnteringContext=*/false,
+                         /*AllowDestructorName=*/false,
+                         /*AllowConstructorName=*/false,
                          /*ObjectType=*/ ParsedType(),
+                         TemplateKWLoc,
                          Name))
     return ExprError();
 
@@ -519,10 +519,9 @@
   // followed by a postfix-expression suffix.
   if (isAddressOfOperand && isPostfixExpressionSuffixStart())
     isAddressOfOperand = false;
-  
-  return Actions.ActOnIdExpression(getCurScope(), SS, Name, Tok.is(tok::l_paren),
-                                   isAddressOfOperand);
-  
+
+  return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name,
+                                   Tok.is(tok::l_paren), isAddressOfOperand);
 }
 
 /// ParseLambdaExpression - Parse a C++0x lambda expression.
@@ -1030,6 +1029,8 @@
     assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
     CCLoc = ConsumeToken();
   } else if (Tok.is(tok::annot_template_id)) {
+    // FIXME: retrieve TemplateKWLoc from template-id annotation and
+    // store it in the pseudo-dtor node (to be used when instantiating it).
     FirstTypeName.setTemplateId(
                               (TemplateIdAnnotation *)Tok.getAnnotationValue());
     ConsumeToken();
@@ -1067,9 +1068,10 @@
   // If there is a '<', the second type name is a template-id. Parse
   // it as such.
   if (Tok.is(tok::less) &&
-      ParseUnqualifiedIdTemplateId(SS, Name, NameLoc, false, ObjectType,
-                                   SecondTypeName, /*AssumeTemplateName=*/true,
-                                   /*TemplateKWLoc*/SourceLocation()))
+      ParseUnqualifiedIdTemplateId(SS, SourceLocation(),
+                                   Name, NameLoc,
+                                   false, ObjectType, SecondTypeName,
+                                   /*AssumeTemplateName=*/true))
     return ExprError();
 
   return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base,
@@ -1502,13 +1504,13 @@
 ///
 /// \returns true if a parse error occurred, false otherwise.
 bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+                                          SourceLocation TemplateKWLoc,
                                           IdentifierInfo *Name,
                                           SourceLocation NameLoc,
                                           bool EnteringContext,
                                           ParsedType ObjectType,
                                           UnqualifiedId &Id,
-                                          bool AssumeTemplateId,
-                                          SourceLocation TemplateKWLoc) {
+                                          bool AssumeTemplateId) {
   assert((AssumeTemplateId || Tok.is(tok::less)) &&
          "Expected '<' to finish parsing a template-id");
   
@@ -1519,7 +1521,7 @@
   case UnqualifiedId::IK_OperatorFunctionId:
   case UnqualifiedId::IK_LiteralOperatorId:
     if (AssumeTemplateId) {
-      TNK = Actions.ActOnDependentTemplateName(getCurScope(), TemplateKWLoc, SS, 
+      TNK = Actions.ActOnDependentTemplateName(getCurScope(), SS, TemplateKWLoc,
                                                Id, ObjectType, EnteringContext,
                                                Template);
       if (TNK == TNK_Non_template)
@@ -1550,9 +1552,10 @@
         Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword)
           << Name
           << FixItHint::CreateInsertion(Id.StartLocation, "template ");
-        TNK = Actions.ActOnDependentTemplateName(getCurScope(), TemplateKWLoc,
-                                                 SS, Id, ObjectType,
-                                                 EnteringContext, Template);
+        TNK = Actions.ActOnDependentTemplateName(getCurScope(),
+                                                 SS, TemplateKWLoc, Id,
+                                                 ObjectType, EnteringContext,
+                                                 Template);
         if (TNK == TNK_Non_template)
           return true;              
       }
@@ -1575,9 +1578,10 @@
     bool MemberOfUnknownSpecialization;
     TemplateName.setIdentifier(Name, NameLoc);
     if (ObjectType) {
-      TNK = Actions.ActOnDependentTemplateName(getCurScope(), TemplateKWLoc, SS, 
-                                               TemplateName, ObjectType,
-                                               EnteringContext, Template);
+      TNK = Actions.ActOnDependentTemplateName(getCurScope(),
+                                               SS, TemplateKWLoc, TemplateName,
+                                               ObjectType, EnteringContext,
+                                               Template);
       if (TNK == TNK_Non_template)
         return true;
     } else {
@@ -1880,12 +1884,12 @@
                                 bool AllowDestructorName,
                                 bool AllowConstructorName,
                                 ParsedType ObjectType,
+                                SourceLocation& TemplateKWLoc,
                                 UnqualifiedId &Result) {
 
   // Handle 'A::template B'. This is for template-ids which have not
   // already been annotated by ParseOptionalCXXScopeSpecifier().
   bool TemplateSpecified = false;
-  SourceLocation TemplateKWLoc;
   if (getLang().CPlusPlus && Tok.is(tok::kw_template) &&
       (ObjectType || SS.isSet())) {
     TemplateSpecified = true;
@@ -1923,9 +1927,9 @@
 
     // If the next token is a '<', we may have a template.
     if (TemplateSpecified || Tok.is(tok::less))
-      return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext, 
-                                          ObjectType, Result,
-                                          TemplateSpecified, TemplateKWLoc);
+      return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, Id, IdLoc,
+                                          EnteringContext, ObjectType,
+                                          Result, TemplateSpecified);
     
     return false;
   }
@@ -1969,6 +1973,7 @@
     // We have already parsed a template-id; consume the annotation token as
     // our unqualified-id.
     Result.setTemplateId(TemplateId);
+    TemplateKWLoc = TemplateId->TemplateKWLoc;
     ConsumeToken();
     return false;
   }
@@ -1988,10 +1993,10 @@
     if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
          Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
         (TemplateSpecified || Tok.is(tok::less)))
-      return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(), 
-                                          EnteringContext, ObjectType, 
-                                          Result,
-                                          TemplateSpecified, TemplateKWLoc);
+      return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
+                                          0, SourceLocation(),
+                                          EnteringContext, ObjectType,
+                                          Result, TemplateSpecified);
     
     return false;
   }
@@ -2028,9 +2033,10 @@
     
     if (TemplateSpecified || Tok.is(tok::less)) {
       Result.setDestructorName(TildeLoc, ParsedType(), ClassNameLoc);
-      return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
-                                          EnteringContext, ObjectType, Result,
-                                          TemplateSpecified, TemplateKWLoc);
+      return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc,
+                                          ClassName, ClassNameLoc,
+                                          EnteringContext, ObjectType,
+                                          Result, TemplateSpecified);
     }
     
     // Note that this is a destructor name.
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index cd467dd..aa9ba06 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -171,7 +171,7 @@
         if (AnnotateTemplateIdToken(
                             TemplateTy::make(Classification.getTemplateName()),
                                     Classification.getTemplateNameKind(),
-                                    SS, Id, SourceLocation(),
+                                    SS, SourceLocation(), Id,
                                     /*AllowTypeAnnotation=*/false)) {
           // Handle errors here by skipping up to the next semicolon or '}', and
           // eat the semicolon if that's what stopped us.
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 4f2f49c..04050c0 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -765,8 +765,8 @@
 ///
 bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
                                      CXXScopeSpec &SS,
-                                     UnqualifiedId &TemplateName,
                                      SourceLocation TemplateKWLoc,
+                                     UnqualifiedId &TemplateName,
                                      bool AllowTypeAnnotation) {
   assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
   assert(Template && Tok.is(tok::less) &&
@@ -833,6 +833,7 @@
       TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
     }
     TemplateId->SS = SS;
+    TemplateId->TemplateKWLoc = TemplateKWLoc;
     TemplateId->Template = Template;
     TemplateId->Kind = TNK;
     TemplateId->LAngleLoc = LAngleLoc;
@@ -927,7 +928,7 @@
   if (SS.isSet() && Tok.is(tok::kw_template)) {
     // Parse the optional 'template' keyword following the 
     // nested-name-specifier.
-    SourceLocation TemplateLoc = ConsumeToken();
+    SourceLocation TemplateKWLoc = ConsumeToken();
     
     if (Tok.is(tok::identifier)) {
       // We appear to have a dependent template name.
@@ -944,8 +945,8 @@
       // template argument.
       TemplateTy Template;
       if (isEndOfTemplateArgument(Tok) &&
-          Actions.ActOnDependentTemplateName(getCurScope(), TemplateLoc,
-                                             SS, Name, 
+          Actions.ActOnDependentTemplateName(getCurScope(),
+                                             SS, TemplateKWLoc, Name,
                                              /*ObjectType=*/ ParsedType(),
                                              /*EnteringContext=*/false,
                                              Template))
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index da1424c..5afb0fd 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1320,7 +1320,8 @@
                                    Template, MemberOfUnknownSpecialization)) {
         // Consume the identifier.
         ConsumeToken();
-        if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName)) {
+        if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
+                                    TemplateName)) {
           // If an unrecoverable error occurred, we need to return true here,
           // because the token stream is in a damaged state.  We may not return
           // a valid identifier.
@@ -1514,9 +1515,10 @@
     return true;
   }
 
-  // Parse the unqualified-id. 
-  if (ParseUnqualifiedId(Result.SS, false, true, true, ParsedType(), 
-                         Result.Name)) {
+  // Parse the unqualified-id.
+  SourceLocation TemplateKWLoc; // FIXME: parsed, but unused.
+  if (ParseUnqualifiedId(Result.SS, false, true, true, ParsedType(),
+                         TemplateKWLoc, Result.Name)) {
     T.skipToEnd();
     return true;
   }