Initial stab at implement dependent member references to member
templates, e.g.,
  
  x.template get<T>

We can now parse these, represent them within an UnresolvedMemberExpr
expression, then instantiate that expression node in simple cases.

This allows us to stumble through parsing LLVM's Casting.h.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81300 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 780b1fd..30e4234 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3319,7 +3319,8 @@
 /// template name such as \c MetaFun::template apply.
 TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, 
                                                   const IdentifierInfo *Name) {
-  assert(NNS->isDependent() && "Nested name specifier must be dependent");
+  assert((!NNS || NNS->isDependent()) && 
+         "Nested name specifier must be dependent");
 
   llvm::FoldingSetNodeID ID;
   DependentTemplateName::Profile(ID, NNS, Name);
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 86c5227..7c36caa 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -523,6 +523,77 @@
   return child_iterator(reinterpret_cast<Stmt **>(this + 1) + NumArgs);
 }
 
+CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C, 
+                                                 Expr *Base, bool IsArrow, 
+                                                 SourceLocation OperatorLoc,
+                                                 NestedNameSpecifier *Qualifier,
+                                                 SourceRange QualifierRange,
+                                          NamedDecl *FirstQualifierFoundInScope,
+                                                 DeclarationName Member,
+                                                 SourceLocation MemberLoc,
+                                                 bool HasExplicitTemplateArgs,
+                                                 SourceLocation LAngleLoc,
+                                           const TemplateArgument *TemplateArgs,
+                                                 unsigned NumTemplateArgs,
+                                                 SourceLocation RAngleLoc)
+  : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
+    Base(Base), IsArrow(IsArrow), 
+    HasExplicitTemplateArgumentList(HasExplicitTemplateArgs),
+    OperatorLoc(OperatorLoc),
+    Qualifier(Qualifier), QualifierRange(QualifierRange),
+    FirstQualifierFoundInScope(FirstQualifierFoundInScope),
+    Member(Member), MemberLoc(MemberLoc)
+{
+  if (HasExplicitTemplateArgumentList) {
+    ExplicitTemplateArgumentList *ETemplateArgs 
+      = getExplicitTemplateArgumentList();
+    ETemplateArgs->LAngleLoc = LAngleLoc;
+    ETemplateArgs->RAngleLoc = RAngleLoc;
+    ETemplateArgs->NumTemplateArgs = NumTemplateArgs;
+    
+    TemplateArgument *SavedTemplateArgs = ETemplateArgs->getTemplateArgs();
+    for (unsigned I = 0; I < NumTemplateArgs; ++I)
+      new (SavedTemplateArgs + I) TemplateArgument(TemplateArgs[I]);            
+  }
+}
+
+CXXUnresolvedMemberExpr *
+CXXUnresolvedMemberExpr::Create(ASTContext &C, 
+                                Expr *Base, bool IsArrow, 
+                                SourceLocation OperatorLoc,
+                                NestedNameSpecifier *Qualifier,
+                                SourceRange QualifierRange,
+                                NamedDecl *FirstQualifierFoundInScope,
+                                DeclarationName Member,
+                                SourceLocation MemberLoc,
+                                bool HasExplicitTemplateArgs,
+                                SourceLocation LAngleLoc,
+                                const TemplateArgument *TemplateArgs,
+                                unsigned NumTemplateArgs,
+                                SourceLocation RAngleLoc)
+{
+  if (!HasExplicitTemplateArgs)
+    return new (C) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc,
+                                           Qualifier, QualifierRange,
+                                           FirstQualifierFoundInScope,
+                                           Member, MemberLoc);
+  
+  void *Mem = C.Allocate(sizeof(CXXUnresolvedMemberExpr) +
+                         sizeof(ExplicitTemplateArgumentList) + 
+                         sizeof(TemplateArgument) * NumTemplateArgs,
+                         llvm::alignof<CXXUnresolvedMemberExpr>());
+  return new (Mem) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc,
+                                           Qualifier, QualifierRange,
+                                           FirstQualifierFoundInScope,
+                                           Member,
+                                           MemberLoc,
+                                           HasExplicitTemplateArgs,
+                                           LAngleLoc,
+                                           TemplateArgs,
+                                           NumTemplateArgs,
+                                           RAngleLoc);
+}
+
 Stmt::child_iterator CXXUnresolvedMemberExpr::child_begin() {
   return child_iterator(&Base);
 }
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index 24fb752..2ed8eb0 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -42,7 +42,7 @@
 NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix, 
                             IdentifierInfo *II) {
   assert(II && "Identifier cannot be NULL");
-  assert(Prefix && Prefix->isDependent() && "Prefix must be dependent");
+  assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
 
   NestedNameSpecifier Mockup;
   Mockup.Prefix.setPointer(Prefix);
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 317486c..7a0d6d6 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -493,12 +493,10 @@
   if (Node->getQualifier())
     Node->getQualifier()->print(OS, Policy);
   Node->getTemplateName().print(OS, Policy, true);
-  OS << '<';
   OS << TemplateSpecializationType::PrintTemplateArgumentList(
                                                       Node->getTemplateArgs(),
                                                    Node->getNumTemplateArgs(),
                                                               Policy);
-  OS << '>';
 }
 
 void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
@@ -1154,7 +1152,18 @@
   OS << (Node->isArrow() ? "->" : ".");
   if (NestedNameSpecifier *Qualifier = Node->getQualifier())
     Qualifier->print(OS, Policy);
+  else if (Node->hasExplicitTemplateArgumentList())
+    // FIXME: Track use of "template" keyword explicitly?
+    OS << "template ";
+  
   OS << Node->getMember().getAsString();
+  
+  if (Node->hasExplicitTemplateArgumentList()) {
+    OS << TemplateSpecializationType::PrintTemplateArgumentList(
+                                                    Node->getTemplateArgs(),
+                                                    Node->getNumTemplateArgs(),
+                                                    Policy);
+  }
 }
 
 static const char *getTypeTraitName(UnaryTypeTrait UTT) {
diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp
index 3913121..92c741b 100644
--- a/lib/AST/TemplateName.cpp
+++ b/lib/AST/TemplateName.cpp
@@ -67,7 +67,7 @@
       OS << "template ";
     OS << QTN->getDecl()->getNameAsString();
   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
-    if (!SuppressNNS)
+    if (!SuppressNNS && DTN->getQualifier())
       DTN->getQualifier()->print(OS, Policy);
     OS << "template ";
     // FIXME: Shouldn't we have a more general kind of name?