2009-10-24 06:13:42 +08:00
|
|
|
//===--- DeclTemplate.cpp - Template Declaration AST Node Implementation --===//
|
2009-02-05 03:02:06 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the C++ related Decl classes for templates.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2009-02-10 02:46:07 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2011-01-04 10:33:52 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2009-02-05 03:02:06 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2009-10-29 16:12:44 +08:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2010-10-28 15:38:42 +08:00
|
|
|
#include "clang/AST/ASTMutationListener.h"
|
2009-02-05 03:02:06 +08:00
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2010-11-08 07:05:16 +08:00
|
|
|
#include <memory>
|
2009-02-05 03:02:06 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateParameterList Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-07 06:42:48 +08:00
|
|
|
TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
|
|
|
|
SourceLocation LAngleLoc,
|
2009-09-16 00:23:51 +08:00
|
|
|
NamedDecl **Params, unsigned NumParams,
|
2009-02-07 06:42:48 +08:00
|
|
|
SourceLocation RAngleLoc)
|
|
|
|
: TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
|
2012-09-07 10:06:42 +08:00
|
|
|
NumParams(NumParams), ContainsUnexpandedParameterPack(false) {
|
|
|
|
assert(this->NumParams == NumParams && "Too many template parameters");
|
|
|
|
for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
|
|
|
|
NamedDecl *P = Params[Idx];
|
|
|
|
begin()[Idx] = P;
|
|
|
|
|
|
|
|
if (!P->isTemplateParameterPack()) {
|
|
|
|
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
|
|
|
|
if (NTTP->getType()->containsUnexpandedParameterPack())
|
|
|
|
ContainsUnexpandedParameterPack = true;
|
|
|
|
|
|
|
|
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
|
|
|
|
if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
|
|
|
|
ContainsUnexpandedParameterPack = true;
|
|
|
|
|
|
|
|
// FIXME: If a default argument contains an unexpanded parameter pack, the
|
|
|
|
// template parameter list does too.
|
|
|
|
}
|
|
|
|
}
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TemplateParameterList *
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
|
2009-09-16 00:23:51 +08:00
|
|
|
SourceLocation LAngleLoc, NamedDecl **Params,
|
2009-02-07 06:42:48 +08:00
|
|
|
unsigned NumParams, SourceLocation RAngleLoc) {
|
2009-09-16 00:23:51 +08:00
|
|
|
unsigned Size = sizeof(TemplateParameterList)
|
|
|
|
+ sizeof(NamedDecl *) * NumParams;
|
2012-08-17 06:51:34 +08:00
|
|
|
unsigned Align = std::max(llvm::alignOf<TemplateParameterList>(),
|
|
|
|
llvm::alignOf<NamedDecl*>());
|
2009-02-05 03:02:06 +08:00
|
|
|
void *Mem = C.Allocate(Size, Align);
|
2009-09-09 23:08:12 +08:00
|
|
|
return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
|
2009-02-07 06:42:48 +08:00
|
|
|
NumParams, RAngleLoc);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2009-02-12 02:16:40 +08:00
|
|
|
unsigned TemplateParameterList::getMinRequiredArguments() const {
|
2011-01-20 04:10:05 +08:00
|
|
|
unsigned NumRequiredArgs = 0;
|
|
|
|
for (iterator P = const_cast<TemplateParameterList *>(this)->begin(),
|
|
|
|
PEnd = const_cast<TemplateParameterList *>(this)->end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
if ((*P)->isTemplateParameterPack()) {
|
|
|
|
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P))
|
|
|
|
if (NTTP->isExpandedParameterPack()) {
|
|
|
|
NumRequiredArgs += NTTP->getNumExpansionTypes();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-02-12 02:16:40 +08:00
|
|
|
break;
|
2011-01-20 04:10:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
|
|
|
|
if (TTP->hasDefaultArgument())
|
|
|
|
break;
|
|
|
|
} else if (NonTypeTemplateParmDecl *NTTP
|
|
|
|
= dyn_cast<NonTypeTemplateParmDecl>(*P)) {
|
|
|
|
if (NTTP->hasDefaultArgument())
|
|
|
|
break;
|
|
|
|
} else if (cast<TemplateTemplateParmDecl>(*P)->hasDefaultArgument())
|
|
|
|
break;
|
|
|
|
|
|
|
|
++NumRequiredArgs;
|
2009-02-12 02:16:40 +08:00
|
|
|
}
|
2011-01-20 04:10:05 +08:00
|
|
|
|
2009-02-12 02:16:40 +08:00
|
|
|
return NumRequiredArgs;
|
|
|
|
}
|
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
unsigned TemplateParameterList::getDepth() const {
|
|
|
|
if (size() == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
const NamedDecl *FirstParm = getParam(0);
|
|
|
|
if (const TemplateTypeParmDecl *TTP
|
|
|
|
= dyn_cast<TemplateTypeParmDecl>(FirstParm))
|
|
|
|
return TTP->getDepth();
|
|
|
|
else if (const NonTypeTemplateParmDecl *NTTP
|
|
|
|
= dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
|
|
|
|
return NTTP->getDepth();
|
|
|
|
else
|
|
|
|
return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
|
|
|
|
}
|
|
|
|
|
2011-03-05 02:32:38 +08:00
|
|
|
static void AdoptTemplateParameterList(TemplateParameterList *Params,
|
|
|
|
DeclContext *Owner) {
|
|
|
|
for (TemplateParameterList::iterator P = Params->begin(),
|
|
|
|
PEnd = Params->end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
(*P)->setDeclContext(Owner);
|
|
|
|
|
|
|
|
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(*P))
|
|
|
|
AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-30 00:11:51 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RedeclarableTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() {
|
2012-01-14 23:13:49 +08:00
|
|
|
if (!Common) {
|
|
|
|
// Walk the previous-declaration chain until we either find a declaration
|
|
|
|
// with a common pointer or we run out of previous declarations.
|
|
|
|
llvm::SmallVector<RedeclarableTemplateDecl *, 2> PrevDecls;
|
2012-01-15 00:38:05 +08:00
|
|
|
for (RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
|
|
|
|
Prev = Prev->getPreviousDecl()) {
|
2012-01-14 23:13:49 +08:00
|
|
|
if (Prev->Common) {
|
|
|
|
Common = Prev->Common;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
PrevDecls.push_back(Prev);
|
|
|
|
}
|
2010-07-30 00:11:51 +08:00
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
// If we never found a common pointer, allocate one now.
|
2012-01-14 23:30:55 +08:00
|
|
|
if (!Common) {
|
|
|
|
// FIXME: If any of the declarations is from an AST file, we probably
|
|
|
|
// need an update record to add the common data.
|
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
Common = newCommon(getASTContext());
|
2012-01-14 23:30:55 +08:00
|
|
|
}
|
2012-01-14 23:13:49 +08:00
|
|
|
|
|
|
|
// Update any previous declarations we saw with the common pointer.
|
|
|
|
for (unsigned I = 0, N = PrevDecls.size(); I != N; ++I)
|
|
|
|
PrevDecls[I]->Common = Common;
|
2010-07-30 00:12:01 +08:00
|
|
|
}
|
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
return Common;
|
2010-07-30 00:12:09 +08:00
|
|
|
}
|
|
|
|
|
2010-07-31 01:09:04 +08:00
|
|
|
template <class EntryType>
|
|
|
|
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType*
|
|
|
|
RedeclarableTemplateDecl::findSpecializationImpl(
|
2012-05-04 07:49:05 +08:00
|
|
|
llvm::FoldingSetVector<EntryType> &Specs,
|
2010-07-31 01:09:04 +08:00
|
|
|
const TemplateArgument *Args, unsigned NumArgs,
|
|
|
|
void *&InsertPos) {
|
|
|
|
typedef SpecEntryTraits<EntryType> SETraits;
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
EntryType::Profile(ID,Args,NumArgs, getASTContext());
|
|
|
|
EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
|
2012-01-15 00:38:05 +08:00
|
|
|
return Entry ? SETraits::getMostRecentDecl(Entry) : 0;
|
2010-07-31 01:09:04 +08:00
|
|
|
}
|
|
|
|
|
2011-03-06 01:54:25 +08:00
|
|
|
/// \brief Generate the injected template arguments for the given template
|
|
|
|
/// parameter list, e.g., for the injected-class-name of a class template.
|
|
|
|
static void GenerateInjectedTemplateArgs(ASTContext &Context,
|
|
|
|
TemplateParameterList *Params,
|
|
|
|
TemplateArgument *Args) {
|
|
|
|
for (TemplateParameterList::iterator Param = Params->begin(),
|
|
|
|
ParamEnd = Params->end();
|
|
|
|
Param != ParamEnd; ++Param) {
|
|
|
|
TemplateArgument Arg;
|
|
|
|
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
|
|
|
|
QualType ArgType = Context.getTypeDeclType(TTP);
|
|
|
|
if (TTP->isParameterPack())
|
|
|
|
ArgType = Context.getPackExpansionType(ArgType,
|
|
|
|
llvm::Optional<unsigned>());
|
|
|
|
|
|
|
|
Arg = TemplateArgument(ArgType);
|
|
|
|
} else if (NonTypeTemplateParmDecl *NTTP =
|
|
|
|
dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
|
2012-03-10 17:33:50 +08:00
|
|
|
Expr *E = new (Context) DeclRefExpr(NTTP, /*enclosing*/ false,
|
2011-03-06 01:54:25 +08:00
|
|
|
NTTP->getType().getNonLValueExprType(Context),
|
|
|
|
Expr::getValueKindForType(NTTP->getType()),
|
|
|
|
NTTP->getLocation());
|
|
|
|
|
|
|
|
if (NTTP->isParameterPack())
|
|
|
|
E = new (Context) PackExpansionExpr(Context.DependentTy, E,
|
|
|
|
NTTP->getLocation(),
|
|
|
|
llvm::Optional<unsigned>());
|
|
|
|
Arg = TemplateArgument(E);
|
|
|
|
} else {
|
|
|
|
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
|
|
|
|
if (TTP->isParameterPack())
|
|
|
|
Arg = TemplateArgument(TemplateName(TTP), llvm::Optional<unsigned>());
|
|
|
|
else
|
|
|
|
Arg = TemplateArgument(TemplateName(TTP));
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*Param)->isTemplateParameterPack())
|
|
|
|
Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1);
|
|
|
|
|
|
|
|
*Args++ = Arg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// FunctionTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-05-24 02:26:36 +08:00
|
|
|
void FunctionTemplateDecl::DeallocateCommon(void *Ptr) {
|
|
|
|
static_cast<Common *>(Ptr)->~Common();
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
DeclarationName Name,
|
2009-06-30 04:59:39 +08:00
|
|
|
TemplateParameterList *Params,
|
2009-02-05 03:02:06 +08:00
|
|
|
NamedDecl *Decl) {
|
2011-03-05 02:32:38 +08:00
|
|
|
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
2009-02-05 03:02:06 +08:00
|
|
|
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
|
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionTemplateDecl));
|
|
|
|
return new (Mem) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(),
|
|
|
|
0, 0);
|
2011-03-05 01:52:15 +08:00
|
|
|
}
|
|
|
|
|
2010-09-09 03:31:22 +08:00
|
|
|
RedeclarableTemplateDecl::CommonBase *
|
|
|
|
FunctionTemplateDecl::newCommon(ASTContext &C) {
|
|
|
|
Common *CommonPtr = new (C) Common;
|
|
|
|
C.AddDeallocation(DeallocateCommon, CommonPtr);
|
2010-07-30 00:11:51 +08:00
|
|
|
return CommonPtr;
|
|
|
|
}
|
|
|
|
|
2010-07-20 21:59:58 +08:00
|
|
|
FunctionDecl *
|
|
|
|
FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs, void *&InsertPos) {
|
2010-07-31 01:09:04 +08:00
|
|
|
return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
|
2010-07-20 21:59:58 +08:00
|
|
|
}
|
|
|
|
|
2011-04-14 22:07:59 +08:00
|
|
|
void FunctionTemplateDecl::addSpecialization(
|
|
|
|
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
|
2012-03-28 22:34:23 +08:00
|
|
|
if (InsertPos)
|
|
|
|
getSpecializations().InsertNode(Info, InsertPos);
|
|
|
|
else
|
|
|
|
getSpecializations().GetOrInsertNode(Info);
|
2011-04-14 22:07:59 +08:00
|
|
|
if (ASTMutationListener *L = getASTMutationListener())
|
|
|
|
L->AddedCXXTemplateSpecialization(this, Info->Function);
|
|
|
|
}
|
|
|
|
|
2011-03-06 01:54:25 +08:00
|
|
|
std::pair<const TemplateArgument *, unsigned>
|
|
|
|
FunctionTemplateDecl::getInjectedTemplateArgs() {
|
|
|
|
TemplateParameterList *Params = getTemplateParameters();
|
|
|
|
Common *CommonPtr = getCommonPtr();
|
|
|
|
if (!CommonPtr->InjectedArgs) {
|
|
|
|
CommonPtr->InjectedArgs
|
|
|
|
= new (getASTContext()) TemplateArgument [Params->size()];
|
|
|
|
GenerateInjectedTemplateArgs(getASTContext(), Params,
|
|
|
|
CommonPtr->InjectedArgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::make_pair(CommonPtr->InjectedArgs, Params->size());
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-05-24 02:26:36 +08:00
|
|
|
void ClassTemplateDecl::DeallocateCommon(void *Ptr) {
|
|
|
|
static_cast<Common *>(Ptr)->~Common();
|
|
|
|
}
|
|
|
|
|
2010-06-20 03:29:09 +08:00
|
|
|
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
DeclarationName Name,
|
|
|
|
TemplateParameterList *Params,
|
|
|
|
NamedDecl *Decl,
|
|
|
|
ClassTemplateDecl *PrevDecl) {
|
2011-03-05 02:32:38 +08:00
|
|
|
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
2010-06-20 03:29:09 +08:00
|
|
|
ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl);
|
2010-06-21 18:57:41 +08:00
|
|
|
New->setPreviousDeclaration(PrevDecl);
|
2010-06-20 03:29:09 +08:00
|
|
|
return New;
|
Introduce a new expression type, UnresolvedDeclRefExpr, that describes
dependent qualified-ids such as
Fibonacci<N - 1>::value
where N is a template parameter. These references are "unresolved"
because the name is dependent and, therefore, cannot be resolved to a
declaration node (as we would do for a DeclRefExpr or
QualifiedDeclRefExpr). UnresolvedDeclRefExprs instantiate to
DeclRefExprs, QualifiedDeclRefExprs, etc.
Also, be a bit more careful about keeping only a single set of
specializations for a class template, and instantiating from the
definition of that template rather than a previous declaration. In
general, we need a better solution for this for all TagDecls, because
it's too easy to accidentally look at a declaration that isn't the
definition.
We can now process a simple Fibonacci computation described as a
template metaprogram.
llvm-svn: 67308
2009-03-20 01:26:29 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ClassTemplateDecl));
|
|
|
|
return new (Mem) ClassTemplateDecl(EmptyShell());
|
2011-03-05 01:52:15 +08:00
|
|
|
}
|
|
|
|
|
2010-10-28 06:21:36 +08:00
|
|
|
void ClassTemplateDecl::LoadLazySpecializations() {
|
|
|
|
Common *CommonPtr = getCommonPtr();
|
|
|
|
if (CommonPtr->LazySpecializations) {
|
|
|
|
ASTContext &Context = getASTContext();
|
|
|
|
uint32_t *Specs = CommonPtr->LazySpecializations;
|
|
|
|
CommonPtr->LazySpecializations = 0;
|
|
|
|
for (uint32_t I = 0, N = *Specs++; I != N; ++I)
|
|
|
|
(void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-04 07:49:05 +08:00
|
|
|
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
|
2010-10-28 06:21:36 +08:00
|
|
|
ClassTemplateDecl::getSpecializations() {
|
|
|
|
LoadLazySpecializations();
|
|
|
|
return getCommonPtr()->Specializations;
|
|
|
|
}
|
|
|
|
|
2012-05-04 07:49:05 +08:00
|
|
|
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
|
2010-10-28 06:21:36 +08:00
|
|
|
ClassTemplateDecl::getPartialSpecializations() {
|
|
|
|
LoadLazySpecializations();
|
|
|
|
return getCommonPtr()->PartialSpecializations;
|
|
|
|
}
|
|
|
|
|
2010-09-09 03:31:22 +08:00
|
|
|
RedeclarableTemplateDecl::CommonBase *
|
|
|
|
ClassTemplateDecl::newCommon(ASTContext &C) {
|
|
|
|
Common *CommonPtr = new (C) Common;
|
|
|
|
C.AddDeallocation(DeallocateCommon, CommonPtr);
|
2010-07-30 00:11:51 +08:00
|
|
|
return CommonPtr;
|
|
|
|
}
|
|
|
|
|
2010-07-20 21:59:28 +08:00
|
|
|
ClassTemplateSpecializationDecl *
|
|
|
|
ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs, void *&InsertPos) {
|
2010-07-31 01:09:04 +08:00
|
|
|
return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
|
2010-07-20 21:59:28 +08:00
|
|
|
}
|
|
|
|
|
2010-10-28 15:38:42 +08:00
|
|
|
void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
|
|
|
|
void *InsertPos) {
|
2012-03-28 22:34:23 +08:00
|
|
|
if (InsertPos)
|
|
|
|
getSpecializations().InsertNode(D, InsertPos);
|
|
|
|
else {
|
|
|
|
ClassTemplateSpecializationDecl *Existing
|
|
|
|
= getSpecializations().GetOrInsertNode(D);
|
|
|
|
(void)Existing;
|
|
|
|
assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
|
|
|
|
}
|
2010-10-28 15:38:42 +08:00
|
|
|
if (ASTMutationListener *L = getASTMutationListener())
|
|
|
|
L->AddedCXXTemplateSpecialization(this, D);
|
|
|
|
}
|
|
|
|
|
2010-07-20 21:59:28 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
|
|
ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs,
|
|
|
|
void *&InsertPos) {
|
2010-07-31 01:09:04 +08:00
|
|
|
return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs,
|
|
|
|
InsertPos);
|
2010-07-20 21:59:28 +08:00
|
|
|
}
|
|
|
|
|
2010-10-28 15:38:42 +08:00
|
|
|
void ClassTemplateDecl::AddPartialSpecialization(
|
|
|
|
ClassTemplatePartialSpecializationDecl *D,
|
|
|
|
void *InsertPos) {
|
2012-03-28 22:34:23 +08:00
|
|
|
if (InsertPos)
|
|
|
|
getPartialSpecializations().InsertNode(D, InsertPos);
|
|
|
|
else {
|
|
|
|
ClassTemplatePartialSpecializationDecl *Existing
|
|
|
|
= getPartialSpecializations().GetOrInsertNode(D);
|
|
|
|
(void)Existing;
|
|
|
|
assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
|
|
|
|
}
|
|
|
|
|
2010-10-28 15:38:42 +08:00
|
|
|
if (ASTMutationListener *L = getASTMutationListener())
|
|
|
|
L->AddedCXXTemplateSpecialization(this, D);
|
|
|
|
}
|
|
|
|
|
2010-04-30 13:56:50 +08:00
|
|
|
void ClassTemplateDecl::getPartialSpecializations(
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) {
|
2012-05-04 07:49:05 +08:00
|
|
|
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &PartialSpecs
|
2010-06-21 18:57:41 +08:00
|
|
|
= getPartialSpecializations();
|
2010-04-30 13:56:50 +08:00
|
|
|
PS.clear();
|
|
|
|
PS.resize(PartialSpecs.size());
|
2012-05-04 07:49:05 +08:00
|
|
|
for (llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>::iterator
|
2010-04-30 13:56:50 +08:00
|
|
|
P = PartialSpecs.begin(), PEnd = PartialSpecs.end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
assert(!PS[P->getSequenceNumber()]);
|
2012-01-15 00:38:05 +08:00
|
|
|
PS[P->getSequenceNumber()] = P->getMostRecentDecl();
|
2010-04-30 13:56:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-31 01:40:51 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
|
|
ClassTemplateDecl::findPartialSpecialization(QualType T) {
|
|
|
|
ASTContext &Context = getASTContext();
|
2012-05-04 07:49:05 +08:00
|
|
|
using llvm::FoldingSetVector;
|
|
|
|
typedef FoldingSetVector<ClassTemplatePartialSpecializationDecl>::iterator
|
2009-07-31 01:40:51 +08:00
|
|
|
partial_spec_iterator;
|
|
|
|
for (partial_spec_iterator P = getPartialSpecializations().begin(),
|
|
|
|
PEnd = getPartialSpecializations().end();
|
|
|
|
P != PEnd; ++P) {
|
2010-04-27 08:57:59 +08:00
|
|
|
if (Context.hasSameType(P->getInjectedSpecializationType(), T))
|
2012-01-15 00:38:05 +08:00
|
|
|
return P->getMostRecentDecl();
|
2010-07-20 21:59:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
|
|
ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
|
|
|
|
ClassTemplatePartialSpecializationDecl *D) {
|
|
|
|
Decl *DCanon = D->getCanonicalDecl();
|
2012-05-04 07:49:05 +08:00
|
|
|
for (llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>::iterator
|
2010-07-20 21:59:28 +08:00
|
|
|
P = getPartialSpecializations().begin(),
|
|
|
|
PEnd = getPartialSpecializations().end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
|
2012-01-15 00:38:05 +08:00
|
|
|
return P->getMostRecentDecl();
|
2009-07-31 01:40:51 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-31 01:40:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-03-10 11:28:59 +08:00
|
|
|
QualType
|
2010-07-09 02:37:38 +08:00
|
|
|
ClassTemplateDecl::getInjectedClassNameSpecialization() {
|
2010-06-21 18:57:41 +08:00
|
|
|
Common *CommonPtr = getCommonPtr();
|
2009-05-11 06:57:19 +08:00
|
|
|
if (!CommonPtr->InjectedClassNameType.isNull())
|
|
|
|
return CommonPtr->InjectedClassNameType;
|
|
|
|
|
2010-12-24 00:00:30 +08:00
|
|
|
// C++0x [temp.dep.type]p2:
|
|
|
|
// The template argument list of a primary template is a template argument
|
|
|
|
// list in which the nth template argument has the value of the nth template
|
|
|
|
// parameter of the class template. If the nth template parameter is a
|
|
|
|
// template parameter pack (14.5.3), the nth template argument is a pack
|
|
|
|
// expansion (14.5.3) whose pattern is the name of the template parameter
|
|
|
|
// pack.
|
2010-07-09 02:37:38 +08:00
|
|
|
ASTContext &Context = getASTContext();
|
2009-05-11 06:57:19 +08:00
|
|
|
TemplateParameterList *Params = getTemplateParameters();
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 16> TemplateArgs;
|
2011-03-06 01:54:25 +08:00
|
|
|
TemplateArgs.resize(Params->size());
|
|
|
|
GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data());
|
2009-05-11 06:57:19 +08:00
|
|
|
CommonPtr->InjectedClassNameType
|
2009-07-29 07:00:59 +08:00
|
|
|
= Context.getTemplateSpecializationType(TemplateName(this),
|
2009-05-11 06:57:19 +08:00
|
|
|
&TemplateArgs[0],
|
2009-07-29 07:00:59 +08:00
|
|
|
TemplateArgs.size());
|
2009-05-11 06:57:19 +08:00
|
|
|
return CommonPtr->InjectedClassNameType;
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateTypeParm Allocation/Deallocation Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
2011-03-06 23:48:19 +08:00
|
|
|
SourceLocation KeyLoc, SourceLocation NameLoc,
|
|
|
|
unsigned D, unsigned P, IdentifierInfo *Id,
|
|
|
|
bool Typename, bool ParameterPack) {
|
Re-applies the patch first applied way back in r106099, with
accompanying fixes to make it work today.
The core of this patch is to provide a link from a TemplateTypeParmType
back to the TemplateTypeParmDecl node which declared it. This in turn
provides much more precise information about the type, where it came
from, and how it functions for AST consumers.
To make the patch work almost a year after its first attempt, it needed
serialization support, and it now retains the old getName() interface.
Finally, it requires us to not attempt to instantiate the type in an
unsupported friend decl -- specifically those coming from template
friend decls but which refer to a specific type through a dependent
name.
A cleaner representation of the last item would be to build
FriendTemplateDecl nodes for these, storing their template parameters
etc, and to perform proper instantation of them like any other template
declaration. They can still be flagged as unsupported for the purpose of
access checking, etc.
This passed an asserts-enabled bootstrap for me, and the reduced test
case mentioned in the original review thread no longer causes issues,
likely fixed at somewhere amidst the 24k revisions that have elapsed.
llvm-svn: 130628
2011-05-01 08:51:33 +08:00
|
|
|
TemplateTypeParmDecl *TTPDecl =
|
|
|
|
new (C) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename);
|
|
|
|
QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl);
|
|
|
|
TTPDecl->TypeForDecl = TTPType.getTypePtr();
|
|
|
|
return TTPDecl;
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-02 19:54:55 +08:00
|
|
|
TemplateTypeParmDecl *
|
2012-01-06 05:55:30 +08:00
|
|
|
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTypeParmDecl));
|
|
|
|
return new (Mem) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(),
|
|
|
|
0, false);
|
2010-07-02 19:54:55 +08:00
|
|
|
}
|
|
|
|
|
2009-10-29 16:12:44 +08:00
|
|
|
SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
|
2011-03-04 20:42:03 +08:00
|
|
|
return hasDefaultArgument()
|
|
|
|
? DefaultArgument->getTypeLoc().getBeginLoc()
|
|
|
|
: SourceLocation();
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceRange TemplateTypeParmDecl::getSourceRange() const {
|
|
|
|
if (hasDefaultArgument() && !defaultArgumentWasInherited())
|
2011-03-06 23:48:19 +08:00
|
|
|
return SourceRange(getLocStart(),
|
2011-03-04 20:42:03 +08:00
|
|
|
DefaultArgument->getTypeLoc().getEndLoc());
|
|
|
|
else
|
2011-03-06 23:48:19 +08:00
|
|
|
return TypeDecl::getSourceRange();
|
2009-10-29 16:12:44 +08:00
|
|
|
}
|
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
unsigned TemplateTypeParmDecl::getDepth() const {
|
|
|
|
return TypeForDecl->getAs<TemplateTypeParmType>()->getDepth();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned TemplateTypeParmDecl::getIndex() const {
|
|
|
|
return TypeForDecl->getAs<TemplateTypeParmType>()->getIndex();
|
|
|
|
}
|
|
|
|
|
Re-applies the patch first applied way back in r106099, with
accompanying fixes to make it work today.
The core of this patch is to provide a link from a TemplateTypeParmType
back to the TemplateTypeParmDecl node which declared it. This in turn
provides much more precise information about the type, where it came
from, and how it functions for AST consumers.
To make the patch work almost a year after its first attempt, it needed
serialization support, and it now retains the old getName() interface.
Finally, it requires us to not attempt to instantiate the type in an
unsupported friend decl -- specifically those coming from template
friend decls but which refer to a specific type through a dependent
name.
A cleaner representation of the last item would be to build
FriendTemplateDecl nodes for these, storing their template parameters
etc, and to perform proper instantation of them like any other template
declaration. They can still be flagged as unsupported for the purpose of
access checking, etc.
This passed an asserts-enabled bootstrap for me, and the reduced test
case mentioned in the original review thread no longer causes issues,
likely fixed at somewhere amidst the 24k revisions that have elapsed.
llvm-svn: 130628
2011-05-01 08:51:33 +08:00
|
|
|
bool TemplateTypeParmDecl::isParameterPack() const {
|
|
|
|
return TypeForDecl->getAs<TemplateTypeParmType>()->isParameterPack();
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// NonTypeTemplateParmDecl Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc,
|
|
|
|
unsigned D, unsigned P,
|
|
|
|
IdentifierInfo *Id,
|
2011-01-20 04:10:05 +08:00
|
|
|
QualType T,
|
|
|
|
TypeSourceInfo *TInfo,
|
|
|
|
const QualType *ExpandedTypes,
|
|
|
|
unsigned NumExpandedTypes,
|
|
|
|
TypeSourceInfo **ExpandedTInfos)
|
2011-03-08 16:55:46 +08:00
|
|
|
: DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
|
2011-01-20 04:10:05 +08:00
|
|
|
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
|
|
|
|
ParameterPack(true), ExpandedParameterPack(true),
|
|
|
|
NumExpandedTypes(NumExpandedTypes)
|
|
|
|
{
|
|
|
|
if (ExpandedTypes && ExpandedTInfos) {
|
|
|
|
void **TypesAndInfos = reinterpret_cast<void **>(this + 1);
|
|
|
|
for (unsigned I = 0; I != NumExpandedTypes; ++I) {
|
|
|
|
TypesAndInfos[2*I] = ExpandedTypes[I].getAsOpaquePtr();
|
|
|
|
TypesAndInfos[2*I + 1] = ExpandedTInfos[I];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
NonTypeTemplateParmDecl *
|
2011-01-12 17:06:06 +08:00
|
|
|
NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
|
|
|
unsigned D, unsigned P, IdentifierInfo *Id,
|
|
|
|
QualType T, bool ParameterPack,
|
|
|
|
TypeSourceInfo *TInfo) {
|
|
|
|
return new (C) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id,
|
|
|
|
T, ParameterPack, TInfo);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
NonTypeTemplateParmDecl *
|
|
|
|
NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
|
|
|
unsigned D, unsigned P,
|
2011-01-20 04:10:05 +08:00
|
|
|
IdentifierInfo *Id, QualType T,
|
|
|
|
TypeSourceInfo *TInfo,
|
|
|
|
const QualType *ExpandedTypes,
|
|
|
|
unsigned NumExpandedTypes,
|
|
|
|
TypeSourceInfo **ExpandedTInfos) {
|
|
|
|
unsigned Size = sizeof(NonTypeTemplateParmDecl)
|
|
|
|
+ NumExpandedTypes * 2 * sizeof(void*);
|
|
|
|
void *Mem = C.Allocate(Size);
|
2011-03-08 16:55:46 +08:00
|
|
|
return new (Mem) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc,
|
|
|
|
D, P, Id, T, TInfo,
|
2011-01-20 04:10:05 +08:00
|
|
|
ExpandedTypes, NumExpandedTypes,
|
|
|
|
ExpandedTInfos);
|
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
NonTypeTemplateParmDecl *
|
|
|
|
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NonTypeTemplateParmDecl));
|
|
|
|
return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(),
|
|
|
|
SourceLocation(), 0, 0, 0,
|
|
|
|
QualType(), false, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
NonTypeTemplateParmDecl *
|
|
|
|
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
|
|
|
|
unsigned NumExpandedTypes) {
|
|
|
|
unsigned Size = sizeof(NonTypeTemplateParmDecl)
|
|
|
|
+ NumExpandedTypes * 2 * sizeof(void*);
|
|
|
|
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID, Size);
|
|
|
|
return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(),
|
|
|
|
SourceLocation(), 0, 0, 0,
|
|
|
|
QualType(), 0, 0, NumExpandedTypes,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
2011-02-09 09:13:10 +08:00
|
|
|
SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
|
2011-03-04 19:03:48 +08:00
|
|
|
if (hasDefaultArgument() && !defaultArgumentWasInherited())
|
2011-03-09 00:41:52 +08:00
|
|
|
return SourceRange(getOuterLocStart(),
|
|
|
|
getDefaultArgument()->getSourceRange().getEnd());
|
|
|
|
return DeclaratorDecl::getSourceRange();
|
2011-02-09 09:13:10 +08:00
|
|
|
}
|
|
|
|
|
2009-02-11 03:49:53 +08:00
|
|
|
SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
|
2010-06-09 17:26:05 +08:00
|
|
|
return hasDefaultArgument()
|
|
|
|
? getDefaultArgument()->getSourceRange().getBegin()
|
|
|
|
: SourceLocation();
|
2009-02-11 03:49:53 +08:00
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateTemplateParmDecl Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void TemplateTemplateParmDecl::anchor() { }
|
|
|
|
|
2012-09-07 10:06:42 +08:00
|
|
|
TemplateTemplateParmDecl::TemplateTemplateParmDecl(
|
|
|
|
DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
|
|
|
|
IdentifierInfo *Id, TemplateParameterList *Params,
|
|
|
|
unsigned NumExpansions, TemplateParameterList * const *Expansions)
|
|
|
|
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
|
|
|
|
TemplateParmPosition(D, P), DefaultArgument(),
|
|
|
|
DefaultArgumentWasInherited(false), ParameterPack(true),
|
|
|
|
ExpandedParameterPack(true), NumExpandedParams(NumExpansions) {
|
|
|
|
if (Expansions)
|
|
|
|
std::memcpy(reinterpret_cast<void*>(this + 1), Expansions,
|
|
|
|
sizeof(TemplateParameterList*) * NumExpandedParams);
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
TemplateTemplateParmDecl *
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
2009-02-05 03:02:06 +08:00
|
|
|
SourceLocation L, unsigned D, unsigned P,
|
2011-01-05 23:48:55 +08:00
|
|
|
bool ParameterPack, IdentifierInfo *Id,
|
2009-02-05 03:02:06 +08:00
|
|
|
TemplateParameterList *Params) {
|
2011-01-05 23:48:55 +08:00
|
|
|
return new (C) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
|
|
|
|
Params);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2012-09-07 10:06:42 +08:00
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L, unsigned D, unsigned P,
|
|
|
|
IdentifierInfo *Id,
|
|
|
|
TemplateParameterList *Params,
|
|
|
|
llvm::ArrayRef<TemplateParameterList*> Expansions) {
|
|
|
|
void *Mem = C.Allocate(sizeof(TemplateTemplateParmDecl) +
|
|
|
|
sizeof(TemplateParameterList*) * Expansions.size());
|
|
|
|
return new (Mem) TemplateTemplateParmDecl(DC, L, D, P, Id, Params,
|
|
|
|
Expansions.size(),
|
|
|
|
Expansions.data());
|
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTemplateParmDecl));
|
|
|
|
return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, false,
|
|
|
|
0, 0);
|
|
|
|
}
|
|
|
|
|
2012-09-07 10:06:42 +08:00
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
|
|
|
|
unsigned NumExpansions) {
|
|
|
|
unsigned Size = sizeof(TemplateTemplateParmDecl) +
|
|
|
|
sizeof(TemplateParameterList*) * NumExpansions;
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID, Size);
|
|
|
|
return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, 0, 0,
|
|
|
|
NumExpansions, 0);
|
|
|
|
}
|
|
|
|
|
2009-05-12 07:53:27 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateArgumentList Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2010-11-08 07:05:16 +08:00
|
|
|
TemplateArgumentList *
|
|
|
|
TemplateArgumentList::CreateCopy(ASTContext &Context,
|
|
|
|
const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs) {
|
|
|
|
std::size_t Size = sizeof(TemplateArgumentList)
|
|
|
|
+ NumArgs * sizeof(TemplateArgument);
|
|
|
|
void *Mem = Context.Allocate(Size);
|
|
|
|
TemplateArgument *StoredArgs
|
|
|
|
= reinterpret_cast<TemplateArgument *>(
|
|
|
|
static_cast<TemplateArgumentList *>(Mem) + 1);
|
|
|
|
std::uninitialized_copy(Args, Args + NumArgs, StoredArgs);
|
|
|
|
return new (Mem) TemplateArgumentList(StoredArgs, NumArgs, true);
|
2010-06-23 21:48:23 +08:00
|
|
|
}
|
|
|
|
|
2011-09-23 04:07:09 +08:00
|
|
|
FunctionTemplateSpecializationInfo *
|
|
|
|
FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD,
|
|
|
|
FunctionTemplateDecl *Template,
|
|
|
|
TemplateSpecializationKind TSK,
|
|
|
|
const TemplateArgumentList *TemplateArgs,
|
|
|
|
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
|
|
|
SourceLocation POI) {
|
|
|
|
const ASTTemplateArgumentListInfo *ArgsAsWritten = 0;
|
|
|
|
if (TemplateArgsAsWritten)
|
|
|
|
ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
|
|
|
|
*TemplateArgsAsWritten);
|
|
|
|
|
|
|
|
return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK,
|
|
|
|
TemplateArgs,
|
|
|
|
ArgsAsWritten,
|
|
|
|
POI);
|
|
|
|
}
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void TemplateDecl::anchor() { }
|
|
|
|
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassTemplateSpecializationDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
ClassTemplateSpecializationDecl::
|
2010-05-06 08:28:52 +08:00
|
|
|
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
|
2011-03-09 22:09:51 +08:00
|
|
|
DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc,
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
2010-11-08 07:05:16 +08:00
|
|
|
const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs,
|
2009-07-30 07:36:44 +08:00
|
|
|
ClassTemplateSpecializationDecl *PrevDecl)
|
2011-03-09 22:09:51 +08:00
|
|
|
: CXXRecordDecl(DK, TK, DC, StartLoc, IdLoc,
|
2009-07-30 07:36:44 +08:00
|
|
|
SpecializedTemplate->getIdentifier(),
|
|
|
|
PrevDecl),
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
SpecializedTemplate(SpecializedTemplate),
|
2010-06-12 15:44:57 +08:00
|
|
|
ExplicitInfo(0),
|
2010-11-08 07:05:16 +08:00
|
|
|
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)),
|
2009-05-12 07:53:27 +08:00
|
|
|
SpecializationKind(TSK_Undeclared) {
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-06-23 21:48:23 +08:00
|
|
|
ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(Kind DK)
|
2011-03-09 22:09:51 +08:00
|
|
|
: CXXRecordDecl(DK, TTK_Struct, 0, SourceLocation(), SourceLocation(), 0, 0),
|
2010-06-23 21:48:23 +08:00
|
|
|
ExplicitInfo(0),
|
|
|
|
SpecializationKind(TSK_Undeclared) {
|
|
|
|
}
|
|
|
|
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
ClassTemplateSpecializationDecl *
|
2010-05-06 08:28:52 +08:00
|
|
|
ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
|
2011-03-09 22:09:51 +08:00
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc,
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
2010-11-08 07:05:16 +08:00
|
|
|
const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs,
|
2009-02-18 07:15:12 +08:00
|
|
|
ClassTemplateSpecializationDecl *PrevDecl) {
|
|
|
|
ClassTemplateSpecializationDecl *Result
|
2009-09-09 23:08:12 +08:00
|
|
|
= new (Context)ClassTemplateSpecializationDecl(Context,
|
2009-05-31 17:31:02 +08:00
|
|
|
ClassTemplateSpecialization,
|
2011-03-09 22:09:51 +08:00
|
|
|
TK, DC, StartLoc, IdLoc,
|
2009-05-12 07:53:27 +08:00
|
|
|
SpecializedTemplate,
|
2010-11-08 07:05:16 +08:00
|
|
|
Args, NumArgs,
|
2009-07-30 07:36:44 +08:00
|
|
|
PrevDecl);
|
2009-02-18 07:15:12 +08:00
|
|
|
Context.getTypeDeclType(Result, PrevDecl);
|
|
|
|
return Result;
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
}
|
2009-05-31 17:31:02 +08:00
|
|
|
|
2010-06-23 21:48:23 +08:00
|
|
|
ClassTemplateSpecializationDecl *
|
2012-01-06 05:55:30 +08:00
|
|
|
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID,
|
|
|
|
sizeof(ClassTemplateSpecializationDecl));
|
|
|
|
return new (Mem) ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
|
2010-06-23 21:48:23 +08:00
|
|
|
}
|
|
|
|
|
2011-02-20 02:51:44 +08:00
|
|
|
void
|
|
|
|
ClassTemplateSpecializationDecl::getNameForDiagnostic(std::string &S,
|
|
|
|
const PrintingPolicy &Policy,
|
|
|
|
bool Qualified) const {
|
|
|
|
NamedDecl::getNameForDiagnostic(S, Policy, Qualified);
|
|
|
|
|
|
|
|
const TemplateArgumentList &TemplateArgs = getTemplateArgs();
|
|
|
|
S += TemplateSpecializationType::PrintTemplateArgumentList(
|
|
|
|
TemplateArgs.data(),
|
|
|
|
TemplateArgs.size(),
|
|
|
|
Policy);
|
|
|
|
}
|
|
|
|
|
2009-08-03 07:24:31 +08:00
|
|
|
ClassTemplateDecl *
|
2009-09-09 23:08:12 +08:00
|
|
|
ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
|
|
|
|
if (SpecializedPartialSpecialization *PartialSpec
|
2009-08-03 07:24:31 +08:00
|
|
|
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
|
|
|
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
|
|
|
|
return SpecializedTemplate.get<ClassTemplateDecl*>();
|
|
|
|
}
|
|
|
|
|
2011-03-04 22:20:30 +08:00
|
|
|
SourceRange
|
|
|
|
ClassTemplateSpecializationDecl::getSourceRange() const {
|
2011-10-04 04:34:03 +08:00
|
|
|
if (ExplicitInfo) {
|
2012-10-16 05:06:42 +08:00
|
|
|
SourceLocation Begin = getTemplateKeywordLoc();
|
|
|
|
if (Begin.isValid()) {
|
|
|
|
// Here we have an explicit (partial) specialization or instantiation.
|
|
|
|
assert(getSpecializationKind() == TSK_ExplicitSpecialization ||
|
|
|
|
getSpecializationKind() == TSK_ExplicitInstantiationDeclaration ||
|
|
|
|
getSpecializationKind() == TSK_ExplicitInstantiationDefinition);
|
|
|
|
if (getExternLoc().isValid())
|
|
|
|
Begin = getExternLoc();
|
|
|
|
SourceLocation End = getRBraceLoc();
|
|
|
|
if (End.isInvalid())
|
|
|
|
End = getTypeAsWritten()->getTypeLoc().getEndLoc();
|
|
|
|
return SourceRange(Begin, End);
|
|
|
|
}
|
|
|
|
// An implicit instantiation of a class template partial specialization
|
|
|
|
// uses ExplicitInfo to record the TypeAsWritten, but the source
|
|
|
|
// locations should be retrieved from the instantiation pattern.
|
|
|
|
typedef ClassTemplatePartialSpecializationDecl CTPSDecl;
|
|
|
|
CTPSDecl *ctpsd = const_cast<CTPSDecl*>(cast<CTPSDecl>(this));
|
|
|
|
CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
|
|
|
|
assert(inst_from != 0);
|
|
|
|
return inst_from->getSourceRange();
|
2011-10-04 04:34:03 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// No explicit info available.
|
|
|
|
llvm::PointerUnion<ClassTemplateDecl *,
|
|
|
|
ClassTemplatePartialSpecializationDecl *>
|
|
|
|
inst_from = getInstantiatedFrom();
|
|
|
|
if (inst_from.isNull())
|
|
|
|
return getSpecializedTemplate()->getSourceRange();
|
|
|
|
if (ClassTemplateDecl *ctd = inst_from.dyn_cast<ClassTemplateDecl*>())
|
|
|
|
return ctd->getSourceRange();
|
|
|
|
return inst_from.get<ClassTemplatePartialSpecializationDecl*>()
|
|
|
|
->getSourceRange();
|
|
|
|
}
|
2011-03-04 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2009-05-31 17:31:02 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassTemplatePartialSpecializationDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2011-12-20 10:48:34 +08:00
|
|
|
void ClassTemplatePartialSpecializationDecl::anchor() { }
|
|
|
|
|
2011-03-05 01:52:15 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl::
|
|
|
|
ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
|
2011-03-09 22:09:51 +08:00
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc,
|
2011-03-05 01:52:15 +08:00
|
|
|
TemplateParameterList *Params,
|
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
|
|
|
const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs,
|
|
|
|
TemplateArgumentLoc *ArgInfos,
|
|
|
|
unsigned NumArgInfos,
|
|
|
|
ClassTemplatePartialSpecializationDecl *PrevDecl,
|
|
|
|
unsigned SequenceNumber)
|
|
|
|
: ClassTemplateSpecializationDecl(Context,
|
|
|
|
ClassTemplatePartialSpecialization,
|
2011-03-09 22:09:51 +08:00
|
|
|
TK, DC, StartLoc, IdLoc,
|
|
|
|
SpecializedTemplate,
|
2011-03-05 01:52:15 +08:00
|
|
|
Args, NumArgs, PrevDecl),
|
|
|
|
TemplateParams(Params), ArgsAsWritten(ArgInfos),
|
|
|
|
NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber),
|
|
|
|
InstantiatedFromMember(0, false)
|
|
|
|
{
|
2011-03-05 02:32:38 +08:00
|
|
|
AdoptTemplateParameterList(Params, this);
|
2011-03-05 01:52:15 +08:00
|
|
|
}
|
|
|
|
|
2009-05-31 17:31:02 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
|
|
ClassTemplatePartialSpecializationDecl::
|
2011-03-09 22:09:51 +08:00
|
|
|
Create(ASTContext &Context, TagKind TK,DeclContext *DC,
|
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
2009-05-31 17:31:02 +08:00
|
|
|
TemplateParameterList *Params,
|
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
2010-11-08 07:05:16 +08:00
|
|
|
const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs,
|
2009-11-23 09:53:49 +08:00
|
|
|
const TemplateArgumentListInfo &ArgInfos,
|
2010-03-10 11:28:59 +08:00
|
|
|
QualType CanonInjectedType,
|
2010-04-30 13:56:50 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *PrevDecl,
|
|
|
|
unsigned SequenceNumber) {
|
2009-11-23 09:53:49 +08:00
|
|
|
unsigned N = ArgInfos.size();
|
2009-10-29 16:12:44 +08:00
|
|
|
TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N];
|
|
|
|
for (unsigned I = 0; I != N; ++I)
|
|
|
|
ClonedArgs[I] = ArgInfos[I];
|
|
|
|
|
2009-05-31 17:31:02 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *Result
|
2011-03-09 22:09:51 +08:00
|
|
|
= new (Context)ClassTemplatePartialSpecializationDecl(Context, TK, DC,
|
|
|
|
StartLoc, IdLoc,
|
|
|
|
Params,
|
2009-05-31 17:31:02 +08:00
|
|
|
SpecializedTemplate,
|
2010-11-08 07:05:16 +08:00
|
|
|
Args, NumArgs,
|
2009-10-29 16:12:44 +08:00
|
|
|
ClonedArgs, N,
|
2010-04-30 13:56:50 +08:00
|
|
|
PrevDecl,
|
|
|
|
SequenceNumber);
|
2009-05-31 17:31:02 +08:00
|
|
|
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
2010-03-10 11:28:59 +08:00
|
|
|
|
|
|
|
Context.getInjectedClassNameType(Result, CanonInjectedType);
|
2009-05-31 17:31:02 +08:00
|
|
|
return Result;
|
|
|
|
}
|
2009-09-17 06:47:08 +08:00
|
|
|
|
2010-06-23 21:48:23 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *
|
2012-01-06 05:55:30 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID,
|
|
|
|
sizeof(ClassTemplatePartialSpecializationDecl));
|
|
|
|
return new (Mem) ClassTemplatePartialSpecializationDecl();
|
2010-06-23 21:48:23 +08:00
|
|
|
}
|
|
|
|
|
2009-09-17 06:47:08 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// FriendTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void FriendTemplateDecl::anchor() { }
|
|
|
|
|
2009-09-17 06:47:08 +08:00
|
|
|
FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
unsigned NParams,
|
|
|
|
TemplateParameterList **Params,
|
|
|
|
FriendUnion Friend,
|
|
|
|
SourceLocation FLoc) {
|
|
|
|
FriendTemplateDecl *Result
|
|
|
|
= new (Context) FriendTemplateDecl(DC, L, NParams, Params, Friend, FLoc);
|
|
|
|
return Result;
|
|
|
|
}
|
2010-07-23 00:04:10 +08:00
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FriendTemplateDecl));
|
|
|
|
return new (Mem) FriendTemplateDecl(EmptyShell());
|
2010-07-23 00:04:10 +08:00
|
|
|
}
|
2011-05-06 05:57:07 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TypeAliasTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
DeclarationName Name,
|
|
|
|
TemplateParameterList *Params,
|
|
|
|
NamedDecl *Decl) {
|
|
|
|
AdoptTemplateParameterList(Params, DC);
|
|
|
|
return new (C) TypeAliasTemplateDecl(DC, L, Name, Params, Decl);
|
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasTemplateDecl));
|
|
|
|
return new (Mem) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(),
|
|
|
|
0, 0);
|
2011-05-06 05:57:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) {
|
|
|
|
static_cast<Common *>(Ptr)->~Common();
|
|
|
|
}
|
|
|
|
RedeclarableTemplateDecl::CommonBase *
|
|
|
|
TypeAliasTemplateDecl::newCommon(ASTContext &C) {
|
|
|
|
Common *CommonPtr = new (C) Common;
|
|
|
|
C.AddDeallocation(DeallocateCommon, CommonPtr);
|
|
|
|
return CommonPtr;
|
|
|
|
}
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassScopeFunctionSpecializationDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void ClassScopeFunctionSpecializationDecl::anchor() { }
|
2012-01-06 05:55:30 +08:00
|
|
|
|
|
|
|
ClassScopeFunctionSpecializationDecl *
|
|
|
|
ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
|
|
|
void *Mem = AllocateDeserializedDecl(C, ID,
|
|
|
|
sizeof(ClassScopeFunctionSpecializationDecl));
|
2012-06-26 01:21:05 +08:00
|
|
|
return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0,
|
|
|
|
false, TemplateArgumentListInfo());
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|