diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 13 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 34 |
3 files changed, 53 insertions, 10 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3a18f9676b..7f686369a8 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1816,6 +1816,19 @@ public: virtual TypeResult ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, const IdentifierInfo &II, SourceLocation IdLoc); + + /// \brief Called when the parser has parsed a C++ typename + /// specifier that ends in a template-id, e.g., + /// "typename MetaFun::template apply<T1, T2>". + /// + /// \param TypenameLoc the location of the 'typename' keyword + /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). + /// \param TemplateLoc the location of the 'template' keyword, if any. + /// \param Ty the type that the typename specifier refers to. + virtual TypeResult + ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, + SourceLocation TemplateLoc, TypeTy *Ty); + QualType CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, SourceRange Range); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 591f323347..5db19a59ac 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2105,6 +2105,22 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, return T.getAsOpaquePtr(); } +Sema::TypeResult +Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, + SourceLocation TemplateLoc, TypeTy *Ty) { + QualType T = QualType::getFromOpaquePtr(Ty); + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + const TemplateSpecializationType *TemplateId + = T->getAsTemplateSpecializationType(); + assert(TemplateId && "Expected a template specialization type"); + + if (NNS->isDependent()) + return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr(); + + return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr(); +} + /// \brief Build the type that describes a C++ typename specifier, /// e.g., "typename T::type". QualType diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 2f12716b72..a041d06bf2 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -497,6 +497,15 @@ InstantiateQualifiedNameType(const QualifiedNameType *T, QualType TemplateTypeInstantiator:: InstantiateTypenameType(const TypenameType *T, unsigned Quals) const { + if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { + // When the typename type refers to a template-id, the template-id + // is dependent and has enough information to instantiate the + // result of the typename type. Since we don't care about keeping + // the spelling of the typename type in template instantiations, + // we just instantiate the template-id. + return InstantiateTemplateSpecializationType(TemplateId, Quals); + } + NestedNameSpecifier *NNS = SemaRef.InstantiateNestedNameSpecifier(T->getQualifier(), SourceRange(Loc), @@ -504,7 +513,7 @@ InstantiateTypenameType(const TypenameType *T, unsigned Quals) const { if (!NNS) return QualType(); - return SemaRef.CheckTypenameType(NNS, *T->getName(), SourceRange(Loc)); + return SemaRef.CheckTypenameType(NNS, *T->getIdentifier(), SourceRange(Loc)); } QualType @@ -801,10 +810,20 @@ Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS, } switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - // FIXME: Implement this lookup! - assert(false && "Cannot instantiate this nested-name-specifier"); + case NestedNameSpecifier::Identifier: { + assert(Prefix && + "Can't have an identifier nested-name-specifier with no prefix"); + CXXScopeSpec SS; + // FIXME: The source location information is all wrong. + SS.setRange(Range); + SS.setScopeRep(Prefix); + return static_cast<NestedNameSpecifier *>( + ActOnCXXNestedNameSpecifier(0, SS, + Range.getEnd(), + Range.getEnd(), + *NNS->getAsIdentifier())); break; + } case NestedNameSpecifier::Namespace: case NestedNameSpecifier::Global: @@ -816,9 +835,6 @@ Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS, if (!T->isDependentType()) return NNS; - // FIXME: We won't be able to perform the instantiation here when - // the template-name is dependent, e.g., we have something like - // "T::template apply<U>::type". T = InstantiateType(T, TemplateArgs, NumTemplateArgs, Range.getBegin(), DeclarationName()); if (T.isNull()) @@ -826,9 +842,7 @@ Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS, if (T->isRecordType() || (getLangOptions().CPlusPlus0x && T->isEnumeralType())) { - // Note that T.getTypePtr(), below, strips cv-qualifiers. This is - // perfectly reasonable, since cv-qualified types in - // nested-name-specifiers don't matter. + assert(T.getCVRQualifiers() == 0 && "Can't get cv-qualifiers here"); return NestedNameSpecifier::Create(Context, Prefix, NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate, T.getTypePtr()); |