[cfe-commits] r78292 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h test/SemaTemplate/metafun-apply.cpp
Douglas Gregor
dgregor at apple.com
Wed Aug 5 23:41:22 PDT 2009
Author: dgregor
Date: Thu Aug 6 01:41:21 2009
New Revision: 78292
URL: http://llvm.org/viewvc/llvm-project?rev=78292&view=rev
Log:
Implement transformation of template names within the generic tree
transform, then use the result for template instantiation. The generic
transformation fixes a few issues:
- It copes better with template template parameters and member
templates (when they're implemented).
- The logic used to replace template template parameters with their
arguments is now centralized in TransformDecl, so that it will apply
for other declaration-instantiation steps.
- The error-recovery strategy is normalized now, so that any error
results in a NULL TemplateName.
Modified:
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaTemplate/metafun-apply.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=78292&r1=78291&r2=78292&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Aug 6 01:41:21 2009
@@ -324,9 +324,6 @@
/// this declaration.
Decl *TransformDecl(Decl *D);
- /// \brief Transform the given template name by instantiating it.
- TemplateName TransformTemplateName(TemplateName Template);
-
/// \brief Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T);
@@ -338,15 +335,22 @@
}
Decl *TemplateInstantiator::TransformDecl(Decl *D) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast_or_null<TemplateTemplateParmDecl>(D)) {
+ // FIXME: Depth reduction
+ assert(TTP->getDepth() == 0 &&
+ "Cannot reduce depth of a template template parameter");
+ assert(TemplateArgs[TTP->getPosition()].getAsDecl() &&
+ "Wrong kind of template template argument");
+ TemplateDecl *Template
+ = dyn_cast<TemplateDecl>(TemplateArgs[TTP->getPosition()].getAsDecl());
+ assert(Template && "Expected a template");
+ return Template;
+ }
+
return SemaRef.InstantiateCurrentDeclRef(cast_or_null<NamedDecl>(D));
}
-TemplateName
-TemplateInstantiator::TransformTemplateName(TemplateName Template) {
- return getSema().InstantiateTemplateName(Template, /*FIXME*/Loc,
- TemplateArgs);
-}
-
QualType
TemplateInstantiator::TransformTemplateTypeParmType(
const TemplateTypeParmType *T) {
@@ -720,66 +724,9 @@
TemplateName
Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
const TemplateArgumentList &TemplateArgs) {
- if (TemplateTemplateParmDecl *TTP
- = dyn_cast_or_null<TemplateTemplateParmDecl>(
- Name.getAsTemplateDecl())) {
- assert(TTP->getDepth() == 0 &&
- "Cannot reduce depth of a template template parameter");
- assert(TemplateArgs[TTP->getPosition()].getAsDecl() &&
- "Wrong kind of template template argument");
- ClassTemplateDecl *ClassTemplate
- = dyn_cast<ClassTemplateDecl>(
- TemplateArgs[TTP->getPosition()].getAsDecl());
- assert(ClassTemplate && "Expected a class template");
- if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
- NestedNameSpecifier *NNS
- = InstantiateNestedNameSpecifier(QTN->getQualifier(),
- /*FIXME=*/SourceRange(Loc),
- TemplateArgs);
- if (NNS)
- return Context.getQualifiedTemplateName(NNS,
- QTN->hasTemplateKeyword(),
- ClassTemplate);
- }
-
- return TemplateName(ClassTemplate);
- } else if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
- NestedNameSpecifier *NNS
- = InstantiateNestedNameSpecifier(DTN->getQualifier(),
- /*FIXME=*/SourceRange(Loc),
- TemplateArgs);
-
- if (!NNS) // FIXME: Not the best recovery strategy.
- return Name;
-
- if (NNS->isDependent())
- return Context.getDependentTemplateName(NNS, DTN->getName());
-
- // Somewhat redundant with ActOnDependentTemplateName.
- CXXScopeSpec SS;
- SS.setRange(SourceRange(Loc));
- SS.setScopeRep(NNS);
- TemplateTy Template;
- TemplateNameKind TNK = isTemplateName(*DTN->getName(), 0, Template, &SS);
- if (TNK == TNK_Non_template) {
- Diag(Loc, diag::err_template_kw_refers_to_non_template)
- << DTN->getName();
- return Name;
- } else if (TNK == TNK_Function_template) {
- Diag(Loc, diag::err_template_kw_refers_to_non_template)
- << DTN->getName();
- return Name;
- }
-
- return Template.getAsVal<TemplateName>();
- }
-
-
-
- // FIXME: Even if we're referring to a Decl that isn't a template template
- // parameter, we may need to instantiate the outer contexts of that
- // Decl. However, this won't be needed until we implement member templates.
- return Name;
+ TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
+ DeclarationName());
+ return Instantiator.TransformTemplateName(Name);
}
TemplateArgument Sema::Instantiate(TemplateArgument Arg,
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=78292&r1=78291&r2=78292&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Aug 6 01:41:21 2009
@@ -171,8 +171,10 @@
/// \brief Transform the given template name.
///
- /// FIXME: At the moment, subclasses must override this.
- TemplateName TransformTemplateName(TemplateName Template);
+ /// By default, transforms the template name by transforming the declarations
+ /// and nested-name-specifiers that occur within the template name.
+ /// Subclasses may override this function to provide alternate behavior.
+ TemplateName TransformTemplateName(TemplateName Name);
/// \brief Transform the given template argument.
///
@@ -433,6 +435,36 @@
SourceRange Range,
bool TemplateKW,
QualType T);
+
+ /// \brief Build a new template name given a nested name specifier, a flag
+ /// indicating whether the "template" keyword was provided, and the template
+ /// that the template name refers to.
+ ///
+ /// By default, builds the new template name directly. Subclasses may override
+ /// this routine to provide different behavior.
+ TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ bool TemplateKW,
+ TemplateDecl *Template);
+
+ /// \brief Build a new template name given a nested name specifier, a flag
+ /// indicating whether the "template" keyword was provided, and a set of
+ /// overloaded function templates.
+ ///
+ /// By default, builds the new template name directly. Subclasses may override
+ /// this routine to provide different behavior.
+ TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ bool TemplateKW,
+ OverloadedFunctionDecl *Ovl);
+
+ /// \brief Build a new template name given a nested name specifier and the
+ /// name that is referred to as a template.
+ ///
+ /// By default, performs semantic analysis to determine whether the name can
+ /// be resolved to a specific template, then builds the appropriate kind of
+ /// template name. Subclasses may override this routine to provide different
+ /// behavior.
+ TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ const IdentifierInfo &II);
};
template<typename Derived>
@@ -477,6 +509,9 @@
case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::TypeSpec: {
QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0));
+ if (T.isNull())
+ return 0;
+
if (!getDerived().AlwaysRebuild() &&
Prefix == NNS->getPrefix() &&
T == QualType(NNS->getAsType(), 0))
@@ -493,6 +528,88 @@
}
template<typename Derived>
+TemplateName
+TreeTransform<Derived>::TransformTemplateName(TemplateName Name) {
+ if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
+ NestedNameSpecifier *NNS
+ = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
+ /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+ if (!NNS)
+ return TemplateName();
+
+ if (TemplateDecl *Template = QTN->getTemplateDecl()) {
+ TemplateDecl *TransTemplate
+ = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Template));
+ if (!TransTemplate)
+ return TemplateName();
+
+ if (!getDerived().AlwaysRebuild() &&
+ NNS == QTN->getQualifier() &&
+ TransTemplate == Template)
+ return Name;
+
+ return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
+ TransTemplate);
+ }
+
+ OverloadedFunctionDecl *Ovl = QTN->getOverloadedFunctionDecl();
+ assert(Ovl && "Not a template name or an overload set?");
+ OverloadedFunctionDecl *TransOvl
+ = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl));
+ if (!TransOvl)
+ return TemplateName();
+
+ if (!getDerived().AlwaysRebuild() &&
+ NNS == QTN->getQualifier() &&
+ TransOvl == Ovl)
+ return Name;
+
+ return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
+ TransOvl);
+ }
+
+ if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+ NestedNameSpecifier *NNS
+ = getDerived().TransformNestedNameSpecifier(DTN->getQualifier(),
+ /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+ if (!NNS)
+ return TemplateName();
+
+ if (!getDerived().AlwaysRebuild() &&
+ NNS == DTN->getQualifier())
+ return Name;
+
+ return getDerived().RebuildTemplateName(NNS, *DTN->getName());
+ }
+
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ TemplateDecl *TransTemplate
+ = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Template));
+ if (!TransTemplate)
+ return TemplateName();
+
+ if (!getDerived().AlwaysRebuild() &&
+ TransTemplate == Template)
+ return Name;
+
+ return TemplateName(TransTemplate);
+ }
+
+ OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl();
+ assert(Ovl && "Not a template name or an overload set?");
+ OverloadedFunctionDecl *TransOvl
+ = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl));
+ if (!TransOvl)
+ return TemplateName();
+
+ if (!getDerived().AlwaysRebuild() &&
+ TransOvl == Ovl)
+ return Name;
+
+ return TemplateName(TransOvl);
+}
+
+template<typename Derived>
TemplateArgument
TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
switch (Arg.getKind()) {
@@ -1343,6 +1460,51 @@
return 0;
}
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ bool TemplateKW,
+ TemplateDecl *Template) {
+ return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW,
+ Template);
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ bool TemplateKW,
+ OverloadedFunctionDecl *Ovl) {
+ return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, Ovl);
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ const IdentifierInfo &II) {
+ if (Qualifier->isDependent())
+ return SemaRef.Context.getDependentTemplateName(Qualifier, &II);
+
+ // Somewhat redundant with ActOnDependentTemplateName.
+ CXXScopeSpec SS;
+ SS.setRange(SourceRange(getDerived().getBaseLocation()));
+ SS.setScopeRep(Qualifier);
+ Sema::TemplateTy Template;
+ TemplateNameKind TNK = SemaRef.isTemplateName(II, 0, Template, &SS);
+ if (TNK == TNK_Non_template) {
+ SemaRef.Diag(getDerived().getBaseLocation(),
+ diag::err_template_kw_refers_to_non_template)
+ << &II;
+ return TemplateName();
+ } else if (TNK == TNK_Function_template) {
+ SemaRef.Diag(getDerived().getBaseLocation(),
+ diag::err_template_kw_refers_to_non_template)
+ << &II;
+ return TemplateName();
+ }
+
+ return Template.getAsVal<TemplateName>();
+}
+
} // end namespace clang
#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H
Modified: cfe/trunk/test/SemaTemplate/metafun-apply.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/metafun-apply.cpp?rev=78292&r1=78291&r2=78292&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/metafun-apply.cpp (original)
+++ cfe/trunk/test/SemaTemplate/metafun-apply.cpp Thu Aug 6 01:41:21 2009
@@ -35,7 +35,8 @@
apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}} \
// FIXME: expected-error{{unexpected type name 'type': expected expression}}
- apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}}
+ apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} \
+ // FIXME: expected-error{{unexpected type name 'type': expected expression}}
}
More information about the cfe-commits
mailing list