Correctly handle elaborated template ids.  Still not handled properly for friends.

llvm-svn: 80977
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index fc19e61..41ba1f1 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -22,6 +22,8 @@
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
+#include "clang/Parse/DeclSpec.h"
+#include "llvm/Support/ErrorHandling.h"
 #include <vector>
 
 using namespace clang;
@@ -708,6 +710,16 @@
   return 0;
 }
 
+TagDecl::TagKind TagDecl::getTagKindForTypeSpec(unsigned TypeSpec) {
+  switch (TypeSpec) {
+  default: llvm::llvm_unreachable("unexpected type specifier");
+  case DeclSpec::TST_struct: return TK_struct;
+  case DeclSpec::TST_class: return TK_class;
+  case DeclSpec::TST_union: return TK_union;
+  case DeclSpec::TST_enum: return TK_enum;
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // RecordDecl Implementation
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index f50147c..5935953 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -606,7 +606,7 @@
   // to turn that template-id into a type.
 
   bool Owned = false;
-  if (TemplateId && TUK != Action::TUK_Reference && TUK != Action::TUK_Friend) {
+  if (TemplateId) {
     // Explicit specialization, class template partial specialization,
     // or explicit instantiation.
     ASTTemplateArgsPtr TemplateArgsPtr(Actions, 
@@ -629,6 +629,31 @@
                                       TemplateId->getTemplateArgLocations(),
                                              TemplateId->RAngleLoc, 
                                              Attr);
+    } else if (TUK == Action::TUK_Reference || TUK == Action::TUK_Friend) {
+      Action::TypeResult TypeResult =
+        Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+                                    TemplateId->TemplateNameLoc,
+                                    TemplateId->LAngleLoc,
+                                    TemplateArgsPtr,
+                                    TemplateId->getTemplateArgLocations(),
+                                    TemplateId->RAngleLoc,
+                                    TagType, StartLoc);
+
+      TemplateId->Destroy();
+
+      if (TypeResult.isInvalid()) {
+        DS.SetTypeSpecError();
+        return;
+      }
+  
+      const char *PrevSpec = 0;
+      unsigned DiagID;
+      if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, PrevSpec,
+                             DiagID, TypeResult.get()))
+        Diag(StartLoc, DiagID) << PrevSpec;
+
+      return;
+      
     } else {
       // This is an explicit specialization or a class template
       // partial specialization.
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 746c28a..f1e4968 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -2396,7 +2396,9 @@
                       SourceLocation LAngleLoc,
                       ASTTemplateArgsPtr TemplateArgs,
                       SourceLocation *TemplateArgLocs,
-                      SourceLocation RAngleLoc);
+                      SourceLocation RAngleLoc,
+                      DeclSpec::TST TagSpec,
+                      SourceLocation TagLoc);
   
   OwningExprResult BuildTemplateIdExpr(TemplateName Template,
                                        SourceLocation TemplateNameLoc,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index abf9528..e929b5f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3966,14 +3966,7 @@
          "Nameless record must be a definition!");
 
   OwnedDecl = false;
-  TagDecl::TagKind Kind;
-  switch (TagSpec) {
-  default: assert(0 && "Unknown tag type!");
-  case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;
-  case DeclSpec::TST_union:  Kind = TagDecl::TK_union; break;
-  case DeclSpec::TST_class:  Kind = TagDecl::TK_class; break;
-  case DeclSpec::TST_enum:   Kind = TagDecl::TK_enum; break;
-  }
+  TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec);
   
   if (TUK != TUK_Reference) {
     if (TemplateParameterList *TemplateParams
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 119e17f..8eaa9fb 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1121,7 +1121,9 @@
                           SourceLocation LAngleLoc, 
                           ASTTemplateArgsPtr TemplateArgsIn,
                           SourceLocation *TemplateArgLocs,
-                          SourceLocation RAngleLoc) {
+                          SourceLocation RAngleLoc,
+                          DeclSpec::TST TagSpec,
+                          SourceLocation TagLoc) {
   TemplateName Template = TemplateD.getAsVal<TemplateName>();
 
   // Translate the parser's template argument list in our AST format.
@@ -1137,6 +1139,25 @@
   if (Result.isNull())
     return true;
 
+  // If we were given a tag specifier, verify it.
+  if (TagSpec != DeclSpec::TST_unspecified) {
+    TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec);
+
+    if (const RecordType *T = Result->getAs<RecordType>()) {
+      RecordDecl *D = T->getDecl();
+
+      IdentifierInfo *Id = D->getIdentifier();
+      assert(Id && "templated class must have an identifier");
+
+      if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) {
+        Diag(TagLoc, diag::err_use_with_wrong_tag)
+          << Id
+          << CodeModificationHint::CreateReplacement(SourceRange(TagLoc),
+                                                     D->getKindName());
+      }
+    }
+  }
+
   return Result.getAsOpaquePtr();
 }
 
@@ -2497,6 +2518,8 @@
                                        SourceLocation RAngleLoc,
                                        AttributeList *Attr,
                                MultiTemplateParamsArg TemplateParameterLists) {
+  assert(TUK == TUK_Declaration || TUK == TUK_Definition);
+
   // Find the class template we're specializing
   TemplateName Name = TemplateD.getAsVal<TemplateName>();
   ClassTemplateDecl *ClassTemplate