[cfe-commits] r98134 - in /cfe/trunk: include/clang/AST/ include/clang/Frontend/ lib/AST/ lib/CodeGen/ lib/Frontend/ lib/Sema/ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/ test/SemaTemplate/

John McCall rjmccall at apple.com
Tue Mar 9 19:29:00 PST 2010


Author: rjmccall
Date: Tue Mar  9 21:28:59 2010
New Revision: 98134

URL: http://llvm.org/viewvc/llvm-project?rev=98134&view=rev
Log:
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.     


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/AST/TypeLoc.h
    cfe/trunk/include/clang/AST/TypeNodes.def
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTDiagnostic.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
    cfe/trunk/test/SemaTemplate/injected-class-name.cpp
    cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Mar  9 21:28:59 2010
@@ -586,6 +586,8 @@
   /// specified typename decl.
   QualType getTypedefType(const TypedefDecl *Decl);
 
+  QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST);
+
   QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
                                         QualType Replacement);
 
@@ -602,6 +604,11 @@
                                          const TemplateArgumentListInfo &Args,
                                          QualType Canon = QualType());
 
+  TypeSourceInfo *
+  getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc,
+                                    const TemplateArgumentListInfo &Args,
+                                    QualType Canon = QualType());
+
   QualType getQualifiedNameType(NestedNameSpecifier *NNS,
                                 QualType NamedType);
   QualType getTypenameType(NestedNameSpecifier *NNS,

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Mar  9 21:28:59 2010
@@ -1429,7 +1429,6 @@
   friend class DeclContext;
   friend class TagDecl;
   friend class TemplateTypeParmDecl;
-  friend class ClassTemplateSpecializationDecl;
   friend class TagType;
 
 protected:

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Tue Mar  9 21:28:59 2010
@@ -771,6 +771,10 @@
   llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
     SpecializedTemplate;
 
+  /// \brief The type-as-written of an explicit template specialization.
+  /// Does not apply to implicit specializations.
+  TypeSourceInfo *TypeAsWritten;
+
   /// \brief The template arguments used to describe this specialization.
   TemplateArgumentList TemplateArgs;
 
@@ -883,8 +887,14 @@
 
   /// \brief Sets the type of this specialization as it was written by
   /// the user. This will be a class template specialization type.
-  void setTypeAsWritten(QualType T) {
-    TypeForDecl = T.getTypePtr();
+  void setTypeAsWritten(TypeSourceInfo *T) {
+    TypeAsWritten = T;
+  }
+
+  /// \brief Gets the type of this specialization as it was written by
+  /// the user, if it was so written.
+  TypeSourceInfo *getTypeAsWritten() const {
+    return TypeAsWritten;
   }
 
   void Profile(llvm::FoldingSetNodeID &ID) const {
@@ -921,6 +931,7 @@
   TemplateParameterList* TemplateParams;
 
   /// \brief The source info for the template arguments as written.
+  /// FIXME: redundant with TypeAsWritten?
   TemplateArgumentLoc *ArgsAsWritten;
   unsigned NumArgsAsWritten;
 
@@ -954,6 +965,7 @@
          ClassTemplateDecl *SpecializedTemplate,
          TemplateArgumentListBuilder &Builder,
          const TemplateArgumentListInfo &ArgInfos,
+         QualType CanonInjectedType,
          ClassTemplatePartialSpecializationDecl *PrevDecl);
 
   /// Get the list of template parameters
@@ -1139,8 +1151,8 @@
   /// the type \p T, or NULL if no such partial specialization exists.
   ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
 
-  /// \brief Retrieve the type of the injected-class-name for this
-  /// class template.
+  /// \brief Retrieve the template specialization type of the
+  /// injected-class-name for this class template.
   ///
   /// The injected-class-name for a class template \c X is \c
   /// X<template-args>, where \c template-args is formed from the
@@ -1153,7 +1165,7 @@
   ///   typedef array this_type; // "array" is equivalent to "array<T, N>"
   /// };
   /// \endcode
-  QualType getInjectedClassNameType(ASTContext &Context);
+  QualType getInjectedClassNameSpecialization(ASTContext &Context);
 
   /// \brief Retrieve the member class template that this class template was
   /// derived from.

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Mar  9 21:28:59 2010
@@ -2440,6 +2440,47 @@
   static bool classof(const TemplateSpecializationType *T) { return true; }
 };
 
+/// \brief The injected class name of a C++ class template.  Used to
+/// record that a type was spelled with a bare identifier rather than
+/// as a template-id; the equivalent for non-templated classes is just
+/// RecordType.
+///
+/// For consistency, template instantiation turns these into RecordTypes.
+///
+/// The desugared form is always a unqualified TemplateSpecializationType.
+/// The canonical form is always either a TemplateSpecializationType
+/// (when dependent) or a RecordType (otherwise).
+class InjectedClassNameType : public Type {
+  CXXRecordDecl *Decl;
+
+  QualType UnderlyingType;
+
+  friend class ASTContext; // ASTContext creates these.
+  InjectedClassNameType(CXXRecordDecl *D, QualType TST, QualType Canon)
+    : Type(InjectedClassName, Canon, Canon->isDependentType()),
+      Decl(D), UnderlyingType(TST) {
+    assert(isa<TemplateSpecializationType>(TST));
+    assert(!TST.hasQualifiers());
+    assert(TST->getCanonicalTypeInternal() == Canon);
+  }
+
+public:
+  QualType getUnderlyingType() const { return UnderlyingType; }
+  const TemplateSpecializationType *getUnderlyingTST() const {
+    return cast<TemplateSpecializationType>(UnderlyingType.getTypePtr());
+  }
+
+  CXXRecordDecl *getDecl() const { return Decl; }
+
+  bool isSugared() const { return true; }
+  QualType desugar() const { return UnderlyingType; }
+
+  static bool classof(const Type *T) {
+    return T->getTypeClass() == InjectedClassName;
+  }
+  static bool classof(const InjectedClassNameType *T) { return true; }
+};
+
 /// \brief Represents a type that was referred to via a qualified
 /// name, e.g., N::M::type.
 ///

Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Tue Mar  9 21:28:59 2010
@@ -488,6 +488,14 @@
   }
 };
 
+/// \brief Wrapper for source info for injected class names of class
+/// templates.
+class InjectedClassNameTypeLoc :
+    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+                                     InjectedClassNameTypeLoc,
+                                     InjectedClassNameType> {
+};
+
 /// \brief Wrapper for source info for unresolved typename using decls.
 class UnresolvedUsingTypeLoc :
     public InheritingConcreteTypeLoc<TypeSpecTypeLoc,

Modified: cfe/trunk/include/clang/AST/TypeNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeNodes.def?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeNodes.def (original)
+++ cfe/trunk/include/clang/AST/TypeNodes.def Tue Mar  9 21:28:59 2010
@@ -91,6 +91,7 @@
 NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
 NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
 NON_CANONICAL_TYPE(QualifiedName, Type)
+NON_CANONICAL_TYPE(InjectedClassName, Type)
 DEPENDENT_TYPE(Typename, Type)
 TYPE(ObjCInterface, Type)
 TYPE(ObjCObjectPointer, Type)

Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Tue Mar  9 21:28:59 2010
@@ -408,7 +408,9 @@
       /// \brief A SubstTemplateTypeParmType record.
       TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,
       /// \brief An UnresolvedUsingType record.
-      TYPE_UNRESOLVED_USING         = 26
+      TYPE_UNRESOLVED_USING         = 26,
+      /// \brief An InjectedClassNameType record.
+      TYPE_INJECTED_CLASS_NAME      = 27
     };
 
     /// \brief The type IDs for special types constructed by semantic

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Mar  9 21:28:59 2010
@@ -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,

Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)
+++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Tue Mar  9 21:28:59 2010
@@ -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)) {

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Mar  9 21:28:59 2010
@@ -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);

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Mar  9 21:28:59 2010
@@ -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 &&

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Mar  9 21:28:59 2010
@@ -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);

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Tue Mar  9 21:28:59 2010
@@ -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;
 }
 

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Tue Mar  9 21:28:59 2010
@@ -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;

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Tue Mar  9 21:28:59 2010
@@ -1246,6 +1246,7 @@
   case Type::MemberPointer:
     return CreateType(cast<MemberPointerType>(Ty), Unit);
 
+  case Type::InjectedClassName:
   case Type::TemplateSpecialization:
   case Type::Elaborated:
   case Type::QualifiedName:

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Mar  9 21:28:59 2010
@@ -2018,6 +2018,12 @@
       Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
                                             Replacement);
   }
+
+  case pch::TYPE_INJECTED_CLASS_NAME: {
+    CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0]));
+    QualType TST = GetType(Record[1]); // probably derivable
+    return Context->getInjectedClassNameType(D, TST);
+  }
   }
   // Suppress a GCC warning
   return QualType();
@@ -2172,6 +2178,9 @@
 void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
   TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
+void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
 void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
   TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Mar  9 21:28:59 2010
@@ -235,6 +235,12 @@
   assert(false && "Cannot serialize qualified name types");
 }
 
+void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
+  Writer.AddDeclRef(T->getDecl(), Record);
+  Writer.AddTypeRef(T->getUnderlyingType(), Record);
+  Code = pch::TYPE_INJECTED_CLASS_NAME;
+}
+
 void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
   Writer.AddDeclRef(T->getDecl(), Record);
   Record.push_back(T->getNumProtocols());
@@ -394,6 +400,9 @@
 void TypeLocWriter::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }
+void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
 void TypeLocWriter::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Tue Mar  9 21:28:59 2010
@@ -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.

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar  9 21:28:59 2010
@@ -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

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Mar  9 21:28:59 2010
@@ -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);
 }
 

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Mar  9 21:28:59 2010
@@ -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())

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Mar  9 21:28:59 2010
@@ -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();

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Mar  9 21:28:59 2010
@@ -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>

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Mar  9 21:28:59 2010
@@ -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;
       }
     }
 

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Mar  9 21:28:59 2010
@@ -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(

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp Tue Mar  9 21:28:59 2010
@@ -52,7 +52,7 @@
 void e4(enum B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
 
 template <class T> struct C {
-  void foo(class B<T>::Member); // expected-error{{no type named 'Member' in 'B<int>'}}
+  void foo(class B<T>::Member); // expected-error{{no type named 'Member' in 'struct B<int>'}}
 };
 
 C<float> f1;

Modified: cfe/trunk/test/SemaTemplate/injected-class-name.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/injected-class-name.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/injected-class-name.cpp (original)
+++ cfe/trunk/test/SemaTemplate/injected-class-name.cpp Tue Mar  9 21:28:59 2010
@@ -42,3 +42,9 @@
   void f0(const X1<T, N>&); // expected-error{{redecl}}
 };
 
+namespace pr6326 {
+  template <class T> class A {
+    friend class A;
+  };
+  template class A<int>;
+}

Modified: cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp?rev=98134&r1=98133&r2=98134&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp Tue Mar  9 21:28:59 2010
@@ -36,7 +36,7 @@
 Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}}
 
 
-template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1<int const>'}}
+template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'struct Def1<int const>'}}
 
 template<typename T, typename T2 = T&> struct Def3;
 





More information about the cfe-commits mailing list