зеркало из https://github.com/microsoft/clang-1.git
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78292 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
38b02b912e
Коммит
d1067e5a0a
|
@ -324,9 +324,6 @@ namespace {
|
|||
/// 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,13 +335,20 @@ Sema::OwningExprResult TemplateInstantiator::TransformExpr(Expr *E) {
|
|||
}
|
||||
|
||||
Decl *TemplateInstantiator::TransformDecl(Decl *D) {
|
||||
return SemaRef.InstantiateCurrentDeclRef(cast_or_null<NamedDecl>(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;
|
||||
}
|
||||
|
||||
TemplateName
|
||||
TemplateInstantiator::TransformTemplateName(TemplateName Template) {
|
||||
return getSema().InstantiateTemplateName(Template, /*FIXME*/Loc,
|
||||
TemplateArgs);
|
||||
return SemaRef.InstantiateCurrentDeclRef(cast_or_null<NamedDecl>(D));
|
||||
}
|
||||
|
||||
QualType
|
||||
|
@ -720,66 +724,9 @@ Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
|
|||
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,
|
||||
|
|
|
@ -171,8 +171,10 @@ public:
|
|||
|
||||
/// \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 @@ public:
|
|||
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 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
|
|||
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))
|
||||
|
@ -492,6 +527,88 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
|
|||
return 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -1343,6 +1460,51 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
|
|||
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
|
||||
|
|
|
@ -35,7 +35,8 @@ void test() {
|
|||
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}}
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче