Create a new InjectedClassNameType to represent bare-word references to the 
injected class name of a class template or class template partial specialization.
This is a non-canonical type;  the canonical type is still a template 
specialization type.  This becomes the TypeForDecl of the pattern declaration,
which cleans up some amount of code (and complicates some other parts, but
whatever).

Fixes PR6326 and probably a few others, primarily by re-establishing a few
invariants about TypeLoc sizes.     



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98134 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index e2c80a6..f134bfd 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -888,6 +888,10 @@
   case Type::QualifiedName:
     return getTypeInfo(cast<QualifiedNameType>(T)->getNamedType().getTypePtr());
 
+ case Type::InjectedClassName:
+   return getTypeInfo(cast<InjectedClassNameType>(T)
+                        ->getUnderlyingType().getTypePtr());
+
   case Type::TemplateSpecialization:
     assert(getCanonicalType(T) != T &&
            "Cannot request the size of a dependent type");
@@ -1918,6 +1922,39 @@
   return QualType(FTP, 0);
 }
 
+#ifndef NDEBUG
+static bool NeedsInjectedClassNameType(const RecordDecl *D) {
+  if (!isa<CXXRecordDecl>(D)) return false;
+  const CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
+  if (isa<ClassTemplatePartialSpecializationDecl>(RD))
+    return true;
+  if (RD->getDescribedClassTemplate() &&
+      !isa<ClassTemplateSpecializationDecl>(RD))
+    return true;
+  return false;
+}
+#endif
+
+/// getInjectedClassNameType - Return the unique reference to the
+/// injected class name type for the specified templated declaration.
+QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl,
+                                              QualType TST) {
+  assert(NeedsInjectedClassNameType(Decl));
+  if (Decl->TypeForDecl) {
+    assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
+  } else if (CXXRecordDecl *PrevDecl
+               = cast_or_null<CXXRecordDecl>(Decl->getPreviousDeclaration())) {
+    assert(PrevDecl->TypeForDecl && "previous declaration has no type");
+    Decl->TypeForDecl = PrevDecl->TypeForDecl;
+    assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
+  } else {
+    Decl->TypeForDecl = new (*this, TypeAlignment)
+      InjectedClassNameType(Decl, TST, TST->getCanonicalTypeInternal());
+    Types.push_back(Decl->TypeForDecl);
+  }
+  return QualType(Decl->TypeForDecl, 0);
+}
+
 /// getTypeDeclType - Return the unique reference to the type for the
 /// specified type declaration.
 QualType ASTContext::getTypeDeclType(const TypeDecl *Decl,
@@ -1936,8 +1973,10 @@
   if (const RecordDecl *Record = dyn_cast<RecordDecl>(Decl)) {
     if (PrevDecl)
       Decl->TypeForDecl = PrevDecl->TypeForDecl;
-    else
+    else {
+      assert(!NeedsInjectedClassNameType(Record));
       Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Record);
+    }
   } else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) {
     if (PrevDecl)
       Decl->TypeForDecl = PrevDecl->TypeForDecl;
@@ -2022,6 +2061,24 @@
   return QualType(TypeParm, 0);
 }
 
+TypeSourceInfo *
+ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
+                                              SourceLocation NameLoc,
+                                        const TemplateArgumentListInfo &Args,
+                                              QualType CanonType) {
+  QualType TST = getTemplateSpecializationType(Name, Args, CanonType);
+
+  TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
+  TemplateSpecializationTypeLoc TL
+    = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
+  TL.setTemplateNameLoc(NameLoc);
+  TL.setLAngleLoc(Args.getLAngleLoc());
+  TL.setRAngleLoc(Args.getRAngleLoc());
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+    TL.setArgLocInfo(i, Args[i].getLocInfo());
+  return DI;
+}
+
 QualType
 ASTContext::getTemplateSpecializationType(TemplateName Template,
                                           const TemplateArgumentListInfo &Args,
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 7402b7d..866b7f7 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -56,6 +56,12 @@
       QT = cast<QualifiedNameType>(Ty)->desugar();
       continue;
     }
+
+    // ...or an injected class name...
+    if (isa<InjectedClassNameType>(Ty)) {
+      QT = cast<InjectedClassNameType>(Ty)->desugar();
+      continue;
+    }
     
     // ...or a substituted template type parameter.
     if (isa<SubstTemplateTypeParmType>(Ty)) {
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index bf1551a..d9c0d7b 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -610,6 +610,16 @@
     break;
   }
 
+  case Type::InjectedClassName: {
+    const InjectedClassNameType *Inj1 = cast<InjectedClassNameType>(T1);
+    const InjectedClassNameType *Inj2 = cast<InjectedClassNameType>(T2);
+    if (!IsStructurallyEquivalent(Context,
+                                  Inj1->getUnderlyingType(),
+                                  Inj2->getUnderlyingType()))
+      return false;
+    break;
+  }
+
   case Type::Typename: {
     const TypenameType *Typename1 = cast<TypenameType>(T1);
     const TypenameType *Typename2 = cast<TypenameType>(T2);
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 9db6ae1..a949534 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -574,11 +574,22 @@
     if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) {
       // If this is a tag type that has a definition or is currently
       // being defined, that definition is our primary context.
-      if (const TagType *TagT =cast<TagDecl>(this)->TypeForDecl->getAs<TagType>())
-        if (TagT->isBeingDefined() ||
-            (TagT->getDecl() && TagT->getDecl()->isDefinition()))
-          return TagT->getDecl();
-      return this;
+      TagDecl *Tag = cast<TagDecl>(this);
+      assert(isa<TagType>(Tag->TypeForDecl) ||
+             isa<InjectedClassNameType>(Tag->TypeForDecl));
+
+      if (TagDecl *Def = Tag->getDefinition())
+        return Def;
+
+      if (!isa<InjectedClassNameType>(Tag->TypeForDecl)) {
+        const TagType *TagTy = cast<TagType>(Tag->TypeForDecl);
+        if (TagTy->isBeingDefined())
+          // FIXME: is it necessarily being defined in the decl
+          // that owns the type?
+          return TagTy->getDecl();
+      }
+
+      return Tag;
     }
 
     assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 9b693af..7f4ad34 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -636,11 +636,16 @@
 
   assert(isInstance() && "No 'this' for static methods!");
 
-  QualType ClassTy;
-  if (ClassTemplateDecl *TD = getParent()->getDescribedClassTemplate())
-    ClassTy = TD->getInjectedClassNameType(C);
-  else
-    ClassTy = C.getTagDeclType(getParent());
+  QualType ClassTy = C.getTypeDeclType(getParent());
+
+  // Aesthetically we prefer not to synthesize a type as the
+  // InjectedClassNameType of a template pattern: injected class names
+  // are printed without template arguments, which might
+  // surprise/confuse/distract our poor users if they didn't
+  // explicitly write one.
+  if (isa<InjectedClassNameType>(ClassTy))
+    ClassTy = cast<InjectedClassNameType>(ClassTy)->getUnderlyingType();
+
   ClassTy = C.getQualifiedType(ClassTy,
                                Qualifiers::fromCVRMask(getTypeQualifiers()));
   return C.getPointerType(ClassTy);
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index d80db45..b449398 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -193,7 +193,8 @@
   return 0;
 }
 
-QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
+QualType
+ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {
   if (!CommonPtr->InjectedClassNameType.isNull())
     return CommonPtr->InjectedClassNameType;
 
@@ -393,6 +394,7 @@
                   SpecializedTemplate->getIdentifier(),
                   PrevDecl),
     SpecializedTemplate(SpecializedTemplate),
+    TypeAsWritten(0),
     TemplateArgs(Context, Builder, /*TakeArgs=*/true),
     SpecializationKind(TSK_Undeclared) {
 }
@@ -453,6 +455,7 @@
        ClassTemplateDecl *SpecializedTemplate,
        TemplateArgumentListBuilder &Builder,
        const TemplateArgumentListInfo &ArgInfos,
+       QualType CanonInjectedType,
        ClassTemplatePartialSpecializationDecl *PrevDecl) {
   unsigned N = ArgInfos.size();
   TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N];
@@ -467,7 +470,8 @@
                                                           ClonedArgs, N,
                                                           PrevDecl);
   Result->setSpecializationKind(TSK_ExplicitSpecialization);
-  Context.getTypeDeclType(Result, PrevDecl);
+
+  Context.getInjectedClassNameType(Result, CanonInjectedType);
   return Result;
 }
 
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 5b621cf..6e88ca3 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -30,7 +30,7 @@
     explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { }
     
     void Print(QualType T, std::string &S);
-    void PrintTag(const TagType *T, std::string &S);
+    void PrintTag(TagDecl *T, std::string &S);
 #define ABSTRACT_TYPE(CLASS, PARENT)
 #define TYPE(CLASS, PARENT) \
   void Print##CLASS(const CLASS##Type *T, std::string &S);
@@ -330,19 +330,21 @@
   Print(T->getResultType(), S);
 }
 
-void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
-                                       std::string &S) {
-  IdentifierInfo *II = T->getDecl()->getIdentifier();
+static void PrintTypeSpec(const NamedDecl *D, std::string &S) {
+  IdentifierInfo *II = D->getIdentifier();
   if (S.empty())
     S = II->getName().str();
   else
     S = II->getName().str() + ' ' + S;
 }
 
+void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
+                                       std::string &S) {
+  PrintTypeSpec(T->getDecl(), S);
+}
+
 void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { 
-  if (!S.empty())    // Prefix the basic type, e.g. 'typedefname X'.
-    S = ' ' + S;
-  S = T->getDecl()->getIdentifier()->getName().str() + S;  
+  PrintTypeSpec(T->getDecl(), S);
 }
 
 void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) {
@@ -371,18 +373,18 @@
   S = "decltype(" + s.str() + ")" + S;
 }
 
-void TypePrinter::PrintTag(const TagType *T, std::string &InnerString) {
+void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
   if (Policy.SuppressTag)
     return;
   
   if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
     InnerString = ' ' + InnerString;
   
-  const char *Kind = Policy.SuppressTagKind? 0 : T->getDecl()->getKindName();
+  const char *Kind = Policy.SuppressTagKind? 0 : D->getKindName();
   const char *ID;
-  if (const IdentifierInfo *II = T->getDecl()->getIdentifier())
+  if (const IdentifierInfo *II = D->getIdentifier())
     ID = II->getNameStart();
-  else if (TypedefDecl *Typedef = T->getDecl()->getTypedefForAnonDecl()) {
+  else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
     Kind = 0;
     assert(Typedef->getIdentifier() && "Typedef without identifier?");
     ID = Typedef->getIdentifier()->getNameStart();
@@ -392,13 +394,22 @@
   // If this is a class template specialization, print the template
   // arguments.
   if (ClassTemplateSpecializationDecl *Spec
-      = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) {
-    const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+      = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+    const TemplateArgument *Args;
+    unsigned NumArgs;
+    if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
+      const TemplateSpecializationType *TST =
+        cast<TemplateSpecializationType>(TAW->getType());
+      Args = TST->getArgs();
+      NumArgs = TST->getNumArgs();
+    } else {
+      const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+      Args = TemplateArgs.getFlatArgumentList();
+      NumArgs = TemplateArgs.flat_size();
+    }
     std::string TemplateArgsStr
-      = TemplateSpecializationType::PrintTemplateArgumentList(
-                                            TemplateArgs.getFlatArgumentList(),
-                                            TemplateArgs.flat_size(),
-                                            Policy);
+      = TemplateSpecializationType::PrintTemplateArgumentList(Args, NumArgs,
+                                                              Policy);
     InnerString = TemplateArgsStr + InnerString;
   }
   
@@ -406,7 +417,7 @@
     // Compute the full nested-name-specifier for this type. In C,
     // this will always be empty.
     std::string ContextStr;
-    for (DeclContext *DC = T->getDecl()->getDeclContext();
+    for (DeclContext *DC = D->getDeclContext();
          !DC->isTranslationUnit(); DC = DC->getParent()) {
       std::string MyPart;
       if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
@@ -441,11 +452,11 @@
 }
 
 void TypePrinter::PrintRecord(const RecordType *T, std::string &S) {
-  PrintTag(T, S);
+  PrintTag(T->getDecl(), S);
 }
 
 void TypePrinter::PrintEnum(const EnumType *T, std::string &S) { 
-  PrintTag(T, S);
+  PrintTag(T->getDecl(), S);
 }
 
 void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { 
@@ -494,6 +505,12 @@
     S = SpecString + ' ' + S;
 }
 
+void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T,
+                                         std::string &S) {
+  // TODO: this should probably be printed with template arguments
+  PrintTag(T->getDecl(), S);
+}
+
 void TypePrinter::PrintQualifiedName(const QualifiedNameType *T, 
                                      std::string &S) { 
   std::string MyString;