diff options
author | John McCall <rjmccall@apple.com> | 2010-03-10 03:28:59 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-03-10 03:28:59 +0000 |
commit | 3cb0ebd5f76abcb776f7cb4062bd79e3268c0dc4 (patch) | |
tree | 84f7dae6f0d5da51df0529ca91ff0c7fdf3f152e | |
parent | d7fdae5ea0158f91f0683044bb3a7dee0426bfe0 (diff) |
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
28 files changed, 337 insertions, 129 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 0838a3d0eb..fab63f556b 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -586,6 +586,8 @@ public: /// 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 @@ public: 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, diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 91aeff3439..bd9f01b0b5 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1429,7 +1429,6 @@ class TypeDecl : public NamedDecl { friend class DeclContext; friend class TagDecl; friend class TemplateTypeParmDecl; - friend class ClassTemplateSpecializationDecl; friend class TagType; protected: diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index ced174716c..560ce46ede 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -771,6 +771,10 @@ class ClassTemplateSpecializationDecl 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 @@ public: /// \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 @@ class ClassTemplatePartialSpecializationDecl TemplateParameterList* TemplateParams; /// \brief The source info for the template arguments as written. + /// FIXME: redundant with TypeAsWritten? TemplateArgumentLoc *ArgsAsWritten; unsigned NumArgsAsWritten; @@ -954,6 +965,7 @@ public: ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, const TemplateArgumentListInfo &ArgInfos, + QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl); /// Get the list of template parameters @@ -1139,8 +1151,8 @@ public: /// 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 @@ public: /// 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. diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index bd8a6bc846..111be55621 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2440,6 +2440,47 @@ public: 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. /// diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 6fb51edb76..27659bd02f 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -488,6 +488,14 @@ public: } }; +/// \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, diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 8187caddc6..e75202e50a 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -91,6 +91,7 @@ DEPENDENT_TYPE(TemplateTypeParm, Type) 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) diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index d4014b3075..e234e9838a 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -408,7 +408,9 @@ namespace clang { /// \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 diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e2c80a6da5..f134bfdf1f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -888,6 +888,10 @@ ASTContext::getTypeInfo(const Type *T) { 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 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, 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 @@ QualType ASTContext::getTypeDeclType(const TypeDecl *Decl, 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 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, 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 7402b7dda4..866b7f799f 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -56,6 +56,12 @@ static bool ShouldAKA(ASTContext &Context, QualType QT, 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 bf1551a099..d9c0d7b6be 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -610,6 +610,16 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, 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 9db6ae1329..a9495343e8 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -574,11 +574,22 @@ DeclContext *DeclContext::getPrimaryContext() { 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 9b693af5bc..7f4ad34fb7 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -636,11 +636,16 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const { 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 d80db45f45..b449398624 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -193,7 +193,8 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) { return 0; } -QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { +QualType +ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) { if (!CommonPtr->InjectedClassNameType.isNull()) return CommonPtr->InjectedClassNameType; @@ -393,6 +394,7 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), + TypeAsWritten(0), TemplateArgs(Context, Builder, /*TakeArgs=*/true), SpecializationKind(TSK_Undeclared) { } @@ -453,6 +455,7 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, 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 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, 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 5b621cf728..6e88ca32ca 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -30,7 +30,7 @@ namespace { 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 @@ void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, 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 @@ void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) { 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 @@ void TypePrinter::PrintTag(const TagType *T, std::string &InnerString) { // 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 @@ void TypePrinter::PrintTag(const TagType *T, std::string &InnerString) { // 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::PrintTag(const TagType *T, std::string &InnerString) { } 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 @@ void TypePrinter::PrintTemplateSpecialization( 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; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 705d7f3c52..c3302e661d 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1246,6 +1246,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, case Type::MemberPointer: return CreateType(cast<MemberPointerType>(Ty), Unit); + case Type::InjectedClassName: case Type::TemplateSpecialization: case Type::Elaborated: case Type::QualifiedName: diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 9a5cae6e81..267f4c1585 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2018,6 +2018,12 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { 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::VisitTemplateSpecializationTypeLoc( 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++])); } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 93af754683..eed3cc1a5b 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -235,6 +235,12 @@ void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) { 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::VisitTemplateSpecializationTypeLoc( 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); } diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 971b78c489..95b79abd8f 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -76,14 +76,6 @@ getCurrentInstantiationOf(ASTContext &Context, DeclContext *CurContext, // 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 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, 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 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, // 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 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, = 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 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) { |