2009-02-28 03:31:52 +08:00
|
|
|
//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
//
|
|
|
|
// This file implements C++ template instantiation.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
|
|
|
|
#include "Sema.h"
|
2009-08-05 00:50:30 +08:00
|
|
|
#include "TreeTransform.h"
|
2009-05-27 04:50:29 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2009-02-28 03:31:52 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/Expr.h"
|
|
|
|
#include "clang/AST/DeclTemplate.h"
|
|
|
|
#include "clang/Parse/DeclSpec.h"
|
|
|
|
#include "clang/Basic/LangOptions.h"
|
2009-02-28 08:25:32 +08:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2009-02-28 03:31:52 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2009-03-11 02:03:33 +08:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation Support
|
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
|
2009-05-15 07:26:13 +08:00
|
|
|
/// \brief Retrieve the template argument list that should be used to
|
|
|
|
/// instantiate the given declaration.
|
|
|
|
const TemplateArgumentList &
|
|
|
|
Sema::getTemplateInstantiationArgs(NamedDecl *D) {
|
2009-06-26 08:10:03 +08:00
|
|
|
// Template arguments for a class template specialization.
|
2009-05-15 07:26:13 +08:00
|
|
|
if (ClassTemplateSpecializationDecl *Spec
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(D))
|
2009-08-03 07:24:31 +08:00
|
|
|
return Spec->getTemplateInstantiationArgs();
|
2009-05-15 07:26:13 +08:00
|
|
|
|
2009-06-26 08:10:03 +08:00
|
|
|
// Template arguments for a function template specialization.
|
|
|
|
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
|
|
|
|
if (const TemplateArgumentList *TemplateArgs
|
|
|
|
= Function->getTemplateSpecializationArgs())
|
|
|
|
return *TemplateArgs;
|
|
|
|
|
|
|
|
// Template arguments for a member of a class template specialization.
|
2009-05-15 07:26:13 +08:00
|
|
|
DeclContext *EnclosingTemplateCtx = D->getDeclContext();
|
|
|
|
while (!isa<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx)) {
|
|
|
|
assert(!EnclosingTemplateCtx->isFileContext() &&
|
|
|
|
"Tried to get the instantiation arguments of a non-template");
|
|
|
|
EnclosingTemplateCtx = EnclosingTemplateCtx->getParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassTemplateSpecializationDecl *EnclosingTemplate
|
|
|
|
= cast<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx);
|
2009-08-03 07:24:31 +08:00
|
|
|
return EnclosingTemplate->getTemplateInstantiationArgs();
|
2009-05-15 07:26:13 +08:00
|
|
|
}
|
|
|
|
|
2009-03-10 08:06:19 +08:00
|
|
|
Sema::InstantiatingTemplate::
|
|
|
|
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
|
2009-05-19 01:01:57 +08:00
|
|
|
Decl *Entity,
|
2009-03-10 08:06:19 +08:00
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: SemaRef(SemaRef) {
|
2009-03-11 04:44:00 +08:00
|
|
|
|
|
|
|
Invalid = CheckInstantiationDepth(PointOfInstantiation,
|
|
|
|
InstantiationRange);
|
|
|
|
if (!Invalid) {
|
|
|
|
ActiveTemplateInstantiation Inst;
|
|
|
|
Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
|
|
|
|
Inst.PointOfInstantiation = PointOfInstantiation;
|
|
|
|
Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
|
2009-03-13 02:36:18 +08:00
|
|
|
Inst.TemplateArgs = 0;
|
|
|
|
Inst.NumTemplateArgs = 0;
|
2009-03-11 04:44:00 +08:00
|
|
|
Inst.InstantiationRange = InstantiationRange;
|
|
|
|
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
|
|
|
|
Invalid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
TemplateDecl *Template,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: SemaRef(SemaRef) {
|
|
|
|
|
|
|
|
Invalid = CheckInstantiationDepth(PointOfInstantiation,
|
|
|
|
InstantiationRange);
|
|
|
|
if (!Invalid) {
|
2009-03-10 08:06:19 +08:00
|
|
|
ActiveTemplateInstantiation Inst;
|
2009-03-11 04:44:00 +08:00
|
|
|
Inst.Kind
|
|
|
|
= ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
|
2009-03-10 08:06:19 +08:00
|
|
|
Inst.PointOfInstantiation = PointOfInstantiation;
|
2009-03-11 04:44:00 +08:00
|
|
|
Inst.Entity = reinterpret_cast<uintptr_t>(Template);
|
|
|
|
Inst.TemplateArgs = TemplateArgs;
|
|
|
|
Inst.NumTemplateArgs = NumTemplateArgs;
|
2009-03-10 08:06:19 +08:00
|
|
|
Inst.InstantiationRange = InstantiationRange;
|
|
|
|
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
|
|
|
|
Invalid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-02 06:01:06 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
FunctionTemplateDecl *FunctionTemplate,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
|
|
|
ActiveTemplateInstantiation::InstantiationKind Kind,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: SemaRef(SemaRef) {
|
|
|
|
|
|
|
|
Invalid = CheckInstantiationDepth(PointOfInstantiation,
|
|
|
|
InstantiationRange);
|
|
|
|
if (!Invalid) {
|
|
|
|
ActiveTemplateInstantiation Inst;
|
|
|
|
Inst.Kind = Kind;
|
|
|
|
Inst.PointOfInstantiation = PointOfInstantiation;
|
|
|
|
Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate);
|
|
|
|
Inst.TemplateArgs = TemplateArgs;
|
|
|
|
Inst.NumTemplateArgs = NumTemplateArgs;
|
|
|
|
Inst.InstantiationRange = InstantiationRange;
|
|
|
|
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
|
|
|
|
Invalid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-11 07:47:09 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
ClassTemplatePartialSpecializationDecl *PartialSpec,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: SemaRef(SemaRef) {
|
|
|
|
|
|
|
|
Invalid = CheckInstantiationDepth(PointOfInstantiation,
|
|
|
|
InstantiationRange);
|
|
|
|
if (!Invalid) {
|
|
|
|
ActiveTemplateInstantiation Inst;
|
|
|
|
Inst.Kind
|
2009-07-02 06:01:06 +08:00
|
|
|
= ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
|
2009-06-11 07:47:09 +08:00
|
|
|
Inst.PointOfInstantiation = PointOfInstantiation;
|
|
|
|
Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
|
|
|
|
Inst.TemplateArgs = TemplateArgs;
|
|
|
|
Inst.NumTemplateArgs = NumTemplateArgs;
|
|
|
|
Inst.InstantiationRange = InstantiationRange;
|
|
|
|
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
|
|
|
|
Invalid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-19 01:01:57 +08:00
|
|
|
void Sema::InstantiatingTemplate::Clear() {
|
|
|
|
if (!Invalid) {
|
2009-03-10 08:06:19 +08:00
|
|
|
SemaRef.ActiveTemplateInstantiations.pop_back();
|
2009-05-19 01:01:57 +08:00
|
|
|
Invalid = true;
|
|
|
|
}
|
2009-03-10 08:06:19 +08:00
|
|
|
}
|
|
|
|
|
2009-03-11 04:44:00 +08:00
|
|
|
bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
SourceRange InstantiationRange) {
|
|
|
|
if (SemaRef.ActiveTemplateInstantiations.size()
|
|
|
|
<= SemaRef.getLangOptions().InstantiationDepth)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SemaRef.Diag(PointOfInstantiation,
|
|
|
|
diag::err_template_recursion_depth_exceeded)
|
|
|
|
<< SemaRef.getLangOptions().InstantiationDepth
|
|
|
|
<< InstantiationRange;
|
|
|
|
SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
|
|
|
|
<< SemaRef.getLangOptions().InstantiationDepth;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-03-11 02:03:33 +08:00
|
|
|
/// \brief Prints the current instantiation stack through a series of
|
|
|
|
/// notes.
|
|
|
|
void Sema::PrintInstantiationStack() {
|
2009-07-02 06:01:06 +08:00
|
|
|
// FIXME: In all of these cases, we need to show the template arguments
|
2009-03-11 02:03:33 +08:00
|
|
|
for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
|
|
|
|
Active = ActiveTemplateInstantiations.rbegin(),
|
|
|
|
ActiveEnd = ActiveTemplateInstantiations.rend();
|
|
|
|
Active != ActiveEnd;
|
|
|
|
++Active) {
|
2009-03-11 04:44:00 +08:00
|
|
|
switch (Active->Kind) {
|
|
|
|
case ActiveTemplateInstantiation::TemplateInstantiation: {
|
2009-05-19 01:01:57 +08:00
|
|
|
Decl *D = reinterpret_cast<Decl *>(Active->Entity);
|
|
|
|
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
|
|
|
|
unsigned DiagID = diag::note_template_member_class_here;
|
|
|
|
if (isa<ClassTemplateSpecializationDecl>(Record))
|
|
|
|
DiagID = diag::note_template_class_instantiation_here;
|
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
DiagID)
|
|
|
|
<< Context.getTypeDeclType(Record)
|
|
|
|
<< Active->InstantiationRange;
|
2009-07-25 04:34:43 +08:00
|
|
|
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
|
2009-06-26 08:10:03 +08:00
|
|
|
unsigned DiagID;
|
|
|
|
if (Function->getPrimaryTemplate())
|
|
|
|
DiagID = diag::note_function_template_spec_here;
|
|
|
|
else
|
|
|
|
DiagID = diag::note_template_member_function_here;
|
2009-05-19 01:01:57 +08:00
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
DiagID)
|
|
|
|
<< Function
|
|
|
|
<< Active->InstantiationRange;
|
2009-07-25 04:34:43 +08:00
|
|
|
} else {
|
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_template_static_data_member_def_here)
|
|
|
|
<< cast<VarDecl>(D)
|
|
|
|
<< Active->InstantiationRange;
|
2009-05-19 01:01:57 +08:00
|
|
|
}
|
2009-03-11 04:44:00 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
|
|
|
|
TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
|
|
|
|
std::string TemplateArgsStr
|
2009-03-31 06:58:21 +08:00
|
|
|
= TemplateSpecializationType::PrintTemplateArgumentList(
|
2009-07-02 06:01:06 +08:00
|
|
|
Active->TemplateArgs,
|
2009-05-30 04:38:28 +08:00
|
|
|
Active->NumTemplateArgs,
|
|
|
|
Context.PrintingPolicy);
|
2009-03-11 04:44:00 +08:00
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_default_arg_instantiation_here)
|
|
|
|
<< (Template->getNameAsString() + TemplateArgsStr)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
2009-06-11 07:47:09 +08:00
|
|
|
|
2009-07-02 06:01:06 +08:00
|
|
|
case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
|
|
|
|
FunctionTemplateDecl *FnTmpl
|
|
|
|
= cast<FunctionTemplateDecl>((Decl *)Active->Entity);
|
2009-06-11 07:47:09 +08:00
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
2009-07-02 06:01:06 +08:00
|
|
|
diag::note_explicit_template_arg_substitution_here)
|
|
|
|
<< FnTmpl << Active->InstantiationRange;
|
2009-06-11 07:47:09 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-07-02 06:01:06 +08:00
|
|
|
|
|
|
|
case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
|
|
|
|
if (ClassTemplatePartialSpecializationDecl *PartialSpec
|
|
|
|
= dyn_cast<ClassTemplatePartialSpecializationDecl>(
|
|
|
|
(Decl *)Active->Entity)) {
|
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_partial_spec_deduct_instantiation_here)
|
|
|
|
<< Context.getTypeDeclType(PartialSpec)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
} else {
|
|
|
|
FunctionTemplateDecl *FnTmpl
|
|
|
|
= cast<FunctionTemplateDecl>((Decl *)Active->Entity);
|
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_function_template_deduction_instantiation_here)
|
|
|
|
<< FnTmpl << Active->InstantiationRange;
|
|
|
|
}
|
|
|
|
break;
|
2009-06-11 07:47:09 +08:00
|
|
|
|
2009-03-11 04:44:00 +08:00
|
|
|
}
|
2009-03-11 02:03:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-14 15:33:30 +08:00
|
|
|
bool Sema::isSFINAEContext() const {
|
|
|
|
using llvm::SmallVector;
|
|
|
|
for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
|
|
|
|
Active = ActiveTemplateInstantiations.rbegin(),
|
|
|
|
ActiveEnd = ActiveTemplateInstantiations.rend();
|
|
|
|
Active != ActiveEnd;
|
|
|
|
++Active) {
|
|
|
|
|
|
|
|
switch(Active->Kind) {
|
2009-07-02 06:01:06 +08:00
|
|
|
case ActiveTemplateInstantiation::TemplateInstantiation:
|
|
|
|
// This is a template instantiation, so there is no SFINAE.
|
|
|
|
return false;
|
|
|
|
|
2009-06-14 15:33:30 +08:00
|
|
|
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
|
|
|
|
// A default template argument instantiation may or may not be a
|
|
|
|
// SFINAE context; look further up the stack.
|
|
|
|
break;
|
2009-07-02 06:01:06 +08:00
|
|
|
|
|
|
|
case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution:
|
|
|
|
case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
|
|
|
|
// We're either substitution explicitly-specified template arguments
|
|
|
|
// or deduced template arguments, so SFINAE applies.
|
|
|
|
return true;
|
2009-06-14 15:33:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-02-28 03:31:52 +08:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation for Types
|
|
|
|
//===----------------------------------------------------------------------===/
|
2009-02-28 08:25:32 +08:00
|
|
|
namespace {
|
2009-08-05 00:50:30 +08:00
|
|
|
class VISIBILITY_HIDDEN TemplateInstantiator
|
|
|
|
: public TreeTransform<TemplateInstantiator>
|
|
|
|
{
|
2009-05-12 07:53:27 +08:00
|
|
|
const TemplateArgumentList &TemplateArgs;
|
2009-02-28 08:25:32 +08:00
|
|
|
SourceLocation Loc;
|
|
|
|
DeclarationName Entity;
|
|
|
|
|
|
|
|
public:
|
2009-08-05 00:50:30 +08:00
|
|
|
TemplateInstantiator(Sema &SemaRef,
|
|
|
|
const TemplateArgumentList &TemplateArgs,
|
|
|
|
SourceLocation Loc,
|
|
|
|
DeclarationName Entity)
|
|
|
|
: TreeTransform<TemplateInstantiator>(SemaRef), TemplateArgs(TemplateArgs),
|
|
|
|
Loc(Loc), Entity(Entity) { }
|
|
|
|
|
|
|
|
/// \brief Determine whether the given type \p T has already been
|
|
|
|
/// transformed.
|
|
|
|
///
|
|
|
|
/// For the purposes of template instantiation, a type has already been
|
|
|
|
/// transformed if it is NULL or if it is not dependent.
|
|
|
|
bool AlreadyTransformed(QualType T) {
|
|
|
|
return T.isNull() || !T->isDependentType();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Returns the location of the entity being instantiated, if known.
|
|
|
|
SourceLocation getBaseLocation() { return Loc; }
|
2009-02-28 08:25:32 +08:00
|
|
|
|
2009-08-05 00:50:30 +08:00
|
|
|
/// \brief Returns the name of the entity being instantiated, if any.
|
|
|
|
DeclarationName getBaseEntity() { return Entity; }
|
|
|
|
|
|
|
|
/// \brief Transform the given declaration by instantiating a reference to
|
|
|
|
/// this declaration.
|
|
|
|
Decl *TransformDecl(Decl *D);
|
|
|
|
|
2009-08-11 13:31:07 +08:00
|
|
|
Sema::OwningStmtResult TransformStmt(Stmt *S) {
|
|
|
|
return SemaRef.InstantiateStmt(S, TemplateArgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::OwningStmtResult TransformCompoundStmt(CompoundStmt *S,
|
|
|
|
bool IsStmtExpr) {
|
|
|
|
return SemaRef.InstantiateCompoundStmt(S, TemplateArgs, IsStmtExpr);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E);
|
|
|
|
|
|
|
|
Sema::OwningExprResult
|
|
|
|
TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E);
|
|
|
|
|
2009-08-05 00:50:30 +08:00
|
|
|
/// \brief Transforms a template type parameter type by performing
|
|
|
|
/// substitution of the corresponding template type argument.
|
|
|
|
QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T);
|
2009-05-14 02:28:20 +08:00
|
|
|
};
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-08-05 00:50:30 +08:00
|
|
|
Decl *TemplateInstantiator::TransformDecl(Decl *D) {
|
2009-08-06 14:41:21 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-08-05 00:50:30 +08:00
|
|
|
return SemaRef.InstantiateCurrentDeclRef(cast_or_null<NamedDecl>(D));
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-08-11 13:31:07 +08:00
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
|
|
|
|
// FIXME: Clean this up a bit
|
|
|
|
NamedDecl *D = E->getDecl();
|
|
|
|
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
|
|
|
assert(NTTP->getDepth() == 0 && "No nested templates yet");
|
|
|
|
|
|
|
|
// If the corresponding template argument is NULL or non-existent, it's
|
|
|
|
// because we are performing instantiation from explicitly-specified
|
|
|
|
// template arguments in a function template, but there were some
|
|
|
|
// arguments left unspecified.
|
|
|
|
if (NTTP->getPosition() >= TemplateArgs.size() ||
|
|
|
|
TemplateArgs[NTTP->getPosition()].isNull())
|
|
|
|
return SemaRef.Owned(E); // FIXME: Clone the expression!
|
|
|
|
|
|
|
|
const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()];
|
|
|
|
|
|
|
|
// The template argument itself might be an expression, in which
|
|
|
|
// case we just return that expression.
|
|
|
|
if (Arg.getKind() == TemplateArgument::Expression)
|
|
|
|
// FIXME: Clone the expression!
|
|
|
|
return SemaRef.Owned(Arg.getAsExpr());
|
|
|
|
|
|
|
|
if (Arg.getKind() == TemplateArgument::Declaration) {
|
|
|
|
ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
|
|
|
|
|
|
|
|
// FIXME: Can VD ever have a dependent type?
|
|
|
|
return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
|
|
|
|
false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(Arg.getKind() == TemplateArgument::Integral);
|
|
|
|
QualType T = Arg.getIntegralType();
|
|
|
|
if (T->isCharType() || T->isWideCharType())
|
|
|
|
return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
|
|
|
|
Arg.getAsIntegral()->getZExtValue(),
|
|
|
|
T->isWideCharType(),
|
|
|
|
T,
|
|
|
|
E->getSourceRange().getBegin()));
|
|
|
|
if (T->isBooleanType())
|
|
|
|
return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
|
|
|
|
Arg.getAsIntegral()->getBoolValue(),
|
|
|
|
T,
|
|
|
|
E->getSourceRange().getBegin()));
|
|
|
|
|
|
|
|
assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
|
|
|
|
return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
|
|
|
|
*Arg.getAsIntegral(),
|
|
|
|
T,
|
|
|
|
E->getSourceRange().getBegin()));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
|
|
|
|
// FIXME: instantiate each decl in the overload set
|
|
|
|
return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Ovl,
|
|
|
|
SemaRef.Context.OverloadTy,
|
|
|
|
E->getLocation(),
|
|
|
|
false, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
NamedDecl *InstD = SemaRef.InstantiateCurrentDeclRef(D);
|
|
|
|
if (!InstD)
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
// FIXME: nested-name-specifier for QualifiedDeclRefExpr
|
|
|
|
return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD,
|
|
|
|
/*FIXME:*/false,
|
|
|
|
/*FIXME:*/0,
|
|
|
|
/*FIXME:*/false);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::OwningExprResult
|
|
|
|
TemplateInstantiator::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) {
|
|
|
|
VarDecl *Var
|
|
|
|
= cast_or_null<VarDecl>(SemaRef.InstantiateDecl(E->getVarDecl(),
|
|
|
|
SemaRef.CurContext,
|
|
|
|
TemplateArgs));
|
|
|
|
if (!Var)
|
|
|
|
return SemaRef.ExprError();
|
|
|
|
|
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(E->getVarDecl(), Var);
|
|
|
|
return SemaRef.Owned(new (SemaRef.Context) CXXConditionDeclExpr(
|
|
|
|
E->getStartLoc(),
|
|
|
|
SourceLocation(),
|
|
|
|
Var));
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
2009-08-05 00:50:30 +08:00
|
|
|
TemplateInstantiator::TransformTemplateTypeParmType(
|
|
|
|
const TemplateTypeParmType *T) {
|
2009-02-28 03:31:52 +08:00
|
|
|
if (T->getDepth() == 0) {
|
|
|
|
// Replace the template type parameter with its corresponding
|
|
|
|
// template argument.
|
2009-07-01 08:28:38 +08:00
|
|
|
|
2009-08-05 00:50:30 +08:00
|
|
|
// FIXME: When dealing with member templates, we might end up with multiple
|
|
|
|
/// levels of template arguments that we're substituting into concurrently.
|
|
|
|
|
2009-07-01 08:28:38 +08:00
|
|
|
// If the corresponding template argument is NULL or doesn't exist, it's
|
|
|
|
// because we are performing instantiation from explicitly-specified
|
|
|
|
// template arguments in a function template class, but there were some
|
|
|
|
// arguments left unspecified.
|
|
|
|
if (T->getIndex() >= TemplateArgs.size() ||
|
|
|
|
TemplateArgs[T->getIndex()].isNull())
|
|
|
|
return QualType(T, 0); // Would be nice to keep the original type here
|
|
|
|
|
2009-02-28 03:31:52 +08:00
|
|
|
assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
|
|
|
|
"Template argument kind mismatch");
|
2009-06-27 05:40:05 +08:00
|
|
|
return TemplateArgs[T->getIndex()].getAsType();
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// The template type parameter comes from an inner template (e.g.,
|
|
|
|
// the template parameter list of a member template inside the
|
|
|
|
// template we are instantiating). Create a new template type
|
|
|
|
// parameter with the template "level" reduced by one.
|
2009-08-05 00:50:30 +08:00
|
|
|
return getSema().Context.getTemplateTypeParmType(T->getDepth() - 1,
|
|
|
|
T->getIndex(),
|
|
|
|
T->isParameterPack(),
|
|
|
|
T->getName());
|
2009-02-28 08:25:32 +08:00
|
|
|
}
|
2009-02-28 03:31:52 +08:00
|
|
|
|
|
|
|
/// \brief Instantiate the type T with a given set of template arguments.
|
|
|
|
///
|
|
|
|
/// This routine substitutes the given template arguments into the
|
|
|
|
/// type T and produces the instantiated type.
|
|
|
|
///
|
|
|
|
/// \param T the type into which the template arguments will be
|
|
|
|
/// substituted. If this type is not dependent, it will be returned
|
|
|
|
/// immediately.
|
|
|
|
///
|
|
|
|
/// \param TemplateArgs the template arguments that will be
|
|
|
|
/// substituted for the top-level template parameters within T.
|
|
|
|
///
|
|
|
|
/// \param Loc the location in the source code where this substitution
|
|
|
|
/// is being performed. It will typically be the location of the
|
|
|
|
/// declarator (if we're instantiating the type of some declaration)
|
|
|
|
/// or the location of the type in the source code (if, e.g., we're
|
|
|
|
/// instantiating the type of a cast expression).
|
|
|
|
///
|
|
|
|
/// \param Entity the name of the entity associated with a declaration
|
|
|
|
/// being instantiated (if any). May be empty to indicate that there
|
|
|
|
/// is no such entity (if, e.g., this is a type that occurs as part of
|
|
|
|
/// a cast expression) or that the entity has no name (e.g., an
|
|
|
|
/// unnamed function parameter).
|
|
|
|
///
|
|
|
|
/// \returns If the instantiation succeeds, the instantiated
|
|
|
|
/// type. Otherwise, produces diagnostics and returns a NULL type.
|
|
|
|
QualType Sema::InstantiateType(QualType T,
|
2009-05-12 07:53:27 +08:00
|
|
|
const TemplateArgumentList &TemplateArgs,
|
2009-02-28 03:31:52 +08:00
|
|
|
SourceLocation Loc, DeclarationName Entity) {
|
2009-03-11 04:44:00 +08:00
|
|
|
assert(!ActiveTemplateInstantiations.empty() &&
|
|
|
|
"Cannot perform an instantiation without some context on the "
|
|
|
|
"instantiation stack");
|
|
|
|
|
2009-02-28 03:31:52 +08:00
|
|
|
// If T is not a dependent type, there is nothing to do.
|
|
|
|
if (!T->isDependentType())
|
|
|
|
return T;
|
|
|
|
|
2009-08-05 00:50:30 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
|
|
|
|
return Instantiator.TransformType(T);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
2009-03-03 12:44:36 +08:00
|
|
|
|
|
|
|
/// \brief Instantiate the base class specifiers of the given class
|
|
|
|
/// template specialization.
|
|
|
|
///
|
|
|
|
/// Produces a diagnostic and returns true on error, returns false and
|
|
|
|
/// attaches the instantiated base classes to the class template
|
|
|
|
/// specialization if successful.
|
|
|
|
bool
|
2009-03-26 05:17:03 +08:00
|
|
|
Sema::InstantiateBaseSpecifiers(CXXRecordDecl *Instantiation,
|
|
|
|
CXXRecordDecl *Pattern,
|
2009-05-12 07:53:27 +08:00
|
|
|
const TemplateArgumentList &TemplateArgs) {
|
2009-03-03 12:44:36 +08:00
|
|
|
bool Invalid = false;
|
2009-05-30 02:27:38 +08:00
|
|
|
llvm::SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
|
2009-03-26 05:17:03 +08:00
|
|
|
for (ClassTemplateSpecializationDecl::base_class_iterator
|
|
|
|
Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
|
2009-03-11 02:52:44 +08:00
|
|
|
Base != BaseEnd; ++Base) {
|
2009-03-03 12:44:36 +08:00
|
|
|
if (!Base->getType()->isDependentType()) {
|
2009-07-23 01:41:53 +08:00
|
|
|
InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
|
2009-03-03 12:44:36 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType BaseType = InstantiateType(Base->getType(),
|
2009-05-12 07:53:27 +08:00
|
|
|
TemplateArgs,
|
2009-03-03 12:44:36 +08:00
|
|
|
Base->getSourceRange().getBegin(),
|
|
|
|
DeclarationName());
|
|
|
|
if (BaseType.isNull()) {
|
|
|
|
Invalid = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CXXBaseSpecifier *InstantiatedBase
|
2009-03-26 05:17:03 +08:00
|
|
|
= CheckBaseSpecifier(Instantiation,
|
2009-03-03 12:44:36 +08:00
|
|
|
Base->getSourceRange(),
|
|
|
|
Base->isVirtual(),
|
|
|
|
Base->getAccessSpecifierAsWritten(),
|
|
|
|
BaseType,
|
|
|
|
/*FIXME: Not totally accurate */
|
|
|
|
Base->getSourceRange().getBegin()))
|
|
|
|
InstantiatedBases.push_back(InstantiatedBase);
|
|
|
|
else
|
|
|
|
Invalid = true;
|
|
|
|
}
|
|
|
|
|
2009-03-11 02:52:44 +08:00
|
|
|
if (!Invalid &&
|
2009-05-21 17:52:38 +08:00
|
|
|
AttachBaseSpecifiers(Instantiation, InstantiatedBases.data(),
|
2009-03-03 12:44:36 +08:00
|
|
|
InstantiatedBases.size()))
|
|
|
|
Invalid = true;
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
}
|
|
|
|
|
2009-03-26 05:17:03 +08:00
|
|
|
/// \brief Instantiate the definition of a class from a given pattern.
|
|
|
|
///
|
|
|
|
/// \param PointOfInstantiation The point of instantiation within the
|
|
|
|
/// source code.
|
|
|
|
///
|
|
|
|
/// \param Instantiation is the declaration whose definition is being
|
|
|
|
/// instantiated. This will be either a class template specialization
|
|
|
|
/// or a member class of a class template specialization.
|
|
|
|
///
|
|
|
|
/// \param Pattern is the pattern from which the instantiation
|
|
|
|
/// occurs. This will be either the declaration of a class template or
|
|
|
|
/// the declaration of a member class of a class template.
|
|
|
|
///
|
|
|
|
/// \param TemplateArgs The template arguments to be substituted into
|
|
|
|
/// the pattern.
|
|
|
|
///
|
|
|
|
/// \returns true if an error occurred, false otherwise.
|
|
|
|
bool
|
|
|
|
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
|
|
|
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
|
2009-05-13 08:25:59 +08:00
|
|
|
const TemplateArgumentList &TemplateArgs,
|
|
|
|
bool ExplicitInstantiation) {
|
2009-03-26 05:17:03 +08:00
|
|
|
bool Invalid = false;
|
|
|
|
|
|
|
|
CXXRecordDecl *PatternDef
|
|
|
|
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
|
|
|
|
if (!PatternDef) {
|
|
|
|
if (Pattern == Instantiation->getInstantiatedFromMemberClass()) {
|
|
|
|
Diag(PointOfInstantiation,
|
|
|
|
diag::err_implicit_instantiate_member_undefined)
|
|
|
|
<< Context.getTypeDeclType(Instantiation);
|
|
|
|
Diag(Pattern->getLocation(), diag::note_member_of_template_here);
|
|
|
|
} else {
|
2009-05-13 08:25:59 +08:00
|
|
|
Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
|
|
|
|
<< ExplicitInstantiation
|
2009-03-26 05:17:03 +08:00
|
|
|
<< Context.getTypeDeclType(Instantiation);
|
|
|
|
Diag(Pattern->getLocation(), diag::note_template_decl_here);
|
|
|
|
}
|
2009-03-03 12:44:36 +08:00
|
|
|
return true;
|
|
|
|
}
|
2009-03-26 05:17:03 +08:00
|
|
|
Pattern = PatternDef;
|
2009-03-03 12:44:36 +08:00
|
|
|
|
2009-03-26 05:23:52 +08:00
|
|
|
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
|
2009-03-10 08:06:19 +08:00
|
|
|
if (Inst)
|
|
|
|
return true;
|
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
// Enter the scope of this instantiation. We don't use
|
|
|
|
// PushDeclContext because we don't have a scope.
|
|
|
|
DeclContext *PreviousContext = CurContext;
|
2009-03-26 05:17:03 +08:00
|
|
|
CurContext = Instantiation;
|
2009-03-03 12:44:36 +08:00
|
|
|
|
|
|
|
// Start the definition of this instantiation.
|
2009-03-26 05:17:03 +08:00
|
|
|
Instantiation->startDefinition();
|
2009-03-03 12:44:36 +08:00
|
|
|
|
|
|
|
// Instantiate the base class specifiers.
|
2009-05-12 07:53:27 +08:00
|
|
|
if (InstantiateBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
|
2009-03-03 12:44:36 +08:00
|
|
|
Invalid = true;
|
|
|
|
|
2009-05-30 02:27:38 +08:00
|
|
|
llvm::SmallVector<DeclPtrTy, 4> Fields;
|
2009-06-30 10:36:12 +08:00
|
|
|
for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
|
|
|
|
MemberEnd = Pattern->decls_end();
|
2009-04-10 05:40:53 +08:00
|
|
|
Member != MemberEnd; ++Member) {
|
2009-05-12 07:53:27 +08:00
|
|
|
Decl *NewMember = InstantiateDecl(*Member, Instantiation, TemplateArgs);
|
2009-03-18 05:15:40 +08:00
|
|
|
if (NewMember) {
|
|
|
|
if (NewMember->isInvalidDecl())
|
2009-03-16 02:44:04 +08:00
|
|
|
Invalid = true;
|
2009-03-18 05:15:40 +08:00
|
|
|
else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
|
2009-03-29 03:18:32 +08:00
|
|
|
Fields.push_back(DeclPtrTy::make(Field));
|
2009-03-18 05:15:40 +08:00
|
|
|
} else {
|
|
|
|
// FIXME: Eventually, a NULL return will mean that one of the
|
2009-05-16 15:39:55 +08:00
|
|
|
// instantiations was a semantic disaster, and we'll want to set Invalid =
|
|
|
|
// true. For now, we expect to skip some members that we can't yet handle.
|
2009-03-12 00:48:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-12 02:59:21 +08:00
|
|
|
// Finish checking fields.
|
2009-03-29 03:18:32 +08:00
|
|
|
ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
|
2009-05-21 17:52:38 +08:00
|
|
|
Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
|
2009-03-12 02:59:21 +08:00
|
|
|
0);
|
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
// Add any implicitly-declared members that we might need.
|
2009-03-26 05:17:03 +08:00
|
|
|
AddImplicitlyDeclaredMembersToClass(Instantiation);
|
2009-03-03 12:44:36 +08:00
|
|
|
|
|
|
|
// Exit the scope of this instantiation.
|
|
|
|
CurContext = PreviousContext;
|
|
|
|
|
2009-05-27 04:50:29 +08:00
|
|
|
if (!Invalid)
|
|
|
|
Consumer.HandleTagDeclDefinition(Instantiation);
|
|
|
|
|
2009-05-14 04:28:22 +08:00
|
|
|
// If this is an explicit instantiation, instantiate our members, too.
|
2009-05-19 01:01:57 +08:00
|
|
|
if (!Invalid && ExplicitInstantiation) {
|
|
|
|
Inst.Clear();
|
2009-05-14 04:28:22 +08:00
|
|
|
InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs);
|
2009-05-19 01:01:57 +08:00
|
|
|
}
|
2009-05-14 04:28:22 +08:00
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
return Invalid;
|
|
|
|
}
|
Introduce a new expression type, UnresolvedDeclRefExpr, that describes
dependent qualified-ids such as
Fibonacci<N - 1>::value
where N is a template parameter. These references are "unresolved"
because the name is dependent and, therefore, cannot be resolved to a
declaration node (as we would do for a DeclRefExpr or
QualifiedDeclRefExpr). UnresolvedDeclRefExprs instantiate to
DeclRefExprs, QualifiedDeclRefExprs, etc.
Also, be a bit more careful about keeping only a single set of
specializations for a class template, and instantiating from the
definition of that template rather than a previous declaration. In
general, we need a better solution for this for all TagDecls, because
it's too easy to accidentally look at a declaration that isn't the
definition.
We can now process a simple Fibonacci computation described as a
template metaprogram.
llvm-svn: 67308
2009-03-20 01:26:29 +08:00
|
|
|
|
2009-03-26 05:17:03 +08:00
|
|
|
bool
|
|
|
|
Sema::InstantiateClassTemplateSpecialization(
|
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
|
|
|
bool ExplicitInstantiation) {
|
|
|
|
// Perform the actual instantiation on the canonical declaration.
|
|
|
|
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
|
2009-07-18 08:34:25 +08:00
|
|
|
ClassTemplateSpec->getCanonicalDecl());
|
2009-03-26 05:17:03 +08:00
|
|
|
|
|
|
|
// We can only instantiate something that hasn't already been
|
|
|
|
// instantiated or specialized. Fail without any diagnostics: our
|
|
|
|
// caller will provide an error message.
|
|
|
|
if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
|
|
|
|
CXXRecordDecl *Pattern = Template->getTemplatedDecl();
|
2009-05-31 17:31:02 +08:00
|
|
|
const TemplateArgumentList *TemplateArgs
|
|
|
|
= &ClassTemplateSpec->getTemplateArgs();
|
|
|
|
|
2009-06-13 06:31:52 +08:00
|
|
|
// C++ [temp.class.spec.match]p1:
|
|
|
|
// When a class template is used in a context that requires an
|
|
|
|
// instantiation of the class, it is necessary to determine
|
|
|
|
// whether the instantiation is to be generated using the primary
|
|
|
|
// template or one of the partial specializations. This is done by
|
|
|
|
// matching the template arguments of the class template
|
|
|
|
// specialization with the template argument lists of the partial
|
|
|
|
// specializations.
|
2009-06-05 08:53:49 +08:00
|
|
|
typedef std::pair<ClassTemplatePartialSpecializationDecl *,
|
|
|
|
TemplateArgumentList *> MatchResult;
|
|
|
|
llvm::SmallVector<MatchResult, 4> Matched;
|
2009-05-31 17:31:02 +08:00
|
|
|
for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
|
|
|
|
Partial = Template->getPartialSpecializations().begin(),
|
|
|
|
PartialEnd = Template->getPartialSpecializations().end();
|
|
|
|
Partial != PartialEnd;
|
|
|
|
++Partial) {
|
2009-06-13 02:26:56 +08:00
|
|
|
TemplateDeductionInfo Info(Context);
|
|
|
|
if (TemplateDeductionResult Result
|
2009-06-05 08:53:49 +08:00
|
|
|
= DeduceTemplateArguments(&*Partial,
|
2009-06-13 02:26:56 +08:00
|
|
|
ClassTemplateSpec->getTemplateArgs(),
|
|
|
|
Info)) {
|
|
|
|
// FIXME: Store the failed-deduction information for use in
|
|
|
|
// diagnostics, later.
|
|
|
|
(void)Result;
|
|
|
|
} else {
|
|
|
|
Matched.push_back(std::make_pair(&*Partial, Info.take()));
|
|
|
|
}
|
2009-05-31 17:31:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Matched.size() == 1) {
|
2009-06-13 06:31:52 +08:00
|
|
|
// -- If exactly one matching specialization is found, the
|
|
|
|
// instantiation is generated from that specialization.
|
2009-06-05 08:53:49 +08:00
|
|
|
Pattern = Matched[0].first;
|
|
|
|
TemplateArgs = Matched[0].second;
|
2009-08-03 07:24:31 +08:00
|
|
|
ClassTemplateSpec->setInstantiationOf(Matched[0].first, Matched[0].second);
|
2009-05-31 17:31:02 +08:00
|
|
|
} else if (Matched.size() > 1) {
|
2009-06-13 06:31:52 +08:00
|
|
|
// -- If more than one matching specialization is found, the
|
|
|
|
// partial order rules (14.5.4.2) are used to determine
|
|
|
|
// whether one of the specializations is more specialized
|
|
|
|
// than the others. If none of the specializations is more
|
|
|
|
// specialized than all of the other matching
|
|
|
|
// specializations, then the use of the class template is
|
|
|
|
// ambiguous and the program is ill-formed.
|
2009-05-31 17:31:02 +08:00
|
|
|
// FIXME: Implement partial ordering of class template partial
|
|
|
|
// specializations.
|
|
|
|
Diag(ClassTemplateSpec->getLocation(),
|
|
|
|
diag::unsup_template_partial_spec_ordering);
|
2009-06-13 06:31:52 +08:00
|
|
|
} else {
|
|
|
|
// -- If no matches are found, the instantiation is generated
|
|
|
|
// from the primary template.
|
|
|
|
|
|
|
|
// Since we initialized the pattern and template arguments from
|
|
|
|
// the primary template, there is nothing more we need to do here.
|
2009-05-31 17:31:02 +08:00
|
|
|
}
|
2009-03-26 05:17:03 +08:00
|
|
|
|
|
|
|
// Note that this is an instantiation.
|
|
|
|
ClassTemplateSpec->setSpecializationKind(
|
|
|
|
ExplicitInstantiation? TSK_ExplicitInstantiation
|
|
|
|
: TSK_ImplicitInstantiation);
|
|
|
|
|
2009-06-05 08:53:49 +08:00
|
|
|
bool Result = InstantiateClass(ClassTemplateSpec->getLocation(),
|
|
|
|
ClassTemplateSpec, Pattern, *TemplateArgs,
|
|
|
|
ExplicitInstantiation);
|
|
|
|
|
|
|
|
for (unsigned I = 0, N = Matched.size(); I != N; ++I) {
|
|
|
|
// FIXME: Implement TemplateArgumentList::Destroy!
|
|
|
|
// if (Matched[I].first != Pattern)
|
|
|
|
// Matched[I].second->Destroy(Context);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
2009-03-26 05:17:03 +08:00
|
|
|
}
|
|
|
|
|
2009-05-14 04:28:22 +08:00
|
|
|
/// \brief Instantiate the definitions of all of the member of the
|
|
|
|
/// given class, which is an instantiation of a class template or a
|
|
|
|
/// member class of a template.
|
|
|
|
void
|
|
|
|
Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
|
|
|
CXXRecordDecl *Instantiation,
|
|
|
|
const TemplateArgumentList &TemplateArgs) {
|
2009-06-30 10:36:12 +08:00
|
|
|
for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
|
|
|
|
DEnd = Instantiation->decls_end();
|
2009-05-14 04:28:22 +08:00
|
|
|
D != DEnd; ++D) {
|
|
|
|
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
|
2009-06-30 10:35:26 +08:00
|
|
|
if (!Function->getBody())
|
2009-05-19 01:01:57 +08:00
|
|
|
InstantiateFunctionDefinition(PointOfInstantiation, Function);
|
2009-05-14 04:28:22 +08:00
|
|
|
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
|
2009-07-25 04:34:43 +08:00
|
|
|
if (Var->isStaticDataMember())
|
|
|
|
InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
|
2009-05-14 04:28:22 +08:00
|
|
|
} else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
|
|
|
|
if (!Record->isInjectedClassName() && !Record->getDefinition(Context)) {
|
|
|
|
assert(Record->getInstantiatedFromMemberClass() &&
|
|
|
|
"Missing instantiated-from-template information");
|
2009-05-19 01:01:57 +08:00
|
|
|
InstantiateClass(PointOfInstantiation, Record,
|
2009-05-14 04:28:22 +08:00
|
|
|
Record->getInstantiatedFromMemberClass(),
|
|
|
|
TemplateArgs, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Instantiate the definitions of all of the members of the
|
|
|
|
/// given class template specialization, which was named as part of an
|
|
|
|
/// explicit instantiation.
|
|
|
|
void Sema::InstantiateClassTemplateSpecializationMembers(
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec) {
|
|
|
|
// C++0x [temp.explicit]p7:
|
|
|
|
// An explicit instantiation that names a class template
|
|
|
|
// specialization is an explicit instantion of the same kind
|
|
|
|
// (declaration or definition) of each of its members (not
|
|
|
|
// including members inherited from base classes) that has not
|
|
|
|
// been previously explicitly specialized in the translation unit
|
|
|
|
// containing the explicit instantiation, except as described
|
|
|
|
// below.
|
|
|
|
InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
|
|
|
|
ClassTemplateSpec->getTemplateArgs());
|
|
|
|
}
|
|
|
|
|
2009-08-11 13:31:07 +08:00
|
|
|
Sema::OwningExprResult
|
|
|
|
Sema::InstantiateExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
|
|
|
|
if (!E)
|
|
|
|
return Owned(E);
|
|
|
|
|
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs,
|
|
|
|
SourceLocation(),
|
|
|
|
DeclarationName());
|
|
|
|
return Instantiator.TransformExpr(E);
|
|
|
|
}
|
|
|
|
|
2009-03-27 07:50:42 +08:00
|
|
|
/// \brief Instantiate a nested-name-specifier.
|
|
|
|
NestedNameSpecifier *
|
|
|
|
Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
|
|
|
|
SourceRange Range,
|
2009-05-12 07:53:27 +08:00
|
|
|
const TemplateArgumentList &TemplateArgs) {
|
2009-08-06 13:28:30 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
|
|
|
|
DeclarationName());
|
|
|
|
return Instantiator.TransformNestedNameSpecifier(NNS, Range);
|
Introduce a new expression type, UnresolvedDeclRefExpr, that describes
dependent qualified-ids such as
Fibonacci<N - 1>::value
where N is a template parameter. These references are "unresolved"
because the name is dependent and, therefore, cannot be resolved to a
declaration node (as we would do for a DeclRefExpr or
QualifiedDeclRefExpr). UnresolvedDeclRefExprs instantiate to
DeclRefExprs, QualifiedDeclRefExprs, etc.
Also, be a bit more careful about keeping only a single set of
specializations for a class template, and instantiating from the
definition of that template rather than a previous declaration. In
general, we need a better solution for this for all TagDecls, because
it's too easy to accidentally look at a declaration that isn't the
definition.
We can now process a simple Fibonacci computation described as a
template metaprogram.
llvm-svn: 67308
2009-03-20 01:26:29 +08:00
|
|
|
}
|
2009-04-01 02:38:02 +08:00
|
|
|
|
|
|
|
TemplateName
|
|
|
|
Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
|
2009-05-12 07:53:27 +08:00
|
|
|
const TemplateArgumentList &TemplateArgs) {
|
2009-08-06 14:41:21 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
|
|
|
|
DeclarationName());
|
|
|
|
return Instantiator.TransformTemplateName(Name);
|
2009-04-01 02:38:02 +08:00
|
|
|
}
|
2009-06-11 08:06:24 +08:00
|
|
|
|
|
|
|
TemplateArgument Sema::Instantiate(TemplateArgument Arg,
|
|
|
|
const TemplateArgumentList &TemplateArgs) {
|
2009-08-05 06:27:00 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
|
|
|
|
DeclarationName());
|
|
|
|
return Instantiator.TransformTemplateArgument(Arg);
|
2009-06-11 08:06:24 +08:00
|
|
|
}
|