Start processing template-ids as types when the template-name refers
to a class template. For example, the template-id 'vector<int>' now
has a nice, sugary type in the type system. What we can do now:

  - Parse template-ids like 'vector<int>' (where 'vector' names a
    class template) and form proper types for them in the type system.
  - Parse icky template-ids like 'A<5>' and 'A<(5 > 0)>' properly,
    using (sadly) a bool in the parser to tell it whether '>' should
    be treated as an operator or not.

This is a baby-step, with major problems and limitations:
  - There are currently two ways that we handle template arguments
  (whether they are types or expressions). These will be merged, and,
  most likely, TemplateArg will disappear.
  - We don't have any notion of the declaration of class template
  specializations or of template instantiations, so all template-ids
  are fancy names for 'int' :)



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64153 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 6c5f90a..6b6a501 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -25,38 +25,43 @@
 /// declaration if II names a template. An optional CXXScope can be
 /// passed to indicate the C++ scope in which the identifier will be
 /// found. 
-Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S,
-                                   const CXXScopeSpec *SS) {
-  DeclContext *DC = 0;
-  
-  if (SS) {
-    if (SS->isInvalid())
-      return 0;
-    DC = static_cast<DeclContext*>(SS->getScopeRep());
-  }
+Sema::TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S,
+                                            DeclTy *&Template,
+                                            const CXXScopeSpec *SS) {
   NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName);
 
   if (IIDecl) {
-    // FIXME: We need to represent templates via some kind of
-    // TemplateDecl, because what follows is a hack that only works in
-    // one specific case.
-    if (isa<TemplateDecl>(IIDecl))
-      return IIDecl;
+    if (isa<TemplateDecl>(IIDecl)) {
+      Template = IIDecl;
+      if (isa<FunctionTemplateDecl>(IIDecl))
+        return TNK_Function_template;
+      else if (isa<ClassTemplateDecl>(IIDecl))
+        return TNK_Class_template;
+      else if (isa<TemplateTemplateParmDecl>(IIDecl))
+        return TNK_Template_template_parm;
+      else
+        assert(false && "Unknown TemplateDecl");
+    }
 
+    // FIXME: What follows is a gross hack.
     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) {
-      if (FD->getType()->isDependentType())
-        return FD;
+      if (FD->getType()->isDependentType()) {
+        Template = FD;
+        return TNK_Function_template;
+      }
     } else if (OverloadedFunctionDecl *Ovl 
                  = dyn_cast<OverloadedFunctionDecl>(IIDecl)) {
       for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
                                                   FEnd = Ovl->function_end();
            F != FEnd; ++F) {
-        if ((*F)->getType()->isDependentType())
-          return Ovl;
+        if ((*F)->getType()->isDependentType()) {
+          Template = Ovl;
+          return TNK_Function_template;
+        }
       }
     }
   }
-  return 0;
+  return TNK_Non_template;
 }
 
 /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
@@ -226,6 +231,15 @@
                                        (Decl**)Params, NumParams, RAngleLoc);
 }
 
+Sema::OwningTemplateArgResult Sema::ActOnTypeTemplateArgument(TypeTy *Type) {
+  return Owned(new (Context) TemplateArg(QualType::getFromOpaquePtr(Type)));
+}
+
+Sema::OwningTemplateArgResult 
+Sema::ActOnExprTemplateArgument(ExprArg Value) {
+  return Owned(new (Context) TemplateArg(static_cast<Expr *>(Value.release())));
+}
+
 Sema::DeclTy *
 Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
                          SourceLocation KWLoc, const CXXScopeSpec &SS,
@@ -351,6 +365,42 @@
   return NewTemplate;
 }
 
+Action::TypeTy * 
+Sema::ActOnClassTemplateSpecialization(DeclTy *TemplateD,
+                                       SourceLocation LAngleLoc,
+                                       MultiTemplateArgsArg TemplateArgsIn,
+                                       SourceLocation RAngleLoc,
+                                       const CXXScopeSpec *SS) {
+  TemplateDecl *Template = cast<TemplateDecl>(static_cast<Decl *>(TemplateD));
+
+  // FIXME: Not happy about this. We should teach the parser to pass
+  // us opaque pointers + bools for template argument lists.
+  // FIXME: Also not happy about the fact that we leak these
+  // TemplateArg structures. Fixing the above will fix this, too.
+  llvm::SmallVector<uintptr_t, 16> Args;
+  llvm::SmallVector<bool, 16> ArgIsType;
+  unsigned NumArgs = TemplateArgsIn.size();
+  TemplateArg **TemplateArgs 
+    = reinterpret_cast<TemplateArg **>(TemplateArgsIn.release());
+  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+    if (Expr *ExprArg = TemplateArgs[Arg]->getAsExpr()) {
+      Args.push_back(reinterpret_cast<uintptr_t>(ExprArg));
+      ArgIsType.push_back(false);
+    } else {
+      QualType T = TemplateArgs[Arg]->getAsType();
+      Args.push_back(reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()));
+      ArgIsType.push_back(true);
+    }
+  }
+
+  // Yes, all class template specializations are just silly sugar for
+  // 'int'. Gotta problem wit dat?
+  return Context.getClassTemplateSpecializationType(Template, NumArgs,
+                                                    &Args[0], &ArgIsType[0],
+                                                    Context.IntTy)
+    .getAsOpaquePtr();
+}
+
 /// \brief Determine whether the given template parameter lists are
 /// equivalent.
 ///