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/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 971b78c..95b79ab 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -76,14 +76,6 @@
     // our context.
     if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
       return Record;
-    
-    if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
-      QualType InjectedClassName
-        = Template->getInjectedClassNameType(Context);
-      if (T == Context.getCanonicalType(InjectedClassName))
-        return Template->getTemplatedDecl();
-    }
-    // FIXME: check for class template partial specializations
   }  
   
   return 0;
@@ -130,8 +122,11 @@
       return Record;
 
     if (EnteringContext) {
-      if (const TemplateSpecializationType *SpecType
-            = dyn_cast_or_null<TemplateSpecializationType>(NNS->getAsType())) {
+      const Type *NNSType = NNS->getAsType();
+      if (!NNSType) {
+        // do nothing, fall out
+      } else if (const TemplateSpecializationType *SpecType
+                   = NNSType->getAs<TemplateSpecializationType>()) {
         // We are entering the context of the nested name specifier, so try to
         // match the nested name specifier to either a primary class template
         // or a class template partial specialization.
@@ -144,7 +139,8 @@
           // If the type of the nested name specifier is the same as the
           // injected class name of the named class template, we're entering
           // into that class template definition.
-          QualType Injected = ClassTemplate->getInjectedClassNameType(Context);
+          QualType Injected
+            = ClassTemplate->getInjectedClassNameSpecialization(Context);
           if (Context.hasSameType(Injected, ContextType))
             return ClassTemplate->getTemplatedDecl();
 
@@ -156,8 +152,7 @@
                 = ClassTemplate->findPartialSpecialization(ContextType))
             return PartialSpec;
         }
-      } else if (const RecordType *RecordT
-                   = dyn_cast_or_null<RecordType>(NNS->getAsType())) {
+      } else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) {
         // The nested name specifier refers to a member of a class template.
         return RecordT->getDecl();
       }
@@ -248,7 +243,7 @@
     // If we're currently defining this type, then lookup into the
     // type is okay: don't complain that it isn't complete yet.
     const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>();
-    if (TagT->isBeingDefined())
+    if (TagT && TagT->isBeingDefined())
       return false;
 
     // The type must be complete.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 82dcd60..94fcfc6 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -188,18 +188,6 @@
   if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
     DiagnoseUseOfDecl(IIDecl, NameLoc);
 
-    // C++ [temp.local]p2:
-    //   Within the scope of a class template specialization or
-    //   partial specialization, when the injected-class-name is
-    //   not followed by a <, it is equivalent to the
-    //   injected-class-name followed by the template-argument s
-    //   of the class template specialization or partial
-    //   specialization enclosed in <>.
-    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD))
-      if (RD->isInjectedClassName())
-        if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate())
-          T = Template->getInjectedClassNameType(Context);
-
     if (T.isNull())
       T = Context.getTypeDeclType(TD);
     
@@ -1773,12 +1761,7 @@
         return DeclarationName();
 
       // Determine the type of the class being constructed.
-      QualType CurClassType;
-      if (ClassTemplateDecl *ClassTemplate
-            = CurClass->getDescribedClassTemplate())
-        CurClassType = ClassTemplate->getInjectedClassNameType(Context);
-      else
-        CurClassType = Context.getTypeDeclType(CurClass);
+      QualType CurClassType = Context.getTypeDeclType(CurClass);
 
       // FIXME: Check two things: that the template-id names the same type as
       // CurClassType, and that the template-id does not occur when the name
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 79cab15..e694cb4 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -665,22 +665,29 @@
                        (CXXBaseSpecifier**)(Bases), NumBases);
 }
 
+static CXXRecordDecl *GetClassForType(QualType T) {
+  if (const RecordType *RT = T->getAs<RecordType>())
+    return cast<CXXRecordDecl>(RT->getDecl());
+  else if (const InjectedClassNameType *ICT = T->getAs<InjectedClassNameType>())
+    return ICT->getDecl();
+  else
+    return 0;
+}
+
 /// \brief Determine whether the type \p Derived is a C++ class that is
 /// derived from the type \p Base.
 bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
   if (!getLangOptions().CPlusPlus)
     return false;
-    
-  const RecordType *DerivedRT = Derived->getAs<RecordType>();
-  if (!DerivedRT)
+  
+  CXXRecordDecl *DerivedRD = GetClassForType(Derived);
+  if (!DerivedRD)
     return false;
   
-  const RecordType *BaseRT = Base->getAs<RecordType>();
-  if (!BaseRT)
+  CXXRecordDecl *BaseRD = GetClassForType(Base);
+  if (!BaseRD)
     return false;
   
-  CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl());
-  CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
   // FIXME: instantiate DerivedRD if necessary.  We need a PoI for this.
   return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
 }
@@ -691,16 +698,14 @@
   if (!getLangOptions().CPlusPlus)
     return false;
   
-  const RecordType *DerivedRT = Derived->getAs<RecordType>();
-  if (!DerivedRT)
+  CXXRecordDecl *DerivedRD = GetClassForType(Derived);
+  if (!DerivedRD)
     return false;
   
-  const RecordType *BaseRT = Base->getAs<RecordType>();
-  if (!BaseRT)
+  CXXRecordDecl *BaseRD = GetClassForType(Base);
+  if (!BaseRD)
     return false;
   
-  CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl());
-  CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
   return DerivedRD->isDerivedFrom(BaseRD, Paths);
 }
 
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 309da29..b9c8afa 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -172,14 +172,6 @@
 
     if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) {
       QualType T = Context.getTypeDeclType(Type);
-      // If we found the injected-class-name of a class template, retrieve the
-      // type of that template.
-      // FIXME: We really shouldn't need to do this.
-      if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Type))
-        if (Record->isInjectedClassName())
-          if (Record->getDescribedClassTemplate())
-            T = Record->getDescribedClassTemplate()
-                                           ->getInjectedClassNameType(Context);
 
       if (SearchType.isNull() || SearchType->isDependentType() ||
           Context.hasSameUnqualifiedType(T, SearchType)) {
@@ -200,16 +192,8 @@
       if (SS.isSet()) {
         if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) {
           // Figure out the type of the context, if it has one.
-          if (ClassTemplateSpecializationDecl *Spec
-                          = dyn_cast<ClassTemplateSpecializationDecl>(Ctx))
-            MemberOfType = Context.getTypeDeclType(Spec);
-          else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
-            if (Record->getDescribedClassTemplate())
-              MemberOfType = Record->getDescribedClassTemplate()
-                                          ->getInjectedClassNameType(Context);
-            else
-              MemberOfType = Context.getTypeDeclType(Record);
-          }
+          if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx))
+            MemberOfType = Context.getTypeDeclType(Record);
         }
       }
       if (MemberOfType.isNull())
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 445b68b..7c4cab1 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -871,10 +871,8 @@
   NewClass->setDescribedClassTemplate(NewTemplate);
 
   // Build the type for the class template declaration now.
-  QualType T =
-    Context.getTypeDeclType(NewClass,
-                            PrevClassTemplate?
-                              PrevClassTemplate->getTemplatedDecl() : 0);
+  QualType T = NewTemplate->getInjectedClassNameSpecialization(Context);
+  T = Context.getInjectedClassNameType(NewClass, T);
   assert(T->isDependentType() && "Class template type is not dependent?");
   (void)T;
 
@@ -1306,7 +1304,7 @@
         TemplateParameterList *ExpectedTemplateParams = 0;
         // Is this template-id naming the primary template?
         if (Context.hasSameType(TemplateId,
-                             ClassTemplate->getInjectedClassNameType(Context)))
+                 ClassTemplate->getInjectedClassNameSpecialization(Context)))
           ExpectedTemplateParams = ClassTemplate->getTemplateParameters();
         // ... or a partial specialization?
         else if (ClassTemplatePartialSpecializationDecl *PartialSpec
@@ -1431,6 +1429,8 @@
     }
 
     CanonType = Context.getTypeDeclType(Decl);
+    assert(isa<RecordType>(CanonType) &&
+           "type of non-dependent specialization is not a RecordType");
   }
 
   // Build the fully-sugared type for this class template
@@ -3488,6 +3488,7 @@
                                                        ClassTemplate,
                                                        Converted,
                                                        TemplateArgs,
+                                                       CanonType,
                                                        PrevPartial);
 
     if (PrevPartial) {
@@ -3609,8 +3610,9 @@
   // actually wrote the specialization, rather than formatting the
   // name based on the "canonical" representation used to store the
   // template arguments in the specialization.
-  QualType WrittenTy
-    = Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
+  TypeSourceInfo *WrittenTy
+    = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
+                                                TemplateArgs, CanonType);
   if (TUK != TUK_Friend)
     Specialization->setTypeAsWritten(WrittenTy);
   TemplateArgsIn.release();
@@ -3632,7 +3634,7 @@
   if (TUK == TUK_Friend) {
     FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
                                             TemplateNameLoc,
-                                            WrittenTy.getTypePtr(),
+                                            WrittenTy->getType().getTypePtr(),
                                             /*FIXME:*/KWLoc);
     Friend->setAccess(AS_public);
     CurContext->addDecl(Friend);
@@ -4344,8 +4346,9 @@
   // the explicit instantiation, rather than formatting the name based
   // on the "canonical" representation used to store the template
   // arguments in the specialization.
-  QualType WrittenTy
-    = Context.getTemplateSpecializationType(Name, TemplateArgs,
+  TypeSourceInfo *WrittenTy
+    = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
+                                                TemplateArgs,
                                   Context.getTypeDeclType(Specialization));
   Specialization->setTypeAsWritten(WrittenTy);
   TemplateArgsIn.release();
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 7f16400..326519d 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -625,6 +625,15 @@
       return Sema::TDK_Success;
     }
 
+    case Type::InjectedClassName: {
+      // Treat a template's injected-class-name as if the template
+      // specialization type had been used.
+      Param = cast<InjectedClassNameType>(Param)->getUnderlyingType();
+      assert(isa<TemplateSpecializationType>(Param) &&
+             "injected class name is not a template specialization type");
+      // fall through
+    }
+
     //     template-name<T> (where template-name refers to a class template)
     //     template-name<i>
     //     TT<T>
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 3a6b4cb..cf8d38c 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -621,7 +621,8 @@
   Inst->setInstantiatedFromMemberTemplate(D);
   
   // Trigger creation of the type for the instantiation.
-  SemaRef.Context.getTypeDeclType(RecordInst);
+  SemaRef.Context.getInjectedClassNameType(RecordInst,
+                  Inst->getInjectedClassNameSpecialization(SemaRef.Context));
   
   // Finish handling of friends.
   if (Inst->getFriendObjectKind()) {
@@ -1462,8 +1463,10 @@
   // actually wrote the specialization, rather than formatting the
   // name based on the "canonical" representation used to store the
   // template arguments in the specialization.
-  QualType WrittenTy
-    = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate),
+  TypeSourceInfo *WrittenTy
+    = SemaRef.Context.getTemplateSpecializationTypeInfo(
+                                                    TemplateName(ClassTemplate),
+                                                    PartialSpec->getLocation(),
                                                     InstTemplateArgs,
                                                     CanonType);
   
@@ -1499,6 +1502,7 @@
                                                      ClassTemplate, 
                                                      Converted,
                                                      InstTemplateArgs,
+                                                     CanonType,
                                                      0);
   InstPartialSpec->setInstantiatedFromMember(PartialSpec);
   InstPartialSpec->setTypeAsWritten(WrittenTy);
@@ -2236,12 +2240,18 @@
     ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
     
     if (ClassTemplate) {
-      T = ClassTemplate->getInjectedClassNameType(Context);
+      T = ClassTemplate->getInjectedClassNameSpecialization(Context);
     } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
                  = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
-      T = Context.getTypeDeclType(Record);
       ClassTemplate = PartialSpec->getSpecializedTemplate();
-    } 
+
+      // If we call SubstType with an InjectedClassNameType here we
+      // can end up in an infinite loop.
+      T = Context.getTypeDeclType(Record);
+      assert(isa<InjectedClassNameType>(T) &&
+             "type of partial specialization is not an InjectedClassNameType");
+      T = cast<InjectedClassNameType>(T)->getUnderlyingType();
+    }  
     
     if (!T.isNull()) {
       // Substitute into the injected-class-name to get the type
@@ -2308,16 +2318,16 @@
     // so now we need to look into the instantiated parent context to
     // find the instantiation of the declaration D.
 
-    // If our context is a class template specialization, we may need
-    // to instantiate it before performing lookup into that context.
-    if (ClassTemplateSpecializationDecl *Spec
-                       = dyn_cast<ClassTemplateSpecializationDecl>(ParentDC)) {
+    // If our context used to be dependent, we may need to instantiate
+    // it before performing lookup into that context.
+    if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) {
       if (!Spec->isDependentContext()) {
         QualType T = Context.getTypeDeclType(Spec);
-        if (const TagType *Tag = T->getAs<TagType>())
-          if (!Tag->isBeingDefined() &&
-              RequireCompleteType(Loc, T, diag::err_incomplete_type))
-            return 0;
+        const RecordType *Tag = T->getAs<RecordType>();
+        assert(Tag && "type of non-dependent record is not a RecordType");
+        if (!Tag->isBeingDefined() &&
+            RequireCompleteType(Loc, T, diag::err_incomplete_type))
+          return 0;
       }
     }
 
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 24ea62c..17f9419 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2823,6 +2823,20 @@
   return Result;
 }
 
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformInjectedClassNameType(
+                                         TypeLocBuilder &TLB,
+                                         InjectedClassNameTypeLoc TL,
+                                         QualType ObjectType) {
+  Decl *D = getDerived().TransformDecl(TL.getNameLoc(),
+                                       TL.getTypePtr()->getDecl());
+  if (!D) return QualType();
+
+  QualType T = SemaRef.Context.getTypeDeclType(cast<TypeDecl>(D));
+  TLB.pushTypeSpec(T).setNameLoc(TL.getNameLoc());
+  return T;
+}
+
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTemplateTypeParmType(