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"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/Expr.h"
|
|
|
|
#include "clang/AST/ExprCXX.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-03-10 08:06:19 +08:00
|
|
|
Sema::InstantiatingTemplate::
|
|
|
|
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
ClassTemplateSpecializationDecl *Entity,
|
|
|
|
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);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::InstantiatingTemplate::~InstantiatingTemplate() {
|
|
|
|
if (!Invalid)
|
|
|
|
SemaRef.ActiveTemplateInstantiations.pop_back();
|
|
|
|
}
|
|
|
|
|
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 Post-diagnostic hook for printing the instantiation stack.
|
|
|
|
void Sema::PrintInstantiationStackHook(unsigned, void *Cookie) {
|
2009-03-11 02:52:44 +08:00
|
|
|
Sema &SemaRef = *static_cast<Sema*>(Cookie);
|
|
|
|
SemaRef.PrintInstantiationStack();
|
|
|
|
SemaRef.LastTemplateInstantiationErrorContext
|
2009-03-11 04:44:00 +08:00
|
|
|
= SemaRef.ActiveTemplateInstantiations.back();
|
2009-03-11 02:03:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Prints the current instantiation stack through a series of
|
|
|
|
/// notes.
|
|
|
|
void Sema::PrintInstantiationStack() {
|
|
|
|
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: {
|
|
|
|
ClassTemplateSpecializationDecl *Spec
|
|
|
|
= cast<ClassTemplateSpecializationDecl>((Decl*)Active->Entity);
|
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_template_class_instantiation_here)
|
|
|
|
<< Context.getTypeDeclType(Spec)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
|
|
|
|
TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
|
|
|
|
std::string TemplateArgsStr
|
|
|
|
= ClassTemplateSpecializationType::PrintTemplateArgumentList(
|
|
|
|
Active->TemplateArgs,
|
|
|
|
Active->NumTemplateArgs);
|
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_default_arg_instantiation_here)
|
|
|
|
<< (Template->getNameAsString() + TemplateArgsStr)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-03-11 02:03:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-28 03:31:52 +08:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation for Types
|
|
|
|
//===----------------------------------------------------------------------===/
|
2009-02-28 08:25:32 +08:00
|
|
|
namespace {
|
|
|
|
class VISIBILITY_HIDDEN TemplateTypeInstantiator {
|
|
|
|
Sema &SemaRef;
|
|
|
|
const TemplateArgument *TemplateArgs;
|
|
|
|
unsigned NumTemplateArgs;
|
|
|
|
SourceLocation Loc;
|
|
|
|
DeclarationName Entity;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TemplateTypeInstantiator(Sema &SemaRef,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
|
|
|
SourceLocation Loc,
|
|
|
|
DeclarationName Entity)
|
|
|
|
: SemaRef(SemaRef), TemplateArgs(TemplateArgs),
|
|
|
|
NumTemplateArgs(NumTemplateArgs), Loc(Loc), Entity(Entity) { }
|
|
|
|
|
|
|
|
QualType operator()(QualType T) const { return Instantiate(T); }
|
|
|
|
|
|
|
|
QualType Instantiate(QualType T) const;
|
|
|
|
|
|
|
|
// Declare instantiate functions for each type.
|
|
|
|
#define TYPE(Class, Base) \
|
|
|
|
QualType Instantiate##Class##Type(const Class##Type *T, \
|
|
|
|
unsigned Quals) const;
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
};
|
|
|
|
}
|
2009-02-28 03:31:52 +08:00
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate ExtQualType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 09:04:19 +08:00
|
|
|
assert(false && "Builtin types are not dependent and cannot be instantiated");
|
2009-02-28 08:25:32 +08:00
|
|
|
return QualType(T, Quals);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateFixedWidthIntType(const FixedWidthIntType *T, unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate FixedWidthIntType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate ComplexType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
QualType PointeeType = Instantiate(T->getPointeeType());
|
|
|
|
if (PointeeType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.BuildPointerType(PointeeType, Quals, Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate BlockPointerType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateReferenceType(const ReferenceType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
QualType ReferentType = Instantiate(T->getPointeeType());
|
|
|
|
if (ReferentType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.BuildReferenceType(ReferentType, Quals, Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateMemberPointerType(const MemberPointerType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate MemberPointerType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateConstantArrayType(const ConstantArrayType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
QualType ElementType = Instantiate(T->getElementType());
|
|
|
|
if (ElementType.isNull())
|
|
|
|
return ElementType;
|
|
|
|
|
|
|
|
// Build a temporary integer literal to specify the size for
|
|
|
|
// BuildArrayType. Since we have already checked the size as part of
|
|
|
|
// creating the dependent array type in the first place, we know
|
|
|
|
// there aren't any errors.
|
2009-03-10 04:07:22 +08:00
|
|
|
// FIXME: Is IntTy big enough? Maybe not, but LongLongTy causes
|
|
|
|
// problems that I have yet to investigate.
|
|
|
|
IntegerLiteral ArraySize(T->getSize(), SemaRef.Context.IntTy, Loc);
|
2009-02-28 08:25:32 +08:00
|
|
|
return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(),
|
|
|
|
&ArraySize, T->getIndexTypeQualifier(),
|
|
|
|
Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateIncompleteArrayType(const IncompleteArrayType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
QualType ElementType = Instantiate(T->getElementType());
|
|
|
|
if (ElementType.isNull())
|
|
|
|
return ElementType;
|
|
|
|
|
|
|
|
return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(),
|
|
|
|
0, T->getIndexTypeQualifier(),
|
|
|
|
Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateVariableArrayType(const VariableArrayType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate VariableArrayType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate DependentSizedArrayType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate VectorType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateExtVectorType(const ExtVectorType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate ExtVectorType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateFunctionProtoType(const FunctionProtoType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 09:04:19 +08:00
|
|
|
QualType ResultType = Instantiate(T->getResultType());
|
|
|
|
if (ResultType.isNull())
|
|
|
|
return ResultType;
|
|
|
|
|
|
|
|
llvm::SmallVector<QualType, 16> ParamTypes;
|
|
|
|
for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(),
|
|
|
|
ParamEnd = T->arg_type_end();
|
|
|
|
Param != ParamEnd; ++Param) {
|
|
|
|
QualType P = Instantiate(*Param);
|
|
|
|
if (P.isNull())
|
|
|
|
return P;
|
|
|
|
|
|
|
|
ParamTypes.push_back(P);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SemaRef.BuildFunctionType(ResultType, &ParamTypes[0],
|
|
|
|
ParamTypes.size(),
|
|
|
|
T->isVariadic(), T->getTypeQuals(),
|
|
|
|
Loc, Entity);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateFunctionNoProtoType(const FunctionNoProtoType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 09:04:19 +08:00
|
|
|
assert(false && "Functions without prototypes cannot be dependent.");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate TypedefType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate TypeOfExprType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate TypeOfType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate RecordType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate EnumType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateTemplateTypeParmType(const TemplateTypeParmType *T,
|
|
|
|
unsigned Quals) const {
|
2009-02-28 03:31:52 +08:00
|
|
|
if (T->getDepth() == 0) {
|
|
|
|
// Replace the template type parameter with its corresponding
|
|
|
|
// template argument.
|
|
|
|
assert(T->getIndex() < NumTemplateArgs && "Wrong # of template args");
|
|
|
|
assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
|
|
|
|
"Template argument kind mismatch");
|
|
|
|
QualType Result = TemplateArgs[T->getIndex()].getAsType();
|
2009-02-28 08:25:32 +08:00
|
|
|
if (Result.isNull() || !Quals)
|
2009-02-28 03:31:52 +08:00
|
|
|
return Result;
|
|
|
|
|
|
|
|
// C++ [dcl.ref]p1:
|
|
|
|
// [...] Cv-qualified references are ill-formed except when
|
|
|
|
// the cv-qualifiers are introduced through the use of a
|
|
|
|
// typedef (7.1.3) or of a template type argument (14.3), in
|
|
|
|
// which case the cv-qualifiers are ignored.
|
2009-02-28 08:25:32 +08:00
|
|
|
if (Quals && Result->isReferenceType())
|
|
|
|
Quals = 0;
|
2009-02-28 03:31:52 +08:00
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
return QualType(Result.getTypePtr(), Quals | Result.getCVRQualifiers());
|
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.
|
|
|
|
return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1,
|
|
|
|
T->getIndex(),
|
2009-02-28 08:25:32 +08:00
|
|
|
T->getName())
|
|
|
|
.getQualifiedType(Quals);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateClassTemplateSpecializationType(
|
|
|
|
const ClassTemplateSpecializationType *T,
|
|
|
|
unsigned Quals) const {
|
2009-03-10 07:48:35 +08:00
|
|
|
llvm::SmallVector<TemplateArgument, 16> InstantiatedTemplateArgs;
|
|
|
|
InstantiatedTemplateArgs.reserve(T->getNumArgs());
|
|
|
|
for (ClassTemplateSpecializationType::iterator Arg = T->begin(),
|
|
|
|
ArgEnd = T->end();
|
|
|
|
Arg != ArgEnd; ++Arg) {
|
|
|
|
switch (Arg->getKind()) {
|
|
|
|
case TemplateArgument::Type: {
|
|
|
|
QualType T = SemaRef.InstantiateType(Arg->getAsType(),
|
|
|
|
TemplateArgs, NumTemplateArgs,
|
|
|
|
Arg->getLocation(),
|
|
|
|
DeclarationName());
|
|
|
|
if (T.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
InstantiatedTemplateArgs.push_back(
|
|
|
|
TemplateArgument(Arg->getLocation(), T));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateArgument::Declaration:
|
|
|
|
case TemplateArgument::Integral:
|
|
|
|
InstantiatedTemplateArgs.push_back(*Arg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TemplateArgument::Expression:
|
|
|
|
assert(false && "Cannot instantiate expressions yet");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: We're missing the locations of the template name, '<', and
|
|
|
|
// '>'.
|
|
|
|
return SemaRef.CheckClassTemplateId(cast<ClassTemplateDecl>(T->getTemplate()),
|
|
|
|
Loc,
|
|
|
|
SourceLocation(),
|
|
|
|
&InstantiatedTemplateArgs[0],
|
|
|
|
InstantiatedTemplateArgs.size(),
|
|
|
|
SourceLocation());
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateObjCQualifiedIdType(const ObjCQualifiedIdType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
|
|
|
InstantiateObjCQualifiedClassType(const ObjCQualifiedClassType *T,
|
|
|
|
unsigned Quals) const {
|
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-28 03:31:52 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 08:25:32 +08:00
|
|
|
/// \brief The actual implementation of Sema::InstantiateType().
|
|
|
|
QualType TemplateTypeInstantiator::Instantiate(QualType T) const {
|
|
|
|
// If T is not a dependent type, there is nothing to do.
|
|
|
|
if (!T->isDependentType())
|
|
|
|
return T;
|
|
|
|
|
|
|
|
switch (T->getTypeClass()) {
|
|
|
|
#define TYPE(Class, Base) \
|
|
|
|
case Type::Class: \
|
|
|
|
return Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr()), \
|
|
|
|
T.getCVRQualifiers());
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(false && "Not all types have been decoded for instantiation");
|
|
|
|
return QualType();
|
|
|
|
}
|
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 NumTemplateArgs the number of template arguments provided
|
|
|
|
/// by TemplateArgs.
|
|
|
|
///
|
|
|
|
/// \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,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
|
|
|
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-02-28 08:25:32 +08:00
|
|
|
TemplateTypeInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs,
|
|
|
|
Loc, Entity);
|
|
|
|
return Instantiator(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
|
|
|
|
Sema::InstantiateBaseSpecifiers(
|
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
|
|
|
ClassTemplateDecl *ClassTemplate) {
|
|
|
|
bool Invalid = false;
|
|
|
|
llvm::SmallVector<CXXBaseSpecifier*, 8> InstantiatedBases;
|
|
|
|
for (ClassTemplateSpecializationDecl::base_class_iterator
|
|
|
|
Base = ClassTemplate->getTemplatedDecl()->bases_begin(),
|
|
|
|
BaseEnd = ClassTemplate->getTemplatedDecl()->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()) {
|
|
|
|
// FIXME: Allocate via ASTContext
|
|
|
|
InstantiatedBases.push_back(new CXXBaseSpecifier(*Base));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType BaseType = InstantiateType(Base->getType(),
|
|
|
|
ClassTemplateSpec->getTemplateArgs(),
|
|
|
|
ClassTemplateSpec->getNumTemplateArgs(),
|
|
|
|
Base->getSourceRange().getBegin(),
|
|
|
|
DeclarationName());
|
|
|
|
if (BaseType.isNull()) {
|
|
|
|
Invalid = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CXXBaseSpecifier *InstantiatedBase
|
|
|
|
= CheckBaseSpecifier(ClassTemplateSpec,
|
|
|
|
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 &&
|
|
|
|
AttachBaseSpecifiers(ClassTemplateSpec, &InstantiatedBases[0],
|
2009-03-03 12:44:36 +08:00
|
|
|
InstantiatedBases.size()))
|
|
|
|
Invalid = true;
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Sema::InstantiateClassTemplateSpecialization(
|
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
|
|
|
bool ExplicitInstantiation) {
|
|
|
|
// Perform the actual instantiation on the canonical declaration.
|
|
|
|
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
|
|
|
|
Context.getCanonicalDecl(ClassTemplateSpec));
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
// FIXME: Push this class template instantiation onto the
|
|
|
|
// instantiation stack, checking for recursion that exceeds a
|
|
|
|
// certain depth.
|
|
|
|
|
|
|
|
// FIXME: Perform class template partial specialization to select
|
|
|
|
// the best template.
|
|
|
|
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
|
|
|
|
|
|
|
|
if (!Template->getTemplatedDecl()->getDefinition(Context)) {
|
|
|
|
Diag(ClassTemplateSpec->getLocation(),
|
|
|
|
diag::err_template_implicit_instantiate_undefined)
|
|
|
|
<< Context.getTypeDeclType(ClassTemplateSpec);
|
|
|
|
Diag(Template->getTemplatedDecl()->getLocation(),
|
|
|
|
diag::note_template_decl_here);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note that this is an instantiation.
|
|
|
|
ClassTemplateSpec->setSpecializationKind(
|
|
|
|
ExplicitInstantiation? TSK_ExplicitInstantiation
|
|
|
|
: TSK_ImplicitInstantiation);
|
|
|
|
|
|
|
|
|
|
|
|
bool Invalid = false;
|
|
|
|
|
2009-03-10 08:06:19 +08:00
|
|
|
InstantiatingTemplate Inst(*this, ClassTemplateSpec->getLocation(),
|
|
|
|
ClassTemplateSpec);
|
|
|
|
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;
|
|
|
|
CurContext = ClassTemplateSpec;
|
|
|
|
|
|
|
|
// Start the definition of this instantiation.
|
|
|
|
ClassTemplateSpec->startDefinition();
|
|
|
|
|
|
|
|
// FIXME: Create the injected-class-name for the
|
|
|
|
// instantiation. Should this be a typedef or something like it?
|
|
|
|
|
|
|
|
// Instantiate the base class specifiers.
|
|
|
|
if (InstantiateBaseSpecifiers(ClassTemplateSpec, Template))
|
|
|
|
Invalid = true;
|
|
|
|
|
|
|
|
// FIXME: Instantiate all of the members.
|
|
|
|
|
|
|
|
// Add any implicitly-declared members that we might need.
|
|
|
|
AddImplicitlyDeclaredMembersToClass(ClassTemplateSpec);
|
|
|
|
|
|
|
|
// Finish the definition of this instantiation.
|
|
|
|
// FIXME: ActOnFields does more checking, which we'll eventually need.
|
|
|
|
ClassTemplateSpec->completeDefinition(Context);
|
|
|
|
|
|
|
|
// Exit the scope of this instantiation.
|
|
|
|
CurContext = PreviousContext;
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
}
|