2009-02-27 19:31:52 +00: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-05-26 20:50:29 +00:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2009-02-27 19:31:52 +00: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 00:25:32 +00:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2009-02-27 19:31:52 +00:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2009-03-10 18:03:33 +00:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation Support
|
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
|
2009-05-14 23:26:13 +00: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 00:10:03 +00:00
|
|
|
// Template arguments for a class template specialization.
|
2009-05-14 23:26:13 +00:00
|
|
|
if (ClassTemplateSpecializationDecl *Spec
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(D))
|
|
|
|
return Spec->getTemplateArgs();
|
|
|
|
|
2009-06-26 00:10:03 +00: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-14 23:26:13 +00: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);
|
|
|
|
return EnclosingTemplate->getTemplateArgs();
|
|
|
|
}
|
|
|
|
|
2009-03-10 00:06:19 +00:00
|
|
|
Sema::InstantiatingTemplate::
|
|
|
|
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
|
2009-05-18 17:01:57 +00:00
|
|
|
Decl *Entity,
|
2009-03-10 00:06:19 +00:00
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: SemaRef(SemaRef) {
|
2009-03-10 20:44:00 +00: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-12 18:36:18 +00:00
|
|
|
Inst.TemplateArgs = 0;
|
|
|
|
Inst.NumTemplateArgs = 0;
|
2009-03-10 20:44:00 +00: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 00:06:19 +00:00
|
|
|
ActiveTemplateInstantiation Inst;
|
2009-03-10 20:44:00 +00:00
|
|
|
Inst.Kind
|
|
|
|
= ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
|
2009-03-10 00:06:19 +00:00
|
|
|
Inst.PointOfInstantiation = PointOfInstantiation;
|
2009-03-10 20:44:00 +00:00
|
|
|
Inst.Entity = reinterpret_cast<uintptr_t>(Template);
|
|
|
|
Inst.TemplateArgs = TemplateArgs;
|
|
|
|
Inst.NumTemplateArgs = NumTemplateArgs;
|
2009-03-10 00:06:19 +00:00
|
|
|
Inst.InstantiationRange = InstantiationRange;
|
|
|
|
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
|
|
|
|
Invalid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-01 22:01:06 +00: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-10 23:47:09 +00: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-01 22:01:06 +00:00
|
|
|
= ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
|
2009-06-10 23:47:09 +00: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-18 17:01:57 +00:00
|
|
|
void Sema::InstantiatingTemplate::Clear() {
|
|
|
|
if (!Invalid) {
|
2009-03-10 00:06:19 +00:00
|
|
|
SemaRef.ActiveTemplateInstantiations.pop_back();
|
2009-05-18 17:01:57 +00:00
|
|
|
Invalid = true;
|
|
|
|
}
|
2009-03-10 00:06:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-10 20:44:00 +00: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-10 18:03:33 +00:00
|
|
|
/// \brief Prints the current instantiation stack through a series of
|
|
|
|
/// notes.
|
|
|
|
void Sema::PrintInstantiationStack() {
|
2009-07-01 22:01:06 +00:00
|
|
|
// FIXME: In all of these cases, we need to show the template arguments
|
2009-03-10 18:03:33 +00:00
|
|
|
for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
|
|
|
|
Active = ActiveTemplateInstantiations.rbegin(),
|
|
|
|
ActiveEnd = ActiveTemplateInstantiations.rend();
|
|
|
|
Active != ActiveEnd;
|
|
|
|
++Active) {
|
2009-03-10 20:44:00 +00:00
|
|
|
switch (Active->Kind) {
|
|
|
|
case ActiveTemplateInstantiation::TemplateInstantiation: {
|
2009-05-18 17:01:57 +00: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-24 20:34:43 +00:00
|
|
|
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
|
2009-06-26 00:10:03 +00:00
|
|
|
unsigned DiagID;
|
|
|
|
if (Function->getPrimaryTemplate())
|
|
|
|
DiagID = diag::note_function_template_spec_here;
|
|
|
|
else
|
|
|
|
DiagID = diag::note_template_member_function_here;
|
2009-05-18 17:01:57 +00:00
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
DiagID)
|
|
|
|
<< Function
|
|
|
|
<< Active->InstantiationRange;
|
2009-07-24 20:34:43 +00:00
|
|
|
} else {
|
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_template_static_data_member_def_here)
|
|
|
|
<< cast<VarDecl>(D)
|
|
|
|
<< Active->InstantiationRange;
|
2009-05-18 17:01:57 +00:00
|
|
|
}
|
2009-03-10 20:44:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
|
|
|
|
TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
|
|
|
|
std::string TemplateArgsStr
|
2009-03-30 22:58:21 +00:00
|
|
|
= TemplateSpecializationType::PrintTemplateArgumentList(
|
2009-07-01 22:01:06 +00:00
|
|
|
Active->TemplateArgs,
|
2009-05-29 20:38:28 +00:00
|
|
|
Active->NumTemplateArgs,
|
|
|
|
Context.PrintingPolicy);
|
2009-03-10 20:44:00 +00:00
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
|
|
|
diag::note_default_arg_instantiation_here)
|
|
|
|
<< (Template->getNameAsString() + TemplateArgsStr)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
2009-06-10 23:47:09 +00:00
|
|
|
|
2009-07-01 22:01:06 +00:00
|
|
|
case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
|
|
|
|
FunctionTemplateDecl *FnTmpl
|
|
|
|
= cast<FunctionTemplateDecl>((Decl *)Active->Entity);
|
2009-06-10 23:47:09 +00:00
|
|
|
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
2009-07-01 22:01:06 +00:00
|
|
|
diag::note_explicit_template_arg_substitution_here)
|
|
|
|
<< FnTmpl << Active->InstantiationRange;
|
2009-06-10 23:47:09 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-07-01 22:01:06 +00: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-10 23:47:09 +00:00
|
|
|
|
2009-03-10 20:44:00 +00:00
|
|
|
}
|
2009-03-10 18:03:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-14 07:33:30 +00: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-01 22:01:06 +00:00
|
|
|
case ActiveTemplateInstantiation::TemplateInstantiation:
|
|
|
|
// This is a template instantiation, so there is no SFINAE.
|
|
|
|
return false;
|
|
|
|
|
2009-06-14 07:33:30 +00: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-01 22:01:06 +00: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 07:33:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-02-27 19:31:52 +00:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation for Types
|
|
|
|
//===----------------------------------------------------------------------===/
|
2009-02-28 00:25:32 +00:00
|
|
|
namespace {
|
|
|
|
class VISIBILITY_HIDDEN TemplateTypeInstantiator {
|
|
|
|
Sema &SemaRef;
|
2009-05-11 23:53:27 +00:00
|
|
|
const TemplateArgumentList &TemplateArgs;
|
2009-02-28 00:25:32 +00:00
|
|
|
SourceLocation Loc;
|
|
|
|
DeclarationName Entity;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TemplateTypeInstantiator(Sema &SemaRef,
|
2009-05-11 23:53:27 +00:00
|
|
|
const TemplateArgumentList &TemplateArgs,
|
2009-02-28 00:25:32 +00:00
|
|
|
SourceLocation Loc,
|
|
|
|
DeclarationName Entity)
|
|
|
|
: SemaRef(SemaRef), TemplateArgs(TemplateArgs),
|
2009-05-11 23:53:27 +00:00
|
|
|
Loc(Loc), Entity(Entity) { }
|
2009-02-28 00:25:32 +00:00
|
|
|
|
|
|
|
QualType operator()(QualType T) const { return Instantiate(T); }
|
|
|
|
|
|
|
|
QualType Instantiate(QualType T) const;
|
|
|
|
|
|
|
|
// Declare instantiate functions for each type.
|
|
|
|
#define TYPE(Class, Base) \
|
2009-06-26 21:40:05 +00:00
|
|
|
QualType Instantiate##Class##Type(const Class##Type *T) const;
|
2009-02-28 00:25:32 +00:00
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
};
|
|
|
|
}
|
2009-02-27 19:31:52 +00:00
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T) const {
|
2009-02-27 19:31:52 +00:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate ExtQualType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T) const {
|
2009-02-28 01:04:19 +00:00
|
|
|
assert(false && "Builtin types are not dependent and cannot be instantiated");
|
2009-06-26 21:40:05 +00:00
|
|
|
return QualType(T, 0);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateFixedWidthIntType(const FixedWidthIntType *T) const {
|
2009-02-27 19:31:52 +00:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate FixedWidthIntType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T) const {
|
2009-02-27 19:31:52 +00:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate ComplexType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T) const {
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType PointeeType = Instantiate(T->getPointeeType());
|
|
|
|
if (PointeeType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
2009-06-26 21:40:05 +00:00
|
|
|
return SemaRef.BuildPointerType(PointeeType, 0, Loc, Entity);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateBlockPointerType(
|
|
|
|
const BlockPointerType *T) const {
|
2009-06-12 16:23:10 +00:00
|
|
|
QualType PointeeType = Instantiate(T->getPointeeType());
|
|
|
|
if (PointeeType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
2009-06-26 21:40:05 +00:00
|
|
|
return SemaRef.BuildBlockPointerType(PointeeType, 0, Loc, Entity);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-03-16 23:22:08 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateLValueReferenceType(
|
2009-06-26 21:40:05 +00:00
|
|
|
const LValueReferenceType *T) const {
|
2009-03-16 23:22:08 +00:00
|
|
|
QualType ReferentType = Instantiate(T->getPointeeType());
|
|
|
|
if (ReferentType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
2009-06-26 21:40:05 +00:00
|
|
|
return SemaRef.BuildReferenceType(ReferentType, true, 0, Loc, Entity);
|
2009-03-16 23:22:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateRValueReferenceType(
|
2009-06-26 21:40:05 +00:00
|
|
|
const RValueReferenceType *T) const {
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType ReferentType = Instantiate(T->getPointeeType());
|
|
|
|
if (ReferentType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
2009-06-26 21:40:05 +00:00
|
|
|
return SemaRef.BuildReferenceType(ReferentType, false, 0, Loc, Entity);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateMemberPointerType(const MemberPointerType *T) const {
|
2009-06-09 22:17:39 +00:00
|
|
|
QualType PointeeType = Instantiate(T->getPointeeType());
|
|
|
|
if (PointeeType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
QualType ClassType = Instantiate(QualType(T->getClass(), 0));
|
|
|
|
if (ClassType.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
2009-06-26 21:40:05 +00:00
|
|
|
return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0, Loc,
|
2009-06-09 22:17:39 +00:00
|
|
|
Entity);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateConstantArrayType(const ConstantArrayType *T) const {
|
2009-02-28 00:25:32 +00:00
|
|
|
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
|
2009-05-13 18:28:20 +00:00
|
|
|
// there aren't any errors. However, we do need to determine what
|
|
|
|
// C++ type to give the size expression.
|
|
|
|
llvm::APInt Size = T->getSize();
|
|
|
|
QualType Types[] = {
|
|
|
|
SemaRef.Context.UnsignedCharTy, SemaRef.Context.UnsignedShortTy,
|
|
|
|
SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy,
|
|
|
|
SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty
|
|
|
|
};
|
|
|
|
const unsigned NumTypes = sizeof(Types) / sizeof(QualType);
|
|
|
|
QualType SizeType;
|
|
|
|
for (unsigned I = 0; I != NumTypes; ++I)
|
|
|
|
if (Size.getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) {
|
|
|
|
SizeType = Types[I];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SizeType.isNull())
|
|
|
|
SizeType = SemaRef.Context.getFixedWidthIntType(Size.getBitWidth(), false);
|
|
|
|
|
|
|
|
IntegerLiteral ArraySize(Size, SizeType, Loc);
|
2009-02-28 00:25:32 +00:00
|
|
|
return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(),
|
|
|
|
&ArraySize, T->getIndexTypeQualifier(),
|
2009-07-06 15:59:29 +00:00
|
|
|
SourceRange(), // FIXME: provide proper range?
|
|
|
|
Entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateConstantArrayWithExprType
|
|
|
|
(const ConstantArrayWithExprType *T) const {
|
|
|
|
return InstantiateConstantArrayType(T);
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::InstantiateConstantArrayWithoutExprType
|
|
|
|
(const ConstantArrayWithoutExprType *T) const {
|
|
|
|
return InstantiateConstantArrayType(T);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateIncompleteArrayType(const IncompleteArrayType *T) const {
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType ElementType = Instantiate(T->getElementType());
|
|
|
|
if (ElementType.isNull())
|
|
|
|
return ElementType;
|
|
|
|
|
|
|
|
return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(),
|
2009-07-06 15:59:29 +00:00
|
|
|
0, T->getIndexTypeQualifier(),
|
|
|
|
SourceRange(), // FIXME: provide proper range?
|
|
|
|
Entity);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateVariableArrayType(const VariableArrayType *T) const {
|
2009-02-27 19:31:52 +00:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate VariableArrayType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateDependentSizedArrayType(const DependentSizedArrayType *T) const {
|
2009-03-15 20:12:13 +00:00
|
|
|
Expr *ArraySize = T->getSizeExpr();
|
|
|
|
assert(ArraySize->isValueDependent() &&
|
|
|
|
"dependent sized array types must have value dependent size expr");
|
|
|
|
|
|
|
|
// Instantiate the element type if needed
|
|
|
|
QualType ElementType = T->getElementType();
|
|
|
|
if (ElementType->isDependentType()) {
|
|
|
|
ElementType = Instantiate(ElementType);
|
|
|
|
if (ElementType.isNull())
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantiate the size expression
|
2009-06-22 20:57:11 +00:00
|
|
|
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
|
2009-03-15 20:12:13 +00:00
|
|
|
Sema::OwningExprResult InstantiatedArraySize =
|
2009-05-11 23:53:27 +00:00
|
|
|
SemaRef.InstantiateExpr(ArraySize, TemplateArgs);
|
2009-03-15 20:12:13 +00:00
|
|
|
if (InstantiatedArraySize.isInvalid())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(),
|
2009-05-01 19:49:17 +00:00
|
|
|
InstantiatedArraySize.takeAs<Expr>(),
|
2009-07-06 15:59:29 +00:00
|
|
|
T->getIndexTypeQualifier(),
|
|
|
|
SourceRange(), // FIXME: provide proper range?
|
|
|
|
Entity);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-06-17 21:51:59 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateDependentSizedExtVectorType(
|
|
|
|
const DependentSizedExtVectorType *T) const {
|
2009-06-17 21:51:59 +00:00
|
|
|
|
2009-06-18 18:45:36 +00:00
|
|
|
// Instantiate the element type if needed.
|
2009-06-17 21:51:59 +00:00
|
|
|
QualType ElementType = T->getElementType();
|
|
|
|
if (ElementType->isDependentType()) {
|
|
|
|
ElementType = Instantiate(ElementType);
|
|
|
|
if (ElementType.isNull())
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-06-22 20:57:11 +00:00
|
|
|
// The expression in a dependent-sized extended vector type is not
|
|
|
|
// potentially evaluated.
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
|
|
|
|
|
2009-06-18 18:45:36 +00:00
|
|
|
// Instantiate the size expression.
|
|
|
|
const Expr *SizeExpr = T->getSizeExpr();
|
2009-06-17 21:51:59 +00:00
|
|
|
Sema::OwningExprResult InstantiatedArraySize =
|
2009-06-18 18:45:36 +00:00
|
|
|
SemaRef.InstantiateExpr(const_cast<Expr *>(SizeExpr), TemplateArgs);
|
2009-06-17 21:51:59 +00:00
|
|
|
if (InstantiatedArraySize.isInvalid())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.BuildExtVectorType(ElementType,
|
|
|
|
SemaRef.Owned(
|
|
|
|
InstantiatedArraySize.takeAs<Expr>()),
|
|
|
|
T->getAttributeLoc());
|
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T) const {
|
2009-02-27 19:31:52 +00:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate VectorType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateExtVectorType(
|
|
|
|
const ExtVectorType *T) const {
|
2009-02-27 19:31:52 +00:00
|
|
|
// FIXME: Implement this
|
|
|
|
assert(false && "Cannot instantiate ExtVectorType yet");
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateFunctionProtoType(const FunctionProtoType *T) const {
|
2009-02-28 01:04:19 +00:00
|
|
|
QualType ResultType = Instantiate(T->getResultType());
|
|
|
|
if (ResultType.isNull())
|
|
|
|
return ResultType;
|
|
|
|
|
2009-05-29 18:27:38 +00:00
|
|
|
llvm::SmallVector<QualType, 4> ParamTypes;
|
2009-02-28 01:04:19 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-06-11 18:10:32 +00:00
|
|
|
return SemaRef.BuildFunctionType(ResultType, ParamTypes.data(),
|
2009-02-28 01:04:19 +00:00
|
|
|
ParamTypes.size(),
|
|
|
|
T->isVariadic(), T->getTypeQuals(),
|
|
|
|
Loc, Entity);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateFunctionNoProtoType(const FunctionNoProtoType *T) const {
|
2009-02-28 01:04:19 +00:00
|
|
|
assert(false && "Functions without prototypes cannot be dependent.");
|
2009-02-27 19:31:52 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T) const {
|
2009-05-27 05:35:12 +00:00
|
|
|
TypedefDecl *Typedef
|
2009-05-27 17:54:46 +00:00
|
|
|
= cast_or_null<TypedefDecl>(
|
|
|
|
SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
|
2009-05-27 05:35:12 +00:00
|
|
|
if (!Typedef)
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.Context.getTypeDeclType(Typedef);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateTypeOfExprType(
|
|
|
|
const TypeOfExprType *T) const {
|
2009-06-22 20:57:11 +00:00
|
|
|
// The expression in a typeof is not potentially evaluated.
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
|
|
|
|
|
2009-05-26 22:09:24 +00:00
|
|
|
Sema::OwningExprResult E
|
|
|
|
= SemaRef.InstantiateExpr(T->getUnderlyingExpr(), TemplateArgs);
|
|
|
|
if (E.isInvalid())
|
|
|
|
return QualType();
|
|
|
|
|
2009-06-29 22:58:55 +00:00
|
|
|
return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T) const {
|
2009-05-26 22:09:24 +00:00
|
|
|
QualType Underlying = Instantiate(T->getUnderlyingType());
|
|
|
|
if (Underlying.isNull())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.Context.getTypeOfType(Underlying);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-06-24 19:06:50 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateDecltypeType(const DecltypeType *T) const {
|
2009-06-26 03:02:18 +00:00
|
|
|
// C++0x [dcl.type.simple]p4:
|
|
|
|
// The operand of the decltype specifier is an unevaluated operand.
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(SemaRef,
|
|
|
|
Action::Unevaluated);
|
|
|
|
|
2009-06-24 19:06:50 +00:00
|
|
|
Sema::OwningExprResult E
|
|
|
|
= SemaRef.InstantiateExpr(T->getUnderlyingExpr(), TemplateArgs);
|
|
|
|
|
|
|
|
if (E.isInvalid())
|
|
|
|
return QualType();
|
|
|
|
|
2009-06-29 22:58:55 +00:00
|
|
|
return SemaRef.BuildDecltypeType(E.takeAs<Expr>());
|
2009-06-24 19:06:50 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T) const {
|
2009-05-27 05:35:12 +00:00
|
|
|
RecordDecl *Record
|
2009-05-27 17:54:46 +00:00
|
|
|
= cast_or_null<RecordDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
|
2009-05-27 05:35:12 +00:00
|
|
|
if (!Record)
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.Context.getTypeDeclType(Record);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
2009-06-26 21:40:05 +00:00
|
|
|
TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T) const {
|
2009-05-27 05:35:12 +00:00
|
|
|
EnumDecl *Enum
|
2009-05-27 17:54:46 +00:00
|
|
|
= cast_or_null<EnumDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
|
2009-05-27 05:35:12 +00:00
|
|
|
if (!Enum)
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return SemaRef.Context.getTypeDeclType(Enum);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateTemplateTypeParmType(const TemplateTypeParmType *T) const {
|
2009-02-27 19:31:52 +00:00
|
|
|
if (T->getDepth() == 0) {
|
|
|
|
// Replace the template type parameter with its corresponding
|
|
|
|
// template argument.
|
2009-07-01 00:28:38 +00: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-27 19:31:52 +00:00
|
|
|
assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
|
|
|
|
"Template argument kind mismatch");
|
2009-06-26 21:40:05 +00:00
|
|
|
return TemplateArgs[T->getIndex()].getAsType();
|
2009-02-27 19:31:52 +00: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-06-16 00:30:48 +00:00
|
|
|
T->isParameterPack(),
|
2009-06-26 21:40:05 +00:00
|
|
|
T->getName());
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-03-30 22:58:21 +00:00
|
|
|
InstantiateTemplateSpecializationType(
|
2009-06-26 21:40:05 +00:00
|
|
|
const TemplateSpecializationType *T) const {
|
2009-05-29 18:27:38 +00:00
|
|
|
llvm::SmallVector<TemplateArgument, 4> InstantiatedTemplateArgs;
|
2009-03-09 23:48:35 +00:00
|
|
|
InstantiatedTemplateArgs.reserve(T->getNumArgs());
|
2009-03-30 22:58:21 +00:00
|
|
|
for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
|
2009-03-09 23:48:35 +00:00
|
|
|
Arg != ArgEnd; ++Arg) {
|
2009-06-11 00:06:24 +00:00
|
|
|
TemplateArgument InstArg = SemaRef.Instantiate(*Arg, TemplateArgs);
|
|
|
|
if (InstArg.isNull())
|
|
|
|
return QualType();
|
2009-03-09 23:48:35 +00:00
|
|
|
|
2009-06-11 00:06:24 +00:00
|
|
|
InstantiatedTemplateArgs.push_back(InstArg);
|
2009-03-09 23:48:35 +00:00
|
|
|
}
|
|
|
|
|
2009-05-16 07:39:55 +00:00
|
|
|
// FIXME: We're missing the locations of the template name, '<', and '>'.
|
2009-03-31 18:38:02 +00:00
|
|
|
|
|
|
|
TemplateName Name = SemaRef.InstantiateTemplateName(T->getTemplateName(),
|
|
|
|
Loc,
|
2009-05-11 23:53:27 +00:00
|
|
|
TemplateArgs);
|
2009-03-31 18:38:02 +00:00
|
|
|
|
|
|
|
return SemaRef.CheckTemplateIdType(Name, Loc, SourceLocation(),
|
2009-06-11 18:10:32 +00:00
|
|
|
InstantiatedTemplateArgs.data(),
|
2009-03-30 22:58:21 +00:00
|
|
|
InstantiatedTemplateArgs.size(),
|
|
|
|
SourceLocation());
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
|
|
|
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 00:18:19 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateQualifiedNameType(const QualifiedNameType *T) const {
|
2009-03-27 23:10:48 +00:00
|
|
|
// When we instantiated a qualified name type, there's no point in
|
|
|
|
// keeping the qualification around in the instantiated result. So,
|
|
|
|
// just instantiate the named type.
|
|
|
|
return (*this)(T->getNamedType());
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateTypenameType(const TypenameType *T) const {
|
2009-04-01 00:28:59 +00:00
|
|
|
if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
|
|
|
|
// When the typename type refers to a template-id, the template-id
|
|
|
|
// is dependent and has enough information to instantiate the
|
|
|
|
// result of the typename type. Since we don't care about keeping
|
|
|
|
// the spelling of the typename type in template instantiations,
|
|
|
|
// we just instantiate the template-id.
|
2009-06-26 21:40:05 +00:00
|
|
|
return InstantiateTemplateSpecializationType(TemplateId);
|
2009-04-01 00:28:59 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 23:10:48 +00:00
|
|
|
NestedNameSpecifier *NNS
|
|
|
|
= SemaRef.InstantiateNestedNameSpecifier(T->getQualifier(),
|
|
|
|
SourceRange(Loc),
|
2009-05-11 23:53:27 +00:00
|
|
|
TemplateArgs);
|
2009-03-27 23:10:48 +00:00
|
|
|
if (!NNS)
|
|
|
|
return QualType();
|
|
|
|
|
2009-04-01 00:28:59 +00:00
|
|
|
return SemaRef.CheckTypenameType(NNS, *T->getIdentifier(), SourceRange(Loc));
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 00:18:19 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00:00
|
|
|
QualType
|
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateObjCObjectPointerType(const ObjCObjectPointerType *T) const {
|
2009-02-28 00:25:32 +00:00
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-27 19:31:52 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-06-17 22:40:22 +00:00
|
|
|
QualType
|
2009-02-28 00:25:32 +00:00
|
|
|
TemplateTypeInstantiator::
|
2009-06-26 21:40:05 +00:00
|
|
|
InstantiateObjCInterfaceType(const ObjCInterfaceType *T) const {
|
2009-02-28 00:25:32 +00:00
|
|
|
assert(false && "Objective-C types cannot be dependent");
|
2009-02-27 19:31:52 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-02-28 00:25:32 +00: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;
|
|
|
|
|
2009-06-26 21:40:05 +00:00
|
|
|
QualType Result;
|
2009-02-28 00:25:32 +00:00
|
|
|
switch (T->getTypeClass()) {
|
|
|
|
#define TYPE(Class, Base) \
|
|
|
|
case Type::Class: \
|
2009-06-26 21:40:05 +00:00
|
|
|
Result = Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr())); \
|
|
|
|
break;
|
2009-02-28 00:25:32 +00:00
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
}
|
2009-06-26 21:40:05 +00:00
|
|
|
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// The same rule applies to function types.
|
2009-07-22 20:02:25 +00:00
|
|
|
// FIXME: what about address-space and Objective-C GC qualifiers?
|
2009-06-26 21:40:05 +00:00
|
|
|
if (!Result.isNull() && T.getCVRQualifiers() &&
|
|
|
|
!Result->isFunctionType() && !Result->isReferenceType())
|
|
|
|
Result = Result.getWithAdditionalQualifiers(T.getCVRQualifiers());
|
|
|
|
return Result;
|
2009-02-28 00:25:32 +00:00
|
|
|
}
|
2009-02-27 19:31:52 +00: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-11 23:53:27 +00:00
|
|
|
const TemplateArgumentList &TemplateArgs,
|
2009-02-27 19:31:52 +00:00
|
|
|
SourceLocation Loc, DeclarationName Entity) {
|
2009-03-10 20:44:00 +00:00
|
|
|
assert(!ActiveTemplateInstantiations.empty() &&
|
|
|
|
"Cannot perform an instantiation without some context on the "
|
|
|
|
"instantiation stack");
|
|
|
|
|
2009-02-27 19:31:52 +00:00
|
|
|
// If T is not a dependent type, there is nothing to do.
|
|
|
|
if (!T->isDependentType())
|
|
|
|
return T;
|
|
|
|
|
2009-05-11 23:53:27 +00:00
|
|
|
TemplateTypeInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
|
2009-02-28 00:25:32 +00:00
|
|
|
return Instantiator(T);
|
2009-02-27 19:31:52 +00:00
|
|
|
}
|
2009-03-03 04:44:36 +00: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-25 21:17:03 +00:00
|
|
|
Sema::InstantiateBaseSpecifiers(CXXRecordDecl *Instantiation,
|
|
|
|
CXXRecordDecl *Pattern,
|
2009-05-11 23:53:27 +00:00
|
|
|
const TemplateArgumentList &TemplateArgs) {
|
2009-03-03 04:44:36 +00:00
|
|
|
bool Invalid = false;
|
2009-05-29 18:27:38 +00:00
|
|
|
llvm::SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
|
2009-03-25 21:17:03 +00:00
|
|
|
for (ClassTemplateSpecializationDecl::base_class_iterator
|
|
|
|
Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
|
2009-03-10 18:52:44 +00:00
|
|
|
Base != BaseEnd; ++Base) {
|
2009-03-03 04:44:36 +00:00
|
|
|
if (!Base->getType()->isDependentType()) {
|
2009-07-22 17:41:53 +00:00
|
|
|
InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
|
2009-03-03 04:44:36 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType BaseType = InstantiateType(Base->getType(),
|
2009-05-11 23:53:27 +00:00
|
|
|
TemplateArgs,
|
2009-03-03 04:44:36 +00:00
|
|
|
Base->getSourceRange().getBegin(),
|
|
|
|
DeclarationName());
|
|
|
|
if (BaseType.isNull()) {
|
|
|
|
Invalid = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CXXBaseSpecifier *InstantiatedBase
|
2009-03-25 21:17:03 +00:00
|
|
|
= CheckBaseSpecifier(Instantiation,
|
2009-03-03 04:44:36 +00:00
|
|
|
Base->getSourceRange(),
|
|
|
|
Base->isVirtual(),
|
|
|
|
Base->getAccessSpecifierAsWritten(),
|
|
|
|
BaseType,
|
|
|
|
/*FIXME: Not totally accurate */
|
|
|
|
Base->getSourceRange().getBegin()))
|
|
|
|
InstantiatedBases.push_back(InstantiatedBase);
|
|
|
|
else
|
|
|
|
Invalid = true;
|
|
|
|
}
|
|
|
|
|
2009-03-10 18:52:44 +00:00
|
|
|
if (!Invalid &&
|
2009-05-21 09:52:38 +00:00
|
|
|
AttachBaseSpecifiers(Instantiation, InstantiatedBases.data(),
|
2009-03-03 04:44:36 +00:00
|
|
|
InstantiatedBases.size()))
|
|
|
|
Invalid = true;
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
}
|
|
|
|
|
2009-03-25 21:17:03 +00: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 00:25:59 +00:00
|
|
|
const TemplateArgumentList &TemplateArgs,
|
|
|
|
bool ExplicitInstantiation) {
|
2009-03-25 21:17:03 +00: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 00:25:59 +00:00
|
|
|
Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
|
|
|
|
<< ExplicitInstantiation
|
2009-03-25 21:17:03 +00:00
|
|
|
<< Context.getTypeDeclType(Instantiation);
|
|
|
|
Diag(Pattern->getLocation(), diag::note_template_decl_here);
|
|
|
|
}
|
2009-03-03 04:44:36 +00:00
|
|
|
return true;
|
|
|
|
}
|
2009-03-25 21:17:03 +00:00
|
|
|
Pattern = PatternDef;
|
2009-03-03 04:44:36 +00:00
|
|
|
|
2009-03-25 21:23:52 +00:00
|
|
|
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
|
2009-03-10 00:06:19 +00:00
|
|
|
if (Inst)
|
|
|
|
return true;
|
|
|
|
|
2009-03-03 04:44:36 +00:00
|
|
|
// Enter the scope of this instantiation. We don't use
|
|
|
|
// PushDeclContext because we don't have a scope.
|
|
|
|
DeclContext *PreviousContext = CurContext;
|
2009-03-25 21:17:03 +00:00
|
|
|
CurContext = Instantiation;
|
2009-03-03 04:44:36 +00:00
|
|
|
|
|
|
|
// Start the definition of this instantiation.
|
2009-03-25 21:17:03 +00:00
|
|
|
Instantiation->startDefinition();
|
2009-03-03 04:44:36 +00:00
|
|
|
|
|
|
|
// Instantiate the base class specifiers.
|
2009-05-11 23:53:27 +00:00
|
|
|
if (InstantiateBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
|
2009-03-03 04:44:36 +00:00
|
|
|
Invalid = true;
|
|
|
|
|
2009-05-29 18:27:38 +00:00
|
|
|
llvm::SmallVector<DeclPtrTy, 4> Fields;
|
2009-06-30 02:36:12 +00:00
|
|
|
for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
|
|
|
|
MemberEnd = Pattern->decls_end();
|
2009-04-09 21:40:53 +00:00
|
|
|
Member != MemberEnd; ++Member) {
|
2009-05-11 23:53:27 +00:00
|
|
|
Decl *NewMember = InstantiateDecl(*Member, Instantiation, TemplateArgs);
|
2009-03-17 21:15:40 +00:00
|
|
|
if (NewMember) {
|
|
|
|
if (NewMember->isInvalidDecl())
|
2009-03-15 18:44:04 +00:00
|
|
|
Invalid = true;
|
2009-03-17 21:15:40 +00:00
|
|
|
else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
|
2009-03-28 19:18:32 +00:00
|
|
|
Fields.push_back(DeclPtrTy::make(Field));
|
2009-03-17 21:15:40 +00:00
|
|
|
} else {
|
|
|
|
// FIXME: Eventually, a NULL return will mean that one of the
|
2009-05-16 07:39:55 +00: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-11 16:48:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-11 18:59:21 +00:00
|
|
|
// Finish checking fields.
|
2009-03-28 19:18:32 +00:00
|
|
|
ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
|
2009-05-21 09:52:38 +00:00
|
|
|
Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
|
2009-03-11 18:59:21 +00:00
|
|
|
0);
|
|
|
|
|
2009-03-03 04:44:36 +00:00
|
|
|
// Add any implicitly-declared members that we might need.
|
2009-03-25 21:17:03 +00:00
|
|
|
AddImplicitlyDeclaredMembersToClass(Instantiation);
|
2009-03-03 04:44:36 +00:00
|
|
|
|
|
|
|
// Exit the scope of this instantiation.
|
|
|
|
CurContext = PreviousContext;
|
|
|
|
|
2009-05-26 20:50:29 +00:00
|
|
|
if (!Invalid)
|
|
|
|
Consumer.HandleTagDeclDefinition(Instantiation);
|
|
|
|
|
2009-05-13 20:28:22 +00:00
|
|
|
// If this is an explicit instantiation, instantiate our members, too.
|
2009-05-18 17:01:57 +00:00
|
|
|
if (!Invalid && ExplicitInstantiation) {
|
|
|
|
Inst.Clear();
|
2009-05-13 20:28:22 +00:00
|
|
|
InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs);
|
2009-05-18 17:01:57 +00:00
|
|
|
}
|
2009-05-13 20:28:22 +00:00
|
|
|
|
2009-03-03 04:44:36 +00: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-19 17:26:29 +00:00
|
|
|
|
2009-03-25 21:17:03 +00:00
|
|
|
bool
|
|
|
|
Sema::InstantiateClassTemplateSpecialization(
|
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
|
|
|
bool ExplicitInstantiation) {
|
|
|
|
// Perform the actual instantiation on the canonical declaration.
|
|
|
|
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
|
2009-07-18 00:34:25 +00:00
|
|
|
ClassTemplateSpec->getCanonicalDecl());
|
2009-03-25 21:17:03 +00: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 09:31:02 +00:00
|
|
|
const TemplateArgumentList *TemplateArgs
|
|
|
|
= &ClassTemplateSpec->getTemplateArgs();
|
|
|
|
|
2009-06-12 22:31:52 +00: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 00:53:49 +00:00
|
|
|
typedef std::pair<ClassTemplatePartialSpecializationDecl *,
|
|
|
|
TemplateArgumentList *> MatchResult;
|
|
|
|
llvm::SmallVector<MatchResult, 4> Matched;
|
2009-05-31 09:31:02 +00:00
|
|
|
for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
|
|
|
|
Partial = Template->getPartialSpecializations().begin(),
|
|
|
|
PartialEnd = Template->getPartialSpecializations().end();
|
|
|
|
Partial != PartialEnd;
|
|
|
|
++Partial) {
|
2009-06-12 18:26:56 +00:00
|
|
|
TemplateDeductionInfo Info(Context);
|
|
|
|
if (TemplateDeductionResult Result
|
2009-06-05 00:53:49 +00:00
|
|
|
= DeduceTemplateArguments(&*Partial,
|
2009-06-12 18:26:56 +00: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 09:31:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Matched.size() == 1) {
|
2009-06-12 22:31:52 +00:00
|
|
|
// -- If exactly one matching specialization is found, the
|
|
|
|
// instantiation is generated from that specialization.
|
2009-06-05 00:53:49 +00:00
|
|
|
Pattern = Matched[0].first;
|
|
|
|
TemplateArgs = Matched[0].second;
|
2009-05-31 09:31:02 +00:00
|
|
|
} else if (Matched.size() > 1) {
|
2009-06-12 22:31:52 +00: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 09:31:02 +00:00
|
|
|
// FIXME: Implement partial ordering of class template partial
|
|
|
|
// specializations.
|
|
|
|
Diag(ClassTemplateSpec->getLocation(),
|
|
|
|
diag::unsup_template_partial_spec_ordering);
|
2009-06-12 22:31:52 +00: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 09:31:02 +00:00
|
|
|
}
|
2009-03-25 21:17:03 +00:00
|
|
|
|
|
|
|
// Note that this is an instantiation.
|
|
|
|
ClassTemplateSpec->setSpecializationKind(
|
|
|
|
ExplicitInstantiation? TSK_ExplicitInstantiation
|
|
|
|
: TSK_ImplicitInstantiation);
|
|
|
|
|
2009-06-05 00:53:49 +00: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-25 21:17:03 +00:00
|
|
|
}
|
|
|
|
|
2009-05-13 20:28:22 +00: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 02:36:12 +00:00
|
|
|
for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
|
|
|
|
DEnd = Instantiation->decls_end();
|
2009-05-13 20:28:22 +00:00
|
|
|
D != DEnd; ++D) {
|
|
|
|
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
|
2009-06-30 02:35:26 +00:00
|
|
|
if (!Function->getBody())
|
2009-05-18 17:01:57 +00:00
|
|
|
InstantiateFunctionDefinition(PointOfInstantiation, Function);
|
2009-05-13 20:28:22 +00:00
|
|
|
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
|
2009-07-24 20:34:43 +00:00
|
|
|
if (Var->isStaticDataMember())
|
|
|
|
InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
|
2009-05-13 20:28:22 +00: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-18 17:01:57 +00:00
|
|
|
InstantiateClass(PointOfInstantiation, Record,
|
2009-05-13 20:28:22 +00: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-03-26 23:50:42 +00:00
|
|
|
/// \brief Instantiate a nested-name-specifier.
|
|
|
|
NestedNameSpecifier *
|
|
|
|
Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
|
|
|
|
SourceRange Range,
|
2009-05-11 23:53:27 +00:00
|
|
|
const TemplateArgumentList &TemplateArgs) {
|
2009-03-26 23:50:42 +00:00
|
|
|
// Instantiate the prefix of this nested name specifier.
|
|
|
|
NestedNameSpecifier *Prefix = NNS->getPrefix();
|
|
|
|
if (Prefix) {
|
2009-05-11 23:53:27 +00:00
|
|
|
Prefix = InstantiateNestedNameSpecifier(Prefix, Range, TemplateArgs);
|
2009-03-26 23:50:42 +00:00
|
|
|
if (!Prefix)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (NNS->getKind()) {
|
2009-04-01 00:28:59 +00:00
|
|
|
case NestedNameSpecifier::Identifier: {
|
|
|
|
assert(Prefix &&
|
|
|
|
"Can't have an identifier nested-name-specifier with no prefix");
|
|
|
|
CXXScopeSpec SS;
|
|
|
|
// FIXME: The source location information is all wrong.
|
|
|
|
SS.setRange(Range);
|
|
|
|
SS.setScopeRep(Prefix);
|
|
|
|
return static_cast<NestedNameSpecifier *>(
|
|
|
|
ActOnCXXNestedNameSpecifier(0, SS,
|
|
|
|
Range.getEnd(),
|
|
|
|
Range.getEnd(),
|
2009-05-14 00:28:11 +00:00
|
|
|
*NNS->getAsIdentifier()));
|
2009-03-26 23:50:42 +00:00
|
|
|
break;
|
2009-04-01 00:28:59 +00:00
|
|
|
}
|
2009-03-26 23:50:42 +00:00
|
|
|
|
|
|
|
case NestedNameSpecifier::Namespace:
|
|
|
|
case NestedNameSpecifier::Global:
|
|
|
|
return NNS;
|
|
|
|
|
|
|
|
case NestedNameSpecifier::TypeSpecWithTemplate:
|
|
|
|
case NestedNameSpecifier::TypeSpec: {
|
|
|
|
QualType T = QualType(NNS->getAsType(), 0);
|
|
|
|
if (!T->isDependentType())
|
|
|
|
return NNS;
|
|
|
|
|
2009-05-11 23:53:27 +00:00
|
|
|
T = InstantiateType(T, TemplateArgs, Range.getBegin(), DeclarationName());
|
2009-03-26 23:50:42 +00:00
|
|
|
if (T.isNull())
|
|
|
|
return 0;
|
|
|
|
|
2009-06-13 04:51:30 +00:00
|
|
|
if (T->isDependentType() || T->isRecordType() ||
|
2009-03-27 23:10:48 +00:00
|
|
|
(getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
|
2009-04-01 00:28:59 +00:00
|
|
|
assert(T.getCVRQualifiers() == 0 && "Can't get cv-qualifiers here");
|
2009-03-27 23:10:48 +00:00
|
|
|
return NestedNameSpecifier::Create(Context, Prefix,
|
2009-03-26 23:50:42 +00:00
|
|
|
NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
|
2009-03-27 23:10:48 +00:00
|
|
|
T.getTypePtr());
|
|
|
|
}
|
|
|
|
|
|
|
|
Diag(Range.getBegin(), diag::err_nested_name_spec_non_tag) << T;
|
|
|
|
return 0;
|
2009-03-26 23:50:42 +00:00
|
|
|
}
|
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-19 17:26:29 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 23:10:48 +00:00
|
|
|
// Required to silence a GCC warning
|
2009-03-26 23:50:42 +00:00
|
|
|
return 0;
|
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-19 17:26:29 +00:00
|
|
|
}
|
2009-03-31 18:38:02 +00:00
|
|
|
|
|
|
|
TemplateName
|
|
|
|
Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
|
2009-05-11 23:53:27 +00:00
|
|
|
const TemplateArgumentList &TemplateArgs) {
|
2009-03-31 18:38:02 +00:00
|
|
|
if (TemplateTemplateParmDecl *TTP
|
|
|
|
= dyn_cast_or_null<TemplateTemplateParmDecl>(
|
|
|
|
Name.getAsTemplateDecl())) {
|
|
|
|
assert(TTP->getDepth() == 0 &&
|
|
|
|
"Cannot reduce depth of a template template parameter");
|
2009-03-31 20:22:05 +00:00
|
|
|
assert(TemplateArgs[TTP->getPosition()].getAsDecl() &&
|
2009-03-31 18:38:02 +00:00
|
|
|
"Wrong kind of template template argument");
|
|
|
|
ClassTemplateDecl *ClassTemplate
|
|
|
|
= dyn_cast<ClassTemplateDecl>(
|
|
|
|
TemplateArgs[TTP->getPosition()].getAsDecl());
|
2009-03-31 20:22:05 +00:00
|
|
|
assert(ClassTemplate && "Expected a class template");
|
2009-03-31 18:38:02 +00:00
|
|
|
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
|
|
|
|
NestedNameSpecifier *NNS
|
|
|
|
= InstantiateNestedNameSpecifier(QTN->getQualifier(),
|
|
|
|
/*FIXME=*/SourceRange(Loc),
|
2009-05-11 23:53:27 +00:00
|
|
|
TemplateArgs);
|
2009-03-31 18:38:02 +00:00
|
|
|
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),
|
2009-05-11 23:53:27 +00:00
|
|
|
TemplateArgs);
|
2009-03-31 18:38:02 +00:00
|
|
|
|
|
|
|
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>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-05-16 07:39:55 +00:00
|
|
|
// 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.
|
2009-03-31 18:38:02 +00:00
|
|
|
return Name;
|
|
|
|
}
|
2009-06-11 00:06:24 +00:00
|
|
|
|
|
|
|
TemplateArgument Sema::Instantiate(TemplateArgument Arg,
|
|
|
|
const TemplateArgumentList &TemplateArgs) {
|
|
|
|
switch (Arg.getKind()) {
|
|
|
|
case TemplateArgument::Null:
|
|
|
|
assert(false && "Should never have a NULL template argument");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TemplateArgument::Type: {
|
|
|
|
QualType T = InstantiateType(Arg.getAsType(), TemplateArgs,
|
|
|
|
Arg.getLocation(), DeclarationName());
|
|
|
|
if (T.isNull())
|
|
|
|
return TemplateArgument();
|
|
|
|
|
|
|
|
return TemplateArgument(Arg.getLocation(), T);
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateArgument::Declaration:
|
|
|
|
// FIXME: Template instantiation for template template parameters.
|
|
|
|
return Arg;
|
|
|
|
|
|
|
|
case TemplateArgument::Integral:
|
|
|
|
return Arg;
|
|
|
|
|
|
|
|
case TemplateArgument::Expression: {
|
2009-06-22 20:57:11 +00:00
|
|
|
// Template argument expressions are not potentially evaluated.
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
|
|
|
|
|
2009-06-11 00:06:24 +00:00
|
|
|
Sema::OwningExprResult E = InstantiateExpr(Arg.getAsExpr(), TemplateArgs);
|
|
|
|
if (E.isInvalid())
|
|
|
|
return TemplateArgument();
|
|
|
|
return TemplateArgument(E.takeAs<Expr>());
|
|
|
|
}
|
2009-06-15 17:04:53 +00:00
|
|
|
|
|
|
|
case TemplateArgument::Pack:
|
|
|
|
assert(0 && "FIXME: Implement!");
|
|
|
|
break;
|
2009-06-11 00:06:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(false && "Unhandled template argument kind");
|
|
|
|
return TemplateArgument();
|
|
|
|
}
|