diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 75 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 27 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 27 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 56 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 32 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 32 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 12 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 106 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 127 |
13 files changed, 352 insertions, 196 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 2e72449575..1cc8eb8fb2 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1911,44 +1911,69 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, } QualType -ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, +ASTContext::getDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const TemplateSpecializationType *TemplateId, - QualType Canon) { + const IdentifierInfo *Name, + const TemplateArgumentListInfo &Args) { + // TODO: avoid this copy + llvm::SmallVector<TemplateArgument, 16> ArgCopy; + for (unsigned I = 0, E = Args.size(); I != E; ++I) + ArgCopy.push_back(Args[I].getArgument()); + return getDependentTemplateSpecializationType(Keyword, NNS, Name, + ArgCopy.size(), + ArgCopy.data()); +} + +QualType +ASTContext::getDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args) { assert(NNS->isDependent() && "nested-name-specifier must be dependent"); llvm::FoldingSetNodeID ID; - DependentNameType::Profile(ID, Keyword, NNS, TemplateId); + DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS, + Name, NumArgs, Args); void *InsertPos = 0; - DependentNameType *T - = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); + DependentTemplateSpecializationType *T + = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) return QualType(T, 0); - if (Canon.isNull()) { - NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); - QualType CanonType = getCanonicalType(QualType(TemplateId, 0)); - ElaboratedTypeKeyword CanonKeyword = Keyword; - if (Keyword == ETK_None) - CanonKeyword = ETK_Typename; - if (CanonNNS != NNS || CanonKeyword != Keyword || - CanonType != QualType(TemplateId, 0)) { - const TemplateSpecializationType *CanonTemplateId - = CanonType->getAs<TemplateSpecializationType>(); - assert(CanonTemplateId && - "Canonical type must also be a template specialization type"); - Canon = getDependentNameType(CanonKeyword, CanonNNS, CanonTemplateId); - } + NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); + + ElaboratedTypeKeyword CanonKeyword = Keyword; + if (Keyword == ETK_None) CanonKeyword = ETK_Typename; + + bool AnyNonCanonArgs = false; + llvm::SmallVector<TemplateArgument, 16> CanonArgs(NumArgs); + for (unsigned I = 0; I != NumArgs; ++I) { + CanonArgs[I] = getCanonicalTemplateArgument(Args[I]); + if (!CanonArgs[I].structurallyEquals(Args[I])) + AnyNonCanonArgs = true; + } + + QualType Canon; + if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) { + Canon = getDependentTemplateSpecializationType(CanonKeyword, CanonNNS, + Name, NumArgs, + CanonArgs.data()); - DependentNameType *CheckT - = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!CheckT && "Typename canonical type is broken"); (void)CheckT; + // Find the insert position again. + DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); } - T = new (*this) DependentNameType(Keyword, NNS, TemplateId, Canon); + void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) + + sizeof(TemplateArgument) * NumArgs), + TypeAlignment); + T = new (Mem) DependentTemplateSpecializationType(*this, Keyword, NNS, + Name, NumArgs, Args, Canon); Types.push_back(T); - DependentNameTypes.InsertNode(T, InsertPos); + DependentTemplateSpecializationTypes.InsertNode(T, InsertPos); return QualType(T, 0); } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 14fe980575..370dbc54a2 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -73,6 +73,7 @@ namespace { // FIXME: TemplateSpecializationType QualType VisitElaboratedType(ElaboratedType *T); // FIXME: DependentNameType + // FIXME: DependentTemplateSpecializationType QualType VisitObjCInterfaceType(ObjCInterfaceType *T); QualType VisitObjCObjectType(ObjCObjectType *T); QualType VisitObjCObjectPointerType(ObjCObjectPointerType *T); @@ -619,14 +620,32 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Typename1->getIdentifier(), Typename2->getIdentifier())) return false; - if (!IsStructurallyEquivalent(Context, - QualType(Typename1->getTemplateId(), 0), - QualType(Typename2->getTemplateId(), 0))) - return false; break; } + case Type::DependentTemplateSpecialization: { + const DependentTemplateSpecializationType *Spec1 = + cast<DependentTemplateSpecializationType>(T1); + const DependentTemplateSpecializationType *Spec2 = + cast<DependentTemplateSpecializationType>(T2); + if (!IsStructurallyEquivalent(Context, + Spec1->getQualifier(), + Spec2->getQualifier())) + return false; + if (!IsStructurallyEquivalent(Spec1->getIdentifier(), + Spec2->getIdentifier())) + return false; + if (Spec1->getNumArgs() != Spec2->getNumArgs()) + return false; + for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, + Spec1->getArg(I), Spec2->getArg(I))) + return false; + } + break; + } + case Type::ObjCInterface: { const ObjCInterfaceType *Iface1 = cast<ObjCInterfaceType>(T1); const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(T2); diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index 1c775efe57..02e648879a 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -90,6 +90,33 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, } } +bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { + if (getKind() != Other.getKind()) return false; + + switch (getKind()) { + case Null: + case Type: + case Declaration: + case Template: + case Expression: + return TypeOrValue == Other.TypeOrValue; + + case Integral: + return getIntegralType() == Other.getIntegralType() && + *getAsIntegral() == *Other.getAsIntegral(); + + case Pack: + if (Args.NumArgs != Other.Args.NumArgs) return false; + for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) + if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) + return false; + return true; + } + + // Suppress warnings. + return false; +} + //===----------------------------------------------------------------------===// // TemplateArgumentLoc Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1aab65ebec..c8cdae3af8 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -768,6 +768,7 @@ bool Type::isSpecifierType() const { case TemplateSpecialization: case Elaborated: case DependentName: + case DependentTemplateSpecialization: case ObjCInterface: case ObjCObject: case ObjCObjectPointer: // FIXME: object pointers aren't really specifiers @@ -856,12 +857,56 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { } } +ElaboratedType::~ElaboratedType() {} +DependentNameType::~DependentNameType() {} +DependentTemplateSpecializationType::~DependentTemplateSpecializationType() {} + +void DependentTemplateSpecializationType::Destroy(ASTContext &C) { + for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { + // FIXME: Not all expressions get cloned, so we can't yet perform + // this destruction. + // if (Expr *E = getArg(Arg).getAsExpr()) + // E->Destroy(C); + } +} + +DependentTemplateSpecializationType::DependentTemplateSpecializationType( + ASTContext &Context, ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, const IdentifierInfo *Name, + unsigned NumArgs, const TemplateArgument *Args, + QualType Canon) + : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true), + Context(Context), NNS(NNS), Name(Name), NumArgs(NumArgs) { + assert(NNS && NNS->isDependent() && + "DependentTemplateSpecializatonType requires dependent qualifier"); + for (unsigned I = 0; I != NumArgs; ++I) + new (&getArgBuffer()[I]) TemplateArgument(Args[I]); +} + +void +DependentTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, + ASTContext &Context, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *Qualifier, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args) { + ID.AddInteger(Keyword); + ID.AddPointer(Qualifier); + ID.AddPointer(Name); + for (unsigned Idx = 0; Idx < NumArgs; ++Idx) + Args[Idx].Profile(ID, Context); +} + bool Type::isElaboratedTypeSpecifier() const { ElaboratedTypeKeyword Keyword; if (const ElaboratedType *Elab = dyn_cast<ElaboratedType>(this)) Keyword = Elab->getKeyword(); else if (const DependentNameType *DepName = dyn_cast<DependentNameType>(this)) Keyword = DepName->getKeyword(); + else if (const DependentTemplateSpecializationType *DepTST = + dyn_cast<DependentTemplateSpecializationType>(this)) + Keyword = DepTST->getKeyword(); else return false; @@ -1113,17 +1158,6 @@ void TemplateSpecializationType::Destroy(ASTContext& C) { } } -TemplateSpecializationType::iterator -TemplateSpecializationType::end() const { - return begin() + getNumArgs(); -} - -const TemplateArgument & -TemplateSpecializationType::getArg(unsigned Idx) const { - assert(Idx < getNumArgs() && "Template argument out of range"); - return getArgs()[Idx]; -} - void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, TemplateName T, diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index ccf6fb9362..2fa84f350b 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -580,15 +580,31 @@ void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) T->getQualifier()->print(OS, Policy); - if (const IdentifierInfo *Ident = T->getIdentifier()) - OS << Ident->getName(); - else if (const TemplateSpecializationType *Spec = T->getTemplateId()) { - Spec->getTemplateName().print(OS, Policy, true); - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Spec->getArgs(), - Spec->getNumArgs(), + OS << T->getIdentifier()->getName(); + } + + if (S.empty()) + S.swap(MyString); + else + S = MyString + ' ' + S; +} + +void TypePrinter::PrintDependentTemplateSpecialization( + const DependentTemplateSpecializationType *T, std::string &S) { + std::string MyString; + { + llvm::raw_string_ostream OS(MyString); + + OS << TypeWithKeyword::getKeywordName(T->getKeyword()); + if (T->getKeyword() != ETK_None) + OS << " "; + + T->getQualifier()->print(OS, Policy); + OS << T->getIdentifier()->getName(); + OS << TemplateSpecializationType::PrintTemplateArgumentList( + T->getArgs(), + T->getNumArgs(), Policy); - } } if (S.empty()) diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index d8f1ca0b90..011e46941d 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -1369,21 +1369,25 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { void CXXNameMangler::mangleType(const DependentNameType *T) { // Typename types are always nested Out << 'N'; - if (T->getIdentifier()) { - mangleUnresolvedScope(T->getQualifier()); - mangleSourceName(T->getIdentifier()); - } else { - const TemplateSpecializationType *TST = T->getTemplateId(); + mangleUnresolvedScope(T->getQualifier()); + mangleSourceName(T->getIdentifier()); + Out << 'E'; +} - mangleTemplatePrefix(TST->getTemplateName()); - - // FIXME: GCC does not appear to mangle the template arguments when - // the template in question is a dependent template name. Should we - // emulate that badness? - mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(), - TST->getNumArgs()); - } - +void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) { + // Dependently-scoped template types are always nested + Out << 'N'; + + // TODO: avoid making this TemplateName. + TemplateName Prefix = + getASTContext().getDependentTemplateName(T->getQualifier(), + T->getIdentifier()); + mangleTemplatePrefix(Prefix); + + // FIXME: GCC does not appear to mangle the template arguments when + // the template in question is a dependent template name. Should we + // emulate that badness? + mangleTemplateArgs(Prefix, T->getArgs(), T->getNumArgs()); Out << 'E'; } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index aebb7e1772..e555d9078f 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2367,6 +2367,18 @@ void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } +void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); + TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + TL.setArgLocInfo(I, + Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(), + Record, Idx)); +} void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 3d5b7d8156..a2f7482e20 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -408,6 +408,16 @@ void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { Writer.AddSourceRange(TL.getQualifierRange(), Record); Writer.AddSourceLocation(TL.getNameLoc(), Record); } +void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + Writer.AddSourceLocation(TL.getKeywordLoc(), Record); + Writer.AddSourceRange(TL.getQualifierRange(), Record); + Writer.AddSourceLocation(TL.getNameLoc(), Record); + Writer.AddSourceLocation(TL.getLAngleLoc(), Record); + Writer.AddSourceLocation(TL.getRAngleLoc(), Record); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + Writer.AddTemplateArgumentLoc(TL.getArgLoc(I), Record); +} void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1a8f7aa481..6bad5da9c4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -87,8 +87,8 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (!isClassName) return 0; - // We know from the grammar that this name refers to a type, so build a - // DependentNameType node to describe the type. + // We know from the grammar that this name refers to a type, + // so build a dependent node to describe the type. return CheckTypenameType(ETK_None, (NestedNameSpecifier *)SS->getScopeRep(), II, SourceLocation(), SS->getRange(), NameLoc @@ -196,12 +196,6 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { T = Context.getObjCInterfaceType(IDecl); - } else if (UnresolvedUsingTypenameDecl *UUDecl = - dyn_cast<UnresolvedUsingTypenameDecl>(IIDecl)) { - // FIXME: preserve source structure information. - T = Context.getDependentNameType(ETK_None, - UUDecl->getTargetNestedNameSpecifier(), - &II); } else { // If it's not plausibly a type, suppress diagnostics. Result.suppressDiagnostics(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 2f18711e24..5208f28ca6 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5288,15 +5288,31 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, return CreateLocInfoType(T, TSI).getAsOpaquePtr(); } - T = Context.getDependentNameType(ETK_Typename, NNS, - cast<TemplateSpecializationType>(T)); + // TODO: it's really silly that we make a template specialization + // type earlier only to drop it again here. + TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T); + DependentTemplateName *DTN = + TST->getTemplateName().getAsDependentTemplateName(); + assert(DTN && "dependent template has non-dependent name?"); + T = Context.getDependentTemplateSpecializationType(ETK_Typename, NNS, + DTN->getIdentifier(), + TST->getNumArgs(), + TST->getArgs()); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); + DependentTemplateSpecializationTypeLoc TL = + cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc()); + if (InnerTSI) { + TemplateSpecializationTypeLoc TSTL = + cast<TemplateSpecializationTypeLoc>(InnerTSI->getTypeLoc()); + TL.setLAngleLoc(TSTL.getLAngleLoc()); + TL.setRAngleLoc(TSTL.getRAngleLoc()); + for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I) + TL.setArgLocInfo(I, TSTL.getArgLocInfo(I)); + } else { + TL.initializeLocal(SourceLocation()); + } TL.setKeywordLoc(TypenameLoc); TL.setQualifierRange(SS.getRange()); - - // FIXME: the inner type is a template here; remember its full source info - TL.setNameLoc(InnerTSI ? InnerTSI->getTypeLoc().getBeginLoc() : TemplateLoc); return CreateLocInfoType(T, TSI).getAsOpaquePtr(); } @@ -5425,87 +5441,9 @@ namespace { Sema::OwningExprResult TransformExpr(Expr *E) { return getSema().Owned(E->Retain()); } - - /// \brief Transforms a typename type by determining whether the type now - /// refers to a member of the current instantiation, and then - /// type-checking and building an ElaboratedType (when possible). - QualType TransformDependentNameType(TypeLocBuilder &TLB, - DependentNameTypeLoc TL, - QualType ObjectType); }; } -QualType -CurrentInstantiationRebuilder::TransformDependentNameType(TypeLocBuilder &TLB, - DependentNameTypeLoc TL, - QualType ObjectType) { - DependentNameType *T = TL.getTypePtr(); - - NestedNameSpecifier *NNS - = TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange(), - ObjectType); - if (!NNS) - return QualType(); - - // If the nested-name-specifier did not change, and we cannot compute the - // context corresponding to the nested-name-specifier, then this - // typename type will not change; exit early. - CXXScopeSpec SS; - SS.setRange(TL.getQualifierRange()); - SS.setScopeRep(NNS); - - QualType Result; - if (NNS == T->getQualifier() && getSema().computeDeclContext(SS) == 0) - Result = QualType(T, 0); - - // Rebuild the typename type, which will probably turn into a - // ElaboratedType. - else if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { - QualType NewTemplateId - = TransformType(QualType(TemplateId, 0)); - if (NewTemplateId.isNull()) - return QualType(); - - if (NNS == T->getQualifier() && - NewTemplateId == QualType(TemplateId, 0)) - Result = QualType(T, 0); - else - Result = getDerived().RebuildDependentNameType(T->getKeyword(), - NNS, NewTemplateId); - } else - Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - T->getIdentifier(), - TL.getKeywordLoc(), - TL.getQualifierRange(), - TL.getNameLoc()); - - if (Result.isNull()) - return QualType(); - - if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) { - QualType NamedT = ElabT->getNamedType(); - if (isa<TemplateSpecializationType>(NamedT)) { - TemplateSpecializationTypeLoc NamedTLoc - = TLB.push<TemplateSpecializationTypeLoc>(NamedT); - // FIXME: fill locations - NamedTLoc.initializeLocal(TL.getNameLoc()); - } else { - TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); - } - ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); - } - else { - DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); - NewTL.setNameLoc(TL.getNameLoc()); - } - return Result; -} - /// \brief Rebuilds a type within the context of the current instantiation. /// /// The type \p T is part of the type of an out-of-line member definition of diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 88ceeca58a..403d5543a6 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2624,6 +2624,18 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, OnlyDeduced, Depth, Used); break; + case Type::DependentTemplateSpecialization: { + const DependentTemplateSpecializationType *Spec + = cast<DependentTemplateSpecializationType>(T); + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, Spec->getQualifier(), + OnlyDeduced, Depth, Used); + for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) + MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth, + Used); + break; + } + case Type::TypeOf: if (!OnlyDeduced) MarkUsedTemplateParameters(SemaRef, diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index bec929dabf..48c17cde43 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1492,6 +1492,28 @@ namespace { // FIXME: load appropriate source location. TL.setNameLoc(DS.getTypeSpecTypeLoc()); } + void VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); + if (Keyword == ETK_Typename) { + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo); + if (TInfo) { + TL.copy(cast<DependentTemplateSpecializationTypeLoc>( + TInfo->getTypeLoc())); + return; + } + } + TL.initializeLocal(SourceLocation()); + TL.setKeywordLoc(Keyword != ETK_None + ? DS.getTypeSpecTypeLoc() + : SourceLocation()); + const CXXScopeSpec& SS = DS.getTypeSpecScope(); + TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange()); + // FIXME: load appropriate source location. + TL.setNameLoc(DS.getTypeSpecTypeLoc()); + } void VisitTypeLoc(TypeLoc TL) { // FIXME: add other typespec types and change this to an assert. diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 26caaadd49..100ddcb141 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -533,16 +533,27 @@ public: /// By default, builds a new DependentNameType type from the /// nested-name-specifier and the given type. Subclasses may override /// this routine to provide different behavior. - QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType T) { - if (NNS->isDependent()) { - // If the name is still dependent, just build a new dependent name type. - CXXScopeSpec SS; - SS.setScopeRep(NNS); - if (!SemaRef.computeDeclContext(SS)) - return SemaRef.Context.getDependentNameType(Keyword, NNS, - cast<TemplateSpecializationType>(T)); - } + QualType RebuildDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo &Args) { + // Rebuild the template name. + // TODO: avoid TemplateName abstraction + TemplateName InstName = + getDerived().RebuildTemplateName(NNS, *Name, QualType()); + + // If it's still dependent, make a dependent specialization. + if (InstName.getAsDependentTemplateName()) + return SemaRef.Context.getDependentTemplateSpecializationType( + Keyword, NNS, Name, Args); + + // Otherwise, make an elaborated type wrapping a non-dependent + // specialization. + QualType T = + getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); + if (T.isNull()) return QualType(); return SemaRef.Context.getElaboratedType(Keyword, NNS, T); } @@ -3298,46 +3309,23 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, if (!NNS) return QualType(); - QualType Result; - - if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { - QualType NewTemplateId - = getDerived().TransformType(QualType(TemplateId, 0)); - if (NewTemplateId.isNull()) - return QualType(); - - if (!getDerived().AlwaysRebuild() && - NNS == T->getQualifier() && - NewTemplateId == QualType(TemplateId, 0)) - return QualType(T, 0); - - Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - NewTemplateId); - } else { - Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - T->getIdentifier(), - TL.getKeywordLoc(), - TL.getQualifierRange(), - TL.getNameLoc()); - } + QualType Result + = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, + T->getIdentifier(), + TL.getKeywordLoc(), + TL.getQualifierRange(), + TL.getNameLoc()); if (Result.isNull()) return QualType(); if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) { QualType NamedT = ElabT->getNamedType(); - if (isa<TemplateSpecializationType>(NamedT)) { - TemplateSpecializationTypeLoc NamedTLoc - = TLB.push<TemplateSpecializationTypeLoc>(NamedT); - // FIXME: fill locations - NamedTLoc.initializeLocal(TL.getNameLoc()); - } else { - TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); - } + TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); + ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); NewTL.setQualifierRange(TL.getQualifierRange()); - } - else { + } else { DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); NewTL.setQualifierRange(TL.getQualifierRange()); @@ -3347,6 +3335,61 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, } template<typename Derived> +QualType TreeTransform<Derived>:: + TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + QualType ObjectType) { + DependentTemplateSpecializationType *T = TL.getTypePtr(); + + NestedNameSpecifier *NNS + = getDerived().TransformNestedNameSpecifier(T->getQualifier(), + TL.getQualifierRange(), + ObjectType); + if (!NNS) + return QualType(); + + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + + for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I) { + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(TL.getArgLoc(I), Loc)) + return QualType(); + NewTemplateArgs.addArgument(Loc); + } + + QualType Result = getDerived().RebuildDependentTemplateSpecializationType( + T->getKeyword(), + NNS, + T->getIdentifier(), + TL.getNameLoc(), + NewTemplateArgs); + if (Result.isNull()) + return QualType(); + + if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) { + QualType NamedT = ElabT->getNamedType(); + + // Copy information relevant to the template specialization. + TemplateSpecializationTypeLoc NamedTL + = TLB.push<TemplateSpecializationTypeLoc>(NamedT); + NamedTL.setLAngleLoc(TL.getLAngleLoc()); + NamedTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + NamedTL.setArgLocInfo(I, TL.getArgLocInfo(I)); + + // Copy information relevant to the elaborated type. + ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setQualifierRange(TL.getQualifierRange()); + } else { + TLB.pushFullCopy(TL); + } + return Result; +} + +template<typename Derived> QualType TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB, ObjCInterfaceTypeLoc TL, |