Improve the representation of template names in the AST. This
representation handles the various ways in which one can name a
template, including unqualified references ("vector"), qualified
references ("std::vector"), and dependent template names
("MetaFun::template apply").
One immediate effect of this change is that the representation of
nested-name-specifiers in type names for class template
specializations (e.g., std::vector<int>) is more accurate. Rather than
representing std::vector<int> as
std::(vector<int>)
we represent it as
(std::vector)<int>
which more closely follows the C++ grammar.
Additionally, templates are no longer represented as declarations
(DeclPtrTy) in Parse-Sema interactions. Instead, I've introduced a new
OpaquePtr type (TemplateTy) that holds the representation of a
TemplateName. This will simplify the handling of dependent
template-names, once we get there.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68074 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 773a2b1..56a016d 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -27,19 +27,23 @@
/// passed to indicate the C++ scope in which the identifier will be
/// found.
TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S,
- DeclPtrTy &Template,
+ TemplateTy &TemplateResult,
const CXXScopeSpec *SS) {
NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName);
+ TemplateNameKind TNK = TNK_Non_template;
+ TemplateDecl *Template = 0;
+
if (IIDecl) {
- if (isa<TemplateDecl>(IIDecl)) {
- Template = DeclPtrTy::make(IIDecl);
+ if ((Template = dyn_cast<TemplateDecl>(IIDecl))) {
if (isa<FunctionTemplateDecl>(IIDecl))
- return TNK_Function_template;
- if (isa<ClassTemplateDecl>(IIDecl))
- return TNK_Class_template;
- assert(isa<TemplateTemplateParmDecl>(IIDecl) && "Unknown TemplateDecl");
- return TNK_Template_template_parm;
+ TNK = TNK_Function_template;
+ else if (isa<ClassTemplateDecl>(IIDecl))
+ TNK = TNK_Class_template;
+ else if (isa<TemplateTemplateParmDecl>(IIDecl))
+ TNK = TNK_Template_template_parm;
+ else
+ assert(false && "Unknown template declaration kind");
} else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(IIDecl)) {
// C++ [temp.local]p1:
// Like normal (non-template) classes, class templates have an
@@ -54,12 +58,12 @@
// specialization.
if (Record->isInjectedClassName()) {
Record = cast<CXXRecordDecl>(Context.getCanonicalDecl(Record));
- if ((Template = DeclPtrTy::make(Record->getDescribedClassTemplate())))
- return TNK_Class_template;
- if (ClassTemplateSpecializationDecl *Spec
+ if ((Template = Record->getDescribedClassTemplate()))
+ TNK = TNK_Class_template;
+ else if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
- Template = DeclPtrTy::make(Spec->getSpecializedTemplate());
- return TNK_Class_template;
+ Template = Spec->getSpecializedTemplate();
+ TNK = TNK_Class_template;
}
}
}
@@ -67,7 +71,7 @@
// FIXME: What follows is a gross hack.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) {
if (FD->getType()->isDependentType()) {
- Template = DeclPtrTy::make(FD);
+ TemplateResult = TemplateTy::make(FD);
return TNK_Function_template;
}
} else if (OverloadedFunctionDecl *Ovl
@@ -76,13 +80,25 @@
FEnd = Ovl->function_end();
F != FEnd; ++F) {
if ((*F)->getType()->isDependentType()) {
- Template = DeclPtrTy::make(Ovl);
+ TemplateResult = TemplateTy::make(Ovl);
return TNK_Function_template;
}
}
}
+
+ if (TNK != TNK_Non_template) {
+ if (SS && SS->isSet() && !SS->isInvalid()) {
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier *>(SS->getScopeRep());
+ TemplateResult
+ = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier,
+ false,
+ Template));
+ } else
+ TemplateResult = TemplateTy::make(TemplateName(Template));
+ }
}
- return TNK_Non_template;
+ return TNK;
}
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
@@ -700,27 +716,30 @@
}
}
-QualType Sema::CheckClassTemplateId(ClassTemplateDecl *ClassTemplate,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
- SourceLocation RAngleLoc) {
+QualType Sema::CheckTemplateIdType(TemplateName Name,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation RAngleLoc) {
+ TemplateDecl *Template = Name.getAsTemplateDecl();
+ assert(Template && "Cannot handle dependent template-names yet");
+
// Check that the template argument list is well-formed for this
// template.
llvm::SmallVector<TemplateArgument, 16> ConvertedTemplateArgs;
- if (CheckTemplateArgumentList(ClassTemplate, TemplateLoc, LAngleLoc,
+ if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc,
TemplateArgs, NumTemplateArgs, RAngleLoc,
ConvertedTemplateArgs))
return QualType();
assert((ConvertedTemplateArgs.size() ==
- ClassTemplate->getTemplateParameters()->size()) &&
+ Template->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
QualType CanonType;
- if (ClassTemplateSpecializationType::anyDependentTemplateArguments(
+ if (TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs,
NumTemplateArgs)) {
// This class template specialization is a dependent
@@ -731,10 +750,11 @@
//
// template<typename T, typename U = T> struct A;
- CanonType = Context.getClassTemplateSpecializationType(ClassTemplate,
+ CanonType = Context.getTemplateSpecializationType(Name,
&ConvertedTemplateArgs[0],
ConvertedTemplateArgs.size());
- } else {
+ } else if (ClassTemplateDecl *ClassTemplate
+ = dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
@@ -764,35 +784,26 @@
// Build the fully-sugared type for this class template
// specialization, which refers back to the class template
// specialization we created or found.
- return Context.getClassTemplateSpecializationType(ClassTemplate,
- TemplateArgs,
- NumTemplateArgs,
- CanonType);
+ return Context.getTemplateSpecializationType(Name, TemplateArgs,
+ NumTemplateArgs, CanonType);
}
Action::TypeResult
-Sema::ActOnClassTemplateId(DeclPtrTy TemplateD, SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc,
- const CXXScopeSpec *SS) {
- TemplateDecl *Template = cast<TemplateDecl>(TemplateD.getAs<Decl>());
- ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(Template);
+Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc) {
+ TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
- QualType Result = CheckClassTemplateId(ClassTemplate, TemplateLoc,
- LAngleLoc,
- &TemplateArgs[0],
- TemplateArgs.size(),
- RAngleLoc);
+ QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc,
+ &TemplateArgs[0], TemplateArgs.size(),
+ RAngleLoc);
- if (SS)
- Result = getQualifiedNameType(*SS, Result);
-
TemplateArgsIn.release();
return Result.getAsOpaquePtr();
}
@@ -1795,7 +1806,7 @@
Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
SourceLocation KWLoc,
const CXXScopeSpec &SS,
- DeclPtrTy TemplateD,
+ TemplateTy TemplateD,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
@@ -1804,10 +1815,9 @@
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
// Find the class template we're specializing
+ TemplateName Name = TemplateD.getAsVal<TemplateName>();
ClassTemplateDecl *ClassTemplate
- = dyn_cast_or_null<ClassTemplateDecl>(TemplateD.getAs<Decl>());
- if (!ClassTemplate)
- return true;
+ = cast<ClassTemplateDecl>(Name.getAsTemplateDecl());
// Check the validity of the template headers that introduce this
// template.
@@ -1937,11 +1947,11 @@
// name based on the "canonical" representation used to store the
// template arguments in the specialization.
QualType WrittenTy
- = Context.getClassTemplateSpecializationType(ClassTemplate,
- &TemplateArgs[0],
- TemplateArgs.size(),
+ = Context.getTemplateSpecializationType(Name,
+ &TemplateArgs[0],
+ TemplateArgs.size(),
Context.getTypeDeclType(Specialization));
- Specialization->setTypeAsWritten(getQualifiedNameType(SS, WrittenTy));
+ Specialization->setTypeAsWritten(WrittenTy);
TemplateArgsIn.release();
// C++ [temp.expl.spec]p9: