//===------- 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/DeclTemplate.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
//===----------------------------------------------------------------------===/
// Template Instantiation Support
//===----------------------------------------------------------------------===/
/// \brief Retrieve the template argument list that should be used to
/// instantiate the given declaration.
const TemplateArgumentList &
Sema::getTemplateInstantiationArgs(NamedDecl *D) {
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(D))
return Spec->getTemplateArgs();
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();
}
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Decl *Entity,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
Invalid = CheckInstantiationDepth(PointOfInstantiation,
InstantiationRange);
if (!Invalid) {
ActiveTemplateInstantiation Inst;
Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
Inst.TemplateArgs = 0;
Inst.NumTemplateArgs = 0;
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) {
ActiveTemplateInstantiation Inst;
Inst.Kind
= ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Entity = reinterpret_cast<uintptr_t>(Template);
Inst.TemplateArgs = TemplateArgs;
Inst.NumTemplateArgs = NumTemplateArgs;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
Invalid = false;
}
}
void Sema::InstantiatingTemplate::Clear() {
if (!Invalid) {
SemaRef.ActiveTemplateInstantiations.pop_back();
Invalid = true;
}
}
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;
}
/// \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) {
switch (Active->Kind) {
case ActiveTemplateInstantiation::TemplateInstantiation: {
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;