aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h13
-rw-r--r--lib/Sema/SemaTemplate.cpp16
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp34
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());