Improve the representation of template names in the AST. This
representation handles the various ways in which one can name a
template, including unqualified references ("vector"), qualified
references ("std::vector"), and dependent template names
("MetaFun::template apply").

One immediate effect of this change is that the representation of
nested-name-specifiers in type names for class template
specializations (e.g., std::vector<int>) is more accurate. Rather than
representing std::vector<int> as

  std::(vector<int>)

we represent it as

  (std::vector)<int>

which more closely follows the C++ grammar. 

Additionally, templates are no longer represented as declarations
(DeclPtrTy) in Parse-Sema interactions. Instead, I've introduced a new
OpaquePtr type (TemplateTy) that holds the representation of a
TemplateName. This will simplify the handling of dependent
template-names, once we get there.






git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68074 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index f3cf6b1..bb17954 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -483,6 +483,10 @@
     Align = Layout.getAlignment();
     break;
   }
+
+  case Type::TemplateSpecialization:
+    assert(false && "Dependent types have no size");
+    break;
   }
   
   assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
@@ -1358,30 +1362,31 @@
 }
 
 QualType 
-ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
-                                               const TemplateArgument *Args,
-                                               unsigned NumArgs,
-                                               QualType Canon) {
+ASTContext::getTemplateSpecializationType(TemplateName Template,
+                                          const TemplateArgument *Args,
+                                          unsigned NumArgs,
+                                          QualType Canon) {
+  // FIXME: If Template is dependent, canonicalize it!
+
   if (!Canon.isNull())
     Canon = getCanonicalType(Canon);
 
   llvm::FoldingSetNodeID ID;
-  ClassTemplateSpecializationType::Profile(ID, Template, Args, NumArgs);
+  TemplateSpecializationType::Profile(ID, Template, Args, NumArgs);
 
   void *InsertPos = 0;
-  ClassTemplateSpecializationType *Spec
-    = ClassTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+  TemplateSpecializationType *Spec
+    = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
 
   if (Spec)
     return QualType(Spec, 0);
   
-  void *Mem = Allocate((sizeof(ClassTemplateSpecializationType) + 
+  void *Mem = Allocate((sizeof(TemplateSpecializationType) + 
                         sizeof(TemplateArgument) * NumArgs),
                        8);
-  Spec = new (Mem) ClassTemplateSpecializationType(Template, Args, NumArgs, 
-                                                   Canon);
+  Spec = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, Canon);
   Types.push_back(Spec);
-  ClassTemplateSpecializationTypes.InsertNode(Spec, InsertPos);
+  TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
 
   return QualType(Spec, 0);  
 }
@@ -2486,6 +2491,53 @@
   ObjCConstantStringType = getObjCInterfaceType(Decl);
 }
 
+/// \brief Retrieve the template name that represents a qualified
+/// template name such as \c std::vector.
+TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, 
+                                                  bool TemplateKeyword,
+                                                  TemplateDecl *Template) {
+  llvm::FoldingSetNodeID ID;
+  QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
+
+  void *InsertPos = 0;
+  QualifiedTemplateName *QTN =
+    QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+  if (!QTN) {
+    QTN = new (*this,4) QualifiedTemplateName(NNS, TemplateKeyword, Template);
+    QualifiedTemplateNames.InsertNode(QTN, InsertPos);
+  }
+
+  return TemplateName(QTN);
+}
+
+/// \brief Retrieve the template name that represents a dependent
+/// 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");
+
+  llvm::FoldingSetNodeID ID;
+  DependentTemplateName::Profile(ID, NNS, Name);
+
+  void *InsertPos = 0;
+  DependentTemplateName *QTN =
+    DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+
+  if (QTN)
+    return TemplateName(QTN);
+
+  NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+  if (CanonNNS == NNS) {
+    QTN = new (*this,4) DependentTemplateName(NNS, Name);
+  } else {
+    TemplateName Canon = getDependentTemplateName(CanonNNS, Name);
+    QTN = new (*this,4) DependentTemplateName(NNS, Name, Canon);
+  }
+
+  DependentTemplateNames.InsertNode(QTN, InsertPos);
+  return TemplateName(QTN);
+}
+
 /// getFromTargetType - Given one of the integer types provided by
 /// TargetInfo, produce the corresponding type. The unsigned @p Type
 /// is actually a value of type @c TargetInfo::IntType.
@@ -3033,6 +3085,10 @@
     ResultType.setCVRQualifiers(LHSCan.getCVRQualifiers());
     return ResultType;
 #endif
+
+  case Type::TemplateSpecialization:
+    assert(false && "Dependent types have no size");
+    break;
   }
 
   return QualType();
diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp
new file mode 100644
index 0000000..4e54fe4
--- /dev/null
+++ b/lib/AST/TemplateName.cpp
@@ -0,0 +1,54 @@
+//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the TemplateName interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+TemplateDecl *TemplateName::getAsTemplateDecl() const {
+  if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
+    return Template;
+  
+  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
+    return QTN->getTemplateDecl();
+
+  return 0;
+}
+
+bool TemplateName::isDependent() const {
+  if (TemplateDecl *Template = getAsTemplateDecl()) {
+    // FIXME: We don't yet have a notion of dependent
+    // declarations. When we do, check that. This hack won't last
+    // long!.
+    return isa<TemplateTemplateParmDecl>(Template);
+  }
+
+  return true;
+}
+
+void TemplateName::Print(llvm::raw_ostream &OS) const {
+  if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
+    OS << Template->getIdentifier()->getName();
+  else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
+    QTN->getQualifier()->Print(OS);
+    if (QTN->hasTemplateKeyword())
+      OS << "template ";
+    OS << QTN->getTemplateDecl()->getIdentifier()->getName();
+  } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
+    DTN->getQualifier()->Print(OS);
+    OS << "template ";
+    OS << DTN->getName()->getName();
+  }
+}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 0a3e8f9..6922dcc 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -93,8 +93,8 @@
     return TOE->getUnderlyingExpr()->getType().getDesugaredType();
   if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this))
     return TOT->getUnderlyingType().getDesugaredType();
-  if (const ClassTemplateSpecializationType *Spec 
-        = dyn_cast<ClassTemplateSpecializationType>(this))
+  if (const TemplateSpecializationType *Spec 
+        = dyn_cast<TemplateSpecializationType>(this))
     return Spec->getCanonicalTypeInternal().getDesugaredType();
   if (const QualifiedNameType *QualName  = dyn_cast<QualifiedNameType>(this))
     return QualName->getNamedType().getDesugaredType();
@@ -549,11 +549,11 @@
   return dyn_cast<TemplateTypeParmType>(CanonicalType);
 }
 
-const ClassTemplateSpecializationType *
-Type::getAsClassTemplateSpecializationType() const {
+const TemplateSpecializationType *
+Type::getAsTemplateSpecializationType() const {
   // There is no sugar for class template specialization types, so
   // just return the canonical type pointer if it is the right class.
-  return dyn_cast<ClassTemplateSpecializationType>(CanonicalType);
+  return dyn_cast<TemplateSpecializationType>(CanonicalType);
 }
 
 bool Type::isIntegerType() const {
@@ -972,7 +972,7 @@
 }
 
 bool 
-ClassTemplateSpecializationType::
+TemplateSpecializationType::
 anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
   for (unsigned Idx = 0; Idx < NumArgs; ++Idx) {
     switch (Args[Idx].getKind()) {
@@ -997,17 +997,16 @@
   return false;
 }
 
-ClassTemplateSpecializationType::
-ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args,
-                                unsigned NumArgs, QualType Canon)
-  : Type(ClassTemplateSpecialization, 
+TemplateSpecializationType::
+TemplateSpecializationType(TemplateName T, const TemplateArgument *Args,
+                           unsigned NumArgs, QualType Canon)
+  : Type(TemplateSpecialization, 
          Canon.isNull()? QualType(this, 0) : Canon,
-         /*FIXME: Check for dependent template */
-         anyDependentTemplateArguments(Args, NumArgs)),
+         T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)),
     Template(T), NumArgs(NumArgs)
 {
   assert((!Canon.isNull() || 
-          anyDependentTemplateArguments(Args, NumArgs)) &&
+          T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) &&
          "No canonical type for non-dependent class template specialization");
 
   TemplateArgument *TemplateArgs 
@@ -1016,7 +1015,7 @@
     new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
 }
 
-void ClassTemplateSpecializationType::Destroy(ASTContext& C) {
+void TemplateSpecializationType::Destroy(ASTContext& C) {
   for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
     // FIXME: Not all expressions get cloned, so we can't yet perform
     // this destruction.
@@ -1025,24 +1024,23 @@
   }
 }
 
-ClassTemplateSpecializationType::iterator
-ClassTemplateSpecializationType::end() const {
+TemplateSpecializationType::iterator
+TemplateSpecializationType::end() const {
   return begin() + getNumArgs();
 }
 
 const TemplateArgument &
-ClassTemplateSpecializationType::getArg(unsigned Idx) const {
+TemplateSpecializationType::getArg(unsigned Idx) const {
   assert(Idx < getNumArgs() && "Template argument out of range");
   return getArgs()[Idx];
 }
 
 void 
-ClassTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, 
-                                         TemplateDecl *T, 
-                                         const TemplateArgument *Args, 
-                                         unsigned NumArgs) {
-  ID.AddPointer(T);
-
+TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, 
+                                    TemplateName T, 
+                                    const TemplateArgument *Args, 
+                                    unsigned NumArgs) {
+  T.Profile(ID);
   for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
     Args[Idx].Profile(ID);
 }
@@ -1351,7 +1349,7 @@
     InnerString = Name->getName() + InnerString;
 }
 
-std::string ClassTemplateSpecializationType::PrintTemplateArgumentList(
+std::string TemplateSpecializationType::PrintTemplateArgumentList(
                                               const TemplateArgument *Args,
                                               unsigned NumArgs) {
   std::string SpecString;
@@ -1403,9 +1401,15 @@
 }
 
 void 
-ClassTemplateSpecializationType::
+TemplateSpecializationType::
 getAsStringInternal(std::string &InnerString) const {
-  std::string SpecString = Template->getNameAsString();
+  std::string SpecString;
+
+  {
+    llvm::raw_string_ostream OS(SpecString);
+    Template.Print(OS);
+  }
+
   SpecString += PrintTemplateArgumentList(getArgs(), getNumArgs());
   if (InnerString.empty())
     InnerString.swap(SpecString);
@@ -1515,7 +1519,7 @@
   if (ClassTemplateSpecializationDecl *Spec 
         = dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
     std::string TemplateArgs 
-      = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+      = TemplateSpecializationType::PrintTemplateArgumentList(
                                                   Spec->getTemplateArgs(),
                                                   Spec->getNumTemplateArgs());
     InnerString = TemplateArgs + InnerString;
@@ -1534,7 +1538,7 @@
       } else if (ClassTemplateSpecializationDecl *Spec 
                    = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
         std::string TemplateArgs 
-          = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+          = TemplateSpecializationType::PrintTemplateArgumentList(
                                                   Spec->getTemplateArgs(),
                                                   Spec->getNumTemplateArgs());
         MyPart = Spec->getIdentifier()->getName() + TemplateArgs;
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index 4f0334f..0562416 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -391,29 +391,17 @@
 }
 
 //===----------------------------------------------------------------------===//
-// ClassTemplateSpecializationType
+// TemplateSpecializationType
 //===----------------------------------------------------------------------===//
 
-void ClassTemplateSpecializationType::EmitImpl(Serializer& S) const {
-  S.Emit(getCanonicalTypeInternal());
-  S.EmitPtr(Template);
-  S.EmitInt(NumArgs);
-  // FIXME: Serialize class template specialization types
+void TemplateSpecializationType::EmitImpl(Serializer& S) const {
+  // FIXME: Serialization support
 }
 
 Type* 
-ClassTemplateSpecializationType::
+TemplateSpecializationType::
 CreateImpl(ASTContext& Context, Deserializer& D) {
-  llvm::SmallVector<uintptr_t, 16> Args;
-  llvm::SmallVector<bool, 16> ArgIsType;
-
-  QualType Canon = QualType::ReadVal(D);
-  TemplateDecl *Template = cast<TemplateDecl>(D.ReadPtr<Decl>());
-  unsigned NumArgs = D.ReadInt();
-
-  // FIXME: De-serialize class template specialization types
-  (void)Template;
-  (void)NumArgs;
+  // FIXME: Deserialization support
   return 0;
 }