1198893Srdivacky//===--- DeclTemplate.cpp - Template Declaration AST Node Implementation --===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed// This file implements the C++ related Decl classes for templates.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14252723Sdim#include "clang/AST/DeclTemplate.h"
15252723Sdim#include "clang/AST/ASTContext.h"
16252723Sdim#include "clang/AST/ASTMutationListener.h"
17193326Sed#include "clang/AST/DeclCXX.h"
18193326Sed#include "clang/AST/Expr.h"
19218893Sdim#include "clang/AST/ExprCXX.h"
20198893Srdivacky#include "clang/AST/TypeLoc.h"
21193326Sed#include "clang/Basic/IdentifierTable.h"
22193326Sed#include "llvm/ADT/STLExtras.h"
23218893Sdim#include <memory>
24193326Sedusing namespace clang;
25193326Sed
26193326Sed//===----------------------------------------------------------------------===//
27193326Sed// TemplateParameterList Implementation
28193326Sed//===----------------------------------------------------------------------===//
29193326Sed
30193326SedTemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
31193326Sed                                             SourceLocation LAngleLoc,
32198092Srdivacky                                             NamedDecl **Params, unsigned NumParams,
33193326Sed                                             SourceLocation RAngleLoc)
34193326Sed  : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
35245431Sdim    NumParams(NumParams), ContainsUnexpandedParameterPack(false) {
36245431Sdim  assert(this->NumParams == NumParams && "Too many template parameters");
37245431Sdim  for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
38245431Sdim    NamedDecl *P = Params[Idx];
39245431Sdim    begin()[Idx] = P;
40245431Sdim
41245431Sdim    if (!P->isTemplateParameterPack()) {
42245431Sdim      if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
43245431Sdim        if (NTTP->getType()->containsUnexpandedParameterPack())
44245431Sdim          ContainsUnexpandedParameterPack = true;
45245431Sdim
46245431Sdim      if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
47245431Sdim        if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
48245431Sdim          ContainsUnexpandedParameterPack = true;
49245431Sdim
50245431Sdim      // FIXME: If a default argument contains an unexpanded parameter pack, the
51245431Sdim      // template parameter list does too.
52245431Sdim    }
53245431Sdim  }
54193326Sed}
55193326Sed
56193326SedTemplateParameterList *
57218893SdimTemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
58198092Srdivacky                              SourceLocation LAngleLoc, NamedDecl **Params,
59193326Sed                              unsigned NumParams, SourceLocation RAngleLoc) {
60198092Srdivacky  unsigned Size = sizeof(TemplateParameterList)
61198092Srdivacky                + sizeof(NamedDecl *) * NumParams;
62245431Sdim  unsigned Align = std::max(llvm::alignOf<TemplateParameterList>(),
63245431Sdim                            llvm::alignOf<NamedDecl*>());
64193326Sed  void *Mem = C.Allocate(Size, Align);
65198092Srdivacky  return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
66193326Sed                                         NumParams, RAngleLoc);
67193326Sed}
68193326Sed
69193326Sedunsigned TemplateParameterList::getMinRequiredArguments() const {
70218893Sdim  unsigned NumRequiredArgs = 0;
71218893Sdim  for (iterator P = const_cast<TemplateParameterList *>(this)->begin(),
72218893Sdim             PEnd = const_cast<TemplateParameterList *>(this)->end();
73218893Sdim       P != PEnd; ++P) {
74218893Sdim    if ((*P)->isTemplateParameterPack()) {
75218893Sdim      if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P))
76218893Sdim        if (NTTP->isExpandedParameterPack()) {
77218893Sdim          NumRequiredArgs += NTTP->getNumExpansionTypes();
78218893Sdim          continue;
79218893Sdim        }
80218893Sdim
81193326Sed      break;
82218893Sdim    }
83218893Sdim
84218893Sdim    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
85218893Sdim      if (TTP->hasDefaultArgument())
86218893Sdim        break;
87218893Sdim    } else if (NonTypeTemplateParmDecl *NTTP
88218893Sdim                                    = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
89218893Sdim      if (NTTP->hasDefaultArgument())
90218893Sdim        break;
91218893Sdim    } else if (cast<TemplateTemplateParmDecl>(*P)->hasDefaultArgument())
92218893Sdim      break;
93218893Sdim
94218893Sdim    ++NumRequiredArgs;
95193326Sed  }
96218893Sdim
97193326Sed  return NumRequiredArgs;
98193326Sed}
99193326Sed
100198893Srdivackyunsigned TemplateParameterList::getDepth() const {
101198893Srdivacky  if (size() == 0)
102198893Srdivacky    return 0;
103198893Srdivacky
104198893Srdivacky  const NamedDecl *FirstParm = getParam(0);
105198893Srdivacky  if (const TemplateTypeParmDecl *TTP
106198893Srdivacky        = dyn_cast<TemplateTypeParmDecl>(FirstParm))
107198893Srdivacky    return TTP->getDepth();
108198893Srdivacky  else if (const NonTypeTemplateParmDecl *NTTP
109198893Srdivacky             = dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
110198893Srdivacky    return NTTP->getDepth();
111198893Srdivacky  else
112198893Srdivacky    return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
113198893Srdivacky}
114198893Srdivacky
115221345Sdimstatic void AdoptTemplateParameterList(TemplateParameterList *Params,
116221345Sdim                                       DeclContext *Owner) {
117221345Sdim  for (TemplateParameterList::iterator P = Params->begin(),
118221345Sdim                                    PEnd = Params->end();
119221345Sdim       P != PEnd; ++P) {
120221345Sdim    (*P)->setDeclContext(Owner);
121221345Sdim
122221345Sdim    if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(*P))
123221345Sdim      AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner);
124221345Sdim  }
125221345Sdim}
126221345Sdim
127193326Sed//===----------------------------------------------------------------------===//
128212904Sdim// RedeclarableTemplateDecl Implementation
129193326Sed//===----------------------------------------------------------------------===//
130193326Sed
131252723SdimRedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
132263509Sdim  if (Common)
133263509Sdim    return Common;
134263509Sdim
135263509Sdim  // Walk the previous-declaration chain until we either find a declaration
136263509Sdim  // with a common pointer or we run out of previous declarations.
137263509Sdim  SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls;
138263509Sdim  for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
139263509Sdim       Prev = Prev->getPreviousDecl()) {
140263509Sdim    if (Prev->Common) {
141263509Sdim      Common = Prev->Common;
142263509Sdim      break;
143235633Sdim    }
144212904Sdim
145263509Sdim    PrevDecls.push_back(Prev);
146212904Sdim  }
147193326Sed
148263509Sdim  // If we never found a common pointer, allocate one now.
149263509Sdim  if (!Common) {
150263509Sdim    // FIXME: If any of the declarations is from an AST file, we probably
151263509Sdim    // need an update record to add the common data.
152263509Sdim
153263509Sdim    Common = newCommon(getASTContext());
154263509Sdim  }
155263509Sdim
156263509Sdim  // Update any previous declarations we saw with the common pointer.
157263509Sdim  for (unsigned I = 0, N = PrevDecls.size(); I != N; ++I)
158263509Sdim    PrevDecls[I]->Common = Common;
159263509Sdim
160235633Sdim  return Common;
161212904Sdim}
162212904Sdim
163212904Sdimtemplate <class EntryType>
164212904Sdimtypename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType*
165212904SdimRedeclarableTemplateDecl::findSpecializationImpl(
166245431Sdim                                 llvm::FoldingSetVector<EntryType> &Specs,
167212904Sdim                                 const TemplateArgument *Args, unsigned NumArgs,
168212904Sdim                                 void *&InsertPos) {
169212904Sdim  typedef SpecEntryTraits<EntryType> SETraits;
170212904Sdim  llvm::FoldingSetNodeID ID;
171212904Sdim  EntryType::Profile(ID,Args,NumArgs, getASTContext());
172212904Sdim  EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
173235633Sdim  return Entry ? SETraits::getMostRecentDecl(Entry) : 0;
174212904Sdim}
175212904Sdim
176221345Sdim/// \brief Generate the injected template arguments for the given template
177221345Sdim/// parameter list, e.g., for the injected-class-name of a class template.
178221345Sdimstatic void GenerateInjectedTemplateArgs(ASTContext &Context,
179221345Sdim                                        TemplateParameterList *Params,
180221345Sdim                                         TemplateArgument *Args) {
181221345Sdim  for (TemplateParameterList::iterator Param = Params->begin(),
182221345Sdim                                    ParamEnd = Params->end();
183221345Sdim       Param != ParamEnd; ++Param) {
184221345Sdim    TemplateArgument Arg;
185221345Sdim    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
186221345Sdim      QualType ArgType = Context.getTypeDeclType(TTP);
187221345Sdim      if (TTP->isParameterPack())
188252723Sdim        ArgType = Context.getPackExpansionType(ArgType, None);
189252723Sdim
190221345Sdim      Arg = TemplateArgument(ArgType);
191221345Sdim    } else if (NonTypeTemplateParmDecl *NTTP =
192221345Sdim               dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
193235633Sdim      Expr *E = new (Context) DeclRefExpr(NTTP, /*enclosing*/ false,
194221345Sdim                                  NTTP->getType().getNonLValueExprType(Context),
195221345Sdim                                  Expr::getValueKindForType(NTTP->getType()),
196221345Sdim                                          NTTP->getLocation());
197221345Sdim
198221345Sdim      if (NTTP->isParameterPack())
199221345Sdim        E = new (Context) PackExpansionExpr(Context.DependentTy, E,
200252723Sdim                                            NTTP->getLocation(), None);
201221345Sdim      Arg = TemplateArgument(E);
202221345Sdim    } else {
203221345Sdim      TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
204221345Sdim      if (TTP->isParameterPack())
205252723Sdim        Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>());
206221345Sdim      else
207221345Sdim        Arg = TemplateArgument(TemplateName(TTP));
208221345Sdim    }
209221345Sdim
210221345Sdim    if ((*Param)->isTemplateParameterPack())
211221345Sdim      Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1);
212221345Sdim
213221345Sdim    *Args++ = Arg;
214221345Sdim  }
215221345Sdim}
216221345Sdim
217193326Sed//===----------------------------------------------------------------------===//
218193326Sed// FunctionTemplateDecl Implementation
219193326Sed//===----------------------------------------------------------------------===//
220193326Sed
221208600Srdivackyvoid FunctionTemplateDecl::DeallocateCommon(void *Ptr) {
222208600Srdivacky  static_cast<Common *>(Ptr)->~Common();
223208600Srdivacky}
224208600Srdivacky
225193326SedFunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
226193326Sed                                                   DeclContext *DC,
227193326Sed                                                   SourceLocation L,
228193326Sed                                                   DeclarationName Name,
229195341Sed                                               TemplateParameterList *Params,
230193326Sed                                                   NamedDecl *Decl) {
231221345Sdim  AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
232193326Sed  return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
233193326Sed}
234193326Sed
235235633SdimFunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
236235633Sdim                                                               unsigned ID) {
237235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionTemplateDecl));
238235633Sdim  return new (Mem) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(),
239235633Sdim                                        0, 0);
240221345Sdim}
241221345Sdim
242218893SdimRedeclarableTemplateDecl::CommonBase *
243252723SdimFunctionTemplateDecl::newCommon(ASTContext &C) const {
244218893Sdim  Common *CommonPtr = new (C) Common;
245218893Sdim  C.AddDeallocation(DeallocateCommon, CommonPtr);
246212904Sdim  return CommonPtr;
247195341Sed}
248195341Sed
249263509Sdimvoid FunctionTemplateDecl::LoadLazySpecializations() const {
250263509Sdim  Common *CommonPtr = getCommonPtr();
251263509Sdim  if (CommonPtr->LazySpecializations) {
252263509Sdim    ASTContext &Context = getASTContext();
253263509Sdim    uint32_t *Specs = CommonPtr->LazySpecializations;
254263509Sdim    CommonPtr->LazySpecializations = 0;
255263509Sdim    for (uint32_t I = 0, N = *Specs++; I != N; ++I)
256263509Sdim      (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
257263509Sdim  }
258263509Sdim}
259263509Sdim
260263509Sdimllvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
261263509SdimFunctionTemplateDecl::getSpecializations() const {
262263509Sdim  LoadLazySpecializations();
263263509Sdim  return getCommonPtr()->Specializations;
264263509Sdim}
265263509Sdim
266212904SdimFunctionDecl *
267212904SdimFunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
268212904Sdim                                         unsigned NumArgs, void *&InsertPos) {
269212904Sdim  return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
270198092Srdivacky}
271198092Srdivacky
272221345Sdimvoid FunctionTemplateDecl::addSpecialization(
273221345Sdim      FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
274235633Sdim  if (InsertPos)
275235633Sdim    getSpecializations().InsertNode(Info, InsertPos);
276235633Sdim  else
277235633Sdim    getSpecializations().GetOrInsertNode(Info);
278221345Sdim  if (ASTMutationListener *L = getASTMutationListener())
279221345Sdim    L->AddedCXXTemplateSpecialization(this, Info->Function);
280221345Sdim}
281221345Sdim
282263509SdimArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() {
283221345Sdim  TemplateParameterList *Params = getTemplateParameters();
284221345Sdim  Common *CommonPtr = getCommonPtr();
285221345Sdim  if (!CommonPtr->InjectedArgs) {
286221345Sdim    CommonPtr->InjectedArgs
287263509Sdim      = new (getASTContext()) TemplateArgument[Params->size()];
288263509Sdim    GenerateInjectedTemplateArgs(getASTContext(), Params,
289221345Sdim                                 CommonPtr->InjectedArgs);
290221345Sdim  }
291263509Sdim
292263509Sdim  return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size());
293221345Sdim}
294221345Sdim
295193326Sed//===----------------------------------------------------------------------===//
296193326Sed// ClassTemplateDecl Implementation
297193326Sed//===----------------------------------------------------------------------===//
298193326Sed
299208600Srdivackyvoid ClassTemplateDecl::DeallocateCommon(void *Ptr) {
300208600Srdivacky  static_cast<Common *>(Ptr)->~Common();
301208600Srdivacky}
302208600Srdivacky
303193326SedClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
304193326Sed                                             DeclContext *DC,
305193326Sed                                             SourceLocation L,
306193326Sed                                             DeclarationName Name,
307193326Sed                                             TemplateParameterList *Params,
308193326Sed                                             NamedDecl *Decl,
309193326Sed                                             ClassTemplateDecl *PrevDecl) {
310221345Sdim  AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
311210299Sed  ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl);
312263509Sdim  New->setPreviousDecl(PrevDecl);
313210299Sed  return New;
314193326Sed}
315193326Sed
316235633SdimClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
317235633Sdim                                                         unsigned ID) {
318235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ClassTemplateDecl));
319235633Sdim  return new (Mem) ClassTemplateDecl(EmptyShell());
320221345Sdim}
321221345Sdim
322252723Sdimvoid ClassTemplateDecl::LoadLazySpecializations() const {
323218893Sdim  Common *CommonPtr = getCommonPtr();
324218893Sdim  if (CommonPtr->LazySpecializations) {
325218893Sdim    ASTContext &Context = getASTContext();
326218893Sdim    uint32_t *Specs = CommonPtr->LazySpecializations;
327218893Sdim    CommonPtr->LazySpecializations = 0;
328218893Sdim    for (uint32_t I = 0, N = *Specs++; I != N; ++I)
329218893Sdim      (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
330218893Sdim  }
331218893Sdim}
332218893Sdim
333245431Sdimllvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
334252723SdimClassTemplateDecl::getSpecializations() const {
335218893Sdim  LoadLazySpecializations();
336218893Sdim  return getCommonPtr()->Specializations;
337218893Sdim}
338218893Sdim
339245431Sdimllvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
340218893SdimClassTemplateDecl::getPartialSpecializations() {
341218893Sdim  LoadLazySpecializations();
342218893Sdim  return getCommonPtr()->PartialSpecializations;
343218893Sdim}
344218893Sdim
345218893SdimRedeclarableTemplateDecl::CommonBase *
346252723SdimClassTemplateDecl::newCommon(ASTContext &C) const {
347218893Sdim  Common *CommonPtr = new (C) Common;
348218893Sdim  C.AddDeallocation(DeallocateCommon, CommonPtr);
349212904Sdim  return CommonPtr;
350193326Sed}
351193326Sed
352212904SdimClassTemplateSpecializationDecl *
353212904SdimClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
354212904Sdim                                      unsigned NumArgs, void *&InsertPos) {
355212904Sdim  return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
356212904Sdim}
357212904Sdim
358218893Sdimvoid ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
359218893Sdim                                          void *InsertPos) {
360235633Sdim  if (InsertPos)
361235633Sdim    getSpecializations().InsertNode(D, InsertPos);
362235633Sdim  else {
363235633Sdim    ClassTemplateSpecializationDecl *Existing
364235633Sdim      = getSpecializations().GetOrInsertNode(D);
365235633Sdim    (void)Existing;
366235633Sdim    assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
367235633Sdim  }
368218893Sdim  if (ASTMutationListener *L = getASTMutationListener())
369218893Sdim    L->AddedCXXTemplateSpecialization(this, D);
370218893Sdim}
371218893Sdim
372212904SdimClassTemplatePartialSpecializationDecl *
373212904SdimClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
374212904Sdim                                             unsigned NumArgs,
375212904Sdim                                             void *&InsertPos) {
376212904Sdim  return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs,
377212904Sdim                                InsertPos);
378212904Sdim}
379212904Sdim
380218893Sdimvoid ClassTemplateDecl::AddPartialSpecialization(
381218893Sdim                                      ClassTemplatePartialSpecializationDecl *D,
382218893Sdim                                      void *InsertPos) {
383235633Sdim  if (InsertPos)
384235633Sdim    getPartialSpecializations().InsertNode(D, InsertPos);
385235633Sdim  else {
386235633Sdim    ClassTemplatePartialSpecializationDecl *Existing
387235633Sdim      = getPartialSpecializations().GetOrInsertNode(D);
388235633Sdim    (void)Existing;
389235633Sdim    assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
390235633Sdim  }
391235633Sdim
392218893Sdim  if (ASTMutationListener *L = getASTMutationListener())
393218893Sdim    L->AddedCXXTemplateSpecialization(this, D);
394218893Sdim}
395218893Sdim
396207619Srdivackyvoid ClassTemplateDecl::getPartialSpecializations(
397226890Sdim          SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) {
398245431Sdim  llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &PartialSpecs
399210299Sed    = getPartialSpecializations();
400207619Srdivacky  PS.clear();
401263509Sdim  PS.reserve(PartialSpecs.size());
402245431Sdim  for (llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>::iterator
403207619Srdivacky       P = PartialSpecs.begin(), PEnd = PartialSpecs.end();
404263509Sdim       P != PEnd; ++P)
405263509Sdim    PS.push_back(P->getMostRecentDecl());
406207619Srdivacky}
407207619Srdivacky
408198092SrdivackyClassTemplatePartialSpecializationDecl *
409198092SrdivackyClassTemplateDecl::findPartialSpecialization(QualType T) {
410198092Srdivacky  ASTContext &Context = getASTContext();
411245431Sdim  using llvm::FoldingSetVector;
412245431Sdim  typedef FoldingSetVector<ClassTemplatePartialSpecializationDecl>::iterator
413198092Srdivacky    partial_spec_iterator;
414198092Srdivacky  for (partial_spec_iterator P = getPartialSpecializations().begin(),
415198092Srdivacky                          PEnd = getPartialSpecializations().end();
416198092Srdivacky       P != PEnd; ++P) {
417207619Srdivacky    if (Context.hasSameType(P->getInjectedSpecializationType(), T))
418235633Sdim      return P->getMostRecentDecl();
419198092Srdivacky  }
420198092Srdivacky
421198092Srdivacky  return 0;
422198092Srdivacky}
423198092Srdivacky
424212904SdimClassTemplatePartialSpecializationDecl *
425212904SdimClassTemplateDecl::findPartialSpecInstantiatedFromMember(
426212904Sdim                                    ClassTemplatePartialSpecializationDecl *D) {
427212904Sdim  Decl *DCanon = D->getCanonicalDecl();
428245431Sdim  for (llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>::iterator
429212904Sdim            P = getPartialSpecializations().begin(),
430212904Sdim         PEnd = getPartialSpecializations().end();
431212904Sdim       P != PEnd; ++P) {
432212904Sdim    if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
433235633Sdim      return P->getMostRecentDecl();
434212904Sdim  }
435212904Sdim
436212904Sdim  return 0;
437212904Sdim}
438212904Sdim
439204962SrdivackyQualType
440210299SedClassTemplateDecl::getInjectedClassNameSpecialization() {
441210299Sed  Common *CommonPtr = getCommonPtr();
442193326Sed  if (!CommonPtr->InjectedClassNameType.isNull())
443193326Sed    return CommonPtr->InjectedClassNameType;
444193326Sed
445218893Sdim  // C++0x [temp.dep.type]p2:
446218893Sdim  //  The template argument list of a primary template is a template argument
447218893Sdim  //  list in which the nth template argument has the value of the nth template
448218893Sdim  //  parameter of the class template. If the nth template parameter is a
449218893Sdim  //  template parameter pack (14.5.3), the nth template argument is a pack
450218893Sdim  //  expansion (14.5.3) whose pattern is the name of the template parameter
451218893Sdim  //  pack.
452210299Sed  ASTContext &Context = getASTContext();
453193326Sed  TemplateParameterList *Params = getTemplateParameters();
454226890Sdim  SmallVector<TemplateArgument, 16> TemplateArgs;
455221345Sdim  TemplateArgs.resize(Params->size());
456221345Sdim  GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data());
457193326Sed  CommonPtr->InjectedClassNameType
458198092Srdivacky    = Context.getTemplateSpecializationType(TemplateName(this),
459193326Sed                                            &TemplateArgs[0],
460198092Srdivacky                                            TemplateArgs.size());
461193326Sed  return CommonPtr->InjectedClassNameType;
462193326Sed}
463193326Sed
464193326Sed//===----------------------------------------------------------------------===//
465193326Sed// TemplateTypeParm Allocation/Deallocation Method Implementations
466193326Sed//===----------------------------------------------------------------------===//
467193326Sed
468193326SedTemplateTypeParmDecl *
469218893SdimTemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC,
470221345Sdim                             SourceLocation KeyLoc, SourceLocation NameLoc,
471221345Sdim                             unsigned D, unsigned P, IdentifierInfo *Id,
472221345Sdim                             bool Typename, bool ParameterPack) {
473221345Sdim  TemplateTypeParmDecl *TTPDecl =
474221345Sdim    new (C) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename);
475221345Sdim  QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl);
476221345Sdim  TTPDecl->TypeForDecl = TTPType.getTypePtr();
477221345Sdim  return TTPDecl;
478193326Sed}
479193326Sed
480210299SedTemplateTypeParmDecl *
481235633SdimTemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
482235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTypeParmDecl));
483235633Sdim  return new (Mem) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(),
484235633Sdim                                        0, false);
485210299Sed}
486210299Sed
487198893SrdivackySourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
488221345Sdim  return hasDefaultArgument()
489221345Sdim    ? DefaultArgument->getTypeLoc().getBeginLoc()
490221345Sdim    : SourceLocation();
491198893Srdivacky}
492198893Srdivacky
493221345SdimSourceRange TemplateTypeParmDecl::getSourceRange() const {
494221345Sdim  if (hasDefaultArgument() && !defaultArgumentWasInherited())
495221345Sdim    return SourceRange(getLocStart(),
496221345Sdim                       DefaultArgument->getTypeLoc().getEndLoc());
497221345Sdim  else
498221345Sdim    return TypeDecl::getSourceRange();
499221345Sdim}
500221345Sdim
501198893Srdivackyunsigned TemplateTypeParmDecl::getDepth() const {
502198893Srdivacky  return TypeForDecl->getAs<TemplateTypeParmType>()->getDepth();
503198893Srdivacky}
504198893Srdivacky
505198893Srdivackyunsigned TemplateTypeParmDecl::getIndex() const {
506198893Srdivacky  return TypeForDecl->getAs<TemplateTypeParmType>()->getIndex();
507198893Srdivacky}
508198893Srdivacky
509221345Sdimbool TemplateTypeParmDecl::isParameterPack() const {
510221345Sdim  return TypeForDecl->getAs<TemplateTypeParmType>()->isParameterPack();
511221345Sdim}
512221345Sdim
513193326Sed//===----------------------------------------------------------------------===//
514193326Sed// NonTypeTemplateParmDecl Method Implementations
515193326Sed//===----------------------------------------------------------------------===//
516193326Sed
517218893SdimNonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC,
518221345Sdim                                                 SourceLocation StartLoc,
519221345Sdim                                                 SourceLocation IdLoc,
520221345Sdim                                                 unsigned D, unsigned P,
521221345Sdim                                                 IdentifierInfo *Id,
522218893Sdim                                                 QualType T,
523218893Sdim                                                 TypeSourceInfo *TInfo,
524218893Sdim                                                 const QualType *ExpandedTypes,
525218893Sdim                                                 unsigned NumExpandedTypes,
526218893Sdim                                                TypeSourceInfo **ExpandedTInfos)
527221345Sdim  : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
528218893Sdim    TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
529218893Sdim    ParameterPack(true), ExpandedParameterPack(true),
530218893Sdim    NumExpandedTypes(NumExpandedTypes)
531218893Sdim{
532218893Sdim  if (ExpandedTypes && ExpandedTInfos) {
533218893Sdim    void **TypesAndInfos = reinterpret_cast<void **>(this + 1);
534218893Sdim    for (unsigned I = 0; I != NumExpandedTypes; ++I) {
535218893Sdim      TypesAndInfos[2*I] = ExpandedTypes[I].getAsOpaquePtr();
536218893Sdim      TypesAndInfos[2*I + 1] = ExpandedTInfos[I];
537218893Sdim    }
538218893Sdim  }
539218893Sdim}
540218893Sdim
541193326SedNonTypeTemplateParmDecl *
542218893SdimNonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
543221345Sdim                                SourceLocation StartLoc, SourceLocation IdLoc,
544221345Sdim                                unsigned D, unsigned P, IdentifierInfo *Id,
545221345Sdim                                QualType T, bool ParameterPack,
546221345Sdim                                TypeSourceInfo *TInfo) {
547221345Sdim  return new (C) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id,
548221345Sdim                                         T, ParameterPack, TInfo);
549193326Sed}
550193326Sed
551218893SdimNonTypeTemplateParmDecl *
552218893SdimNonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
553221345Sdim                                SourceLocation StartLoc, SourceLocation IdLoc,
554221345Sdim                                unsigned D, unsigned P,
555218893Sdim                                IdentifierInfo *Id, QualType T,
556218893Sdim                                TypeSourceInfo *TInfo,
557218893Sdim                                const QualType *ExpandedTypes,
558218893Sdim                                unsigned NumExpandedTypes,
559218893Sdim                                TypeSourceInfo **ExpandedTInfos) {
560218893Sdim  unsigned Size = sizeof(NonTypeTemplateParmDecl)
561218893Sdim                + NumExpandedTypes * 2 * sizeof(void*);
562218893Sdim  void *Mem = C.Allocate(Size);
563221345Sdim  return new (Mem) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc,
564221345Sdim                                           D, P, Id, T, TInfo,
565218893Sdim                                           ExpandedTypes, NumExpandedTypes,
566218893Sdim                                           ExpandedTInfos);
567218893Sdim}
568218893Sdim
569235633SdimNonTypeTemplateParmDecl *
570235633SdimNonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
571235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NonTypeTemplateParmDecl));
572235633Sdim  return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(),
573235633Sdim                                           SourceLocation(), 0, 0, 0,
574235633Sdim                                           QualType(), false, 0);
575235633Sdim}
576235633Sdim
577235633SdimNonTypeTemplateParmDecl *
578235633SdimNonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
579235633Sdim                                            unsigned NumExpandedTypes) {
580235633Sdim  unsigned Size = sizeof(NonTypeTemplateParmDecl)
581235633Sdim                + NumExpandedTypes * 2 * sizeof(void*);
582235633Sdim
583235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID, Size);
584235633Sdim  return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(),
585235633Sdim                                           SourceLocation(), 0, 0, 0,
586235633Sdim                                           QualType(), 0, 0, NumExpandedTypes,
587235633Sdim                                           0);
588235633Sdim}
589235633Sdim
590218893SdimSourceRange NonTypeTemplateParmDecl::getSourceRange() const {
591221345Sdim  if (hasDefaultArgument() && !defaultArgumentWasInherited())
592221345Sdim    return SourceRange(getOuterLocStart(),
593221345Sdim                       getDefaultArgument()->getSourceRange().getEnd());
594221345Sdim  return DeclaratorDecl::getSourceRange();
595218893Sdim}
596218893Sdim
597193326SedSourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
598210299Sed  return hasDefaultArgument()
599210299Sed    ? getDefaultArgument()->getSourceRange().getBegin()
600210299Sed    : SourceLocation();
601193326Sed}
602193326Sed
603193326Sed//===----------------------------------------------------------------------===//
604193326Sed// TemplateTemplateParmDecl Method Implementations
605193326Sed//===----------------------------------------------------------------------===//
606193326Sed
607235633Sdimvoid TemplateTemplateParmDecl::anchor() { }
608235633Sdim
609245431SdimTemplateTemplateParmDecl::TemplateTemplateParmDecl(
610245431Sdim    DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
611245431Sdim    IdentifierInfo *Id, TemplateParameterList *Params,
612245431Sdim    unsigned NumExpansions, TemplateParameterList * const *Expansions)
613245431Sdim  : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
614245431Sdim    TemplateParmPosition(D, P), DefaultArgument(),
615245431Sdim    DefaultArgumentWasInherited(false), ParameterPack(true),
616245431Sdim    ExpandedParameterPack(true), NumExpandedParams(NumExpansions) {
617245431Sdim  if (Expansions)
618245431Sdim    std::memcpy(reinterpret_cast<void*>(this + 1), Expansions,
619245431Sdim                sizeof(TemplateParameterList*) * NumExpandedParams);
620245431Sdim}
621245431Sdim
622193326SedTemplateTemplateParmDecl *
623218893SdimTemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
624193326Sed                                 SourceLocation L, unsigned D, unsigned P,
625218893Sdim                                 bool ParameterPack, IdentifierInfo *Id,
626193326Sed                                 TemplateParameterList *Params) {
627218893Sdim  return new (C) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
628218893Sdim                                          Params);
629193326Sed}
630193326Sed
631235633SdimTemplateTemplateParmDecl *
632245431SdimTemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
633245431Sdim                                 SourceLocation L, unsigned D, unsigned P,
634245431Sdim                                 IdentifierInfo *Id,
635245431Sdim                                 TemplateParameterList *Params,
636252723Sdim                                 ArrayRef<TemplateParameterList *> Expansions) {
637245431Sdim  void *Mem = C.Allocate(sizeof(TemplateTemplateParmDecl) +
638245431Sdim                         sizeof(TemplateParameterList*) * Expansions.size());
639245431Sdim  return new (Mem) TemplateTemplateParmDecl(DC, L, D, P, Id, Params,
640245431Sdim                                            Expansions.size(),
641245431Sdim                                            Expansions.data());
642245431Sdim}
643245431Sdim
644245431SdimTemplateTemplateParmDecl *
645235633SdimTemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
646235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTemplateParmDecl));
647235633Sdim  return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, false,
648235633Sdim                                            0, 0);
649235633Sdim}
650235633Sdim
651245431SdimTemplateTemplateParmDecl *
652245431SdimTemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
653245431Sdim                                             unsigned NumExpansions) {
654245431Sdim  unsigned Size = sizeof(TemplateTemplateParmDecl) +
655245431Sdim                  sizeof(TemplateParameterList*) * NumExpansions;
656245431Sdim  void *Mem = AllocateDeserializedDecl(C, ID, Size);
657245431Sdim  return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, 0, 0,
658245431Sdim                                            NumExpansions, 0);
659245431Sdim}
660245431Sdim
661193326Sed//===----------------------------------------------------------------------===//
662193326Sed// TemplateArgumentList Implementation
663193326Sed//===----------------------------------------------------------------------===//
664218893SdimTemplateArgumentList *
665218893SdimTemplateArgumentList::CreateCopy(ASTContext &Context,
666218893Sdim                                 const TemplateArgument *Args,
667218893Sdim                                 unsigned NumArgs) {
668218893Sdim  std::size_t Size = sizeof(TemplateArgumentList)
669218893Sdim                   + NumArgs * sizeof(TemplateArgument);
670218893Sdim  void *Mem = Context.Allocate(Size);
671218893Sdim  TemplateArgument *StoredArgs
672218893Sdim    = reinterpret_cast<TemplateArgument *>(
673218893Sdim                                static_cast<TemplateArgumentList *>(Mem) + 1);
674218893Sdim  std::uninitialized_copy(Args, Args + NumArgs, StoredArgs);
675218893Sdim  return new (Mem) TemplateArgumentList(StoredArgs, NumArgs, true);
676193326Sed}
677193326Sed
678226890SdimFunctionTemplateSpecializationInfo *
679226890SdimFunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD,
680226890Sdim                                           FunctionTemplateDecl *Template,
681226890Sdim                                           TemplateSpecializationKind TSK,
682226890Sdim                                       const TemplateArgumentList *TemplateArgs,
683226890Sdim                          const TemplateArgumentListInfo *TemplateArgsAsWritten,
684226890Sdim                                           SourceLocation POI) {
685226890Sdim  const ASTTemplateArgumentListInfo *ArgsAsWritten = 0;
686226890Sdim  if (TemplateArgsAsWritten)
687226890Sdim    ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
688226890Sdim                                                        *TemplateArgsAsWritten);
689226890Sdim
690226890Sdim  return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK,
691226890Sdim                                                    TemplateArgs,
692226890Sdim                                                    ArgsAsWritten,
693226890Sdim                                                    POI);
694226890Sdim}
695226890Sdim
696193326Sed//===----------------------------------------------------------------------===//
697235633Sdim// TemplateDecl Implementation
698235633Sdim//===----------------------------------------------------------------------===//
699235633Sdim
700235633Sdimvoid TemplateDecl::anchor() { }
701235633Sdim
702235633Sdim//===----------------------------------------------------------------------===//
703193326Sed// ClassTemplateSpecializationDecl Implementation
704193326Sed//===----------------------------------------------------------------------===//
705193326SedClassTemplateSpecializationDecl::
706208600SrdivackyClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
707221345Sdim                                DeclContext *DC, SourceLocation StartLoc,
708221345Sdim                                SourceLocation IdLoc,
709193326Sed                                ClassTemplateDecl *SpecializedTemplate,
710218893Sdim                                const TemplateArgument *Args,
711218893Sdim                                unsigned NumArgs,
712198092Srdivacky                                ClassTemplateSpecializationDecl *PrevDecl)
713221345Sdim  : CXXRecordDecl(DK, TK, DC, StartLoc, IdLoc,
714198092Srdivacky                  SpecializedTemplate->getIdentifier(),
715198092Srdivacky                  PrevDecl),
716193326Sed    SpecializedTemplate(SpecializedTemplate),
717210299Sed    ExplicitInfo(0),
718218893Sdim    TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)),
719193326Sed    SpecializationKind(TSK_Undeclared) {
720193326Sed}
721198092Srdivacky
722210299SedClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(Kind DK)
723221345Sdim  : CXXRecordDecl(DK, TTK_Struct, 0, SourceLocation(), SourceLocation(), 0, 0),
724210299Sed    ExplicitInfo(0),
725210299Sed    SpecializationKind(TSK_Undeclared) {
726210299Sed}
727210299Sed
728193326SedClassTemplateSpecializationDecl *
729208600SrdivackyClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
730221345Sdim                                        DeclContext *DC,
731221345Sdim                                        SourceLocation StartLoc,
732221345Sdim                                        SourceLocation IdLoc,
733193326Sed                                        ClassTemplateDecl *SpecializedTemplate,
734218893Sdim                                        const TemplateArgument *Args,
735218893Sdim                                        unsigned NumArgs,
736193326Sed                                   ClassTemplateSpecializationDecl *PrevDecl) {
737193326Sed  ClassTemplateSpecializationDecl *Result
738198092Srdivacky    = new (Context)ClassTemplateSpecializationDecl(Context,
739193326Sed                                                   ClassTemplateSpecialization,
740221345Sdim                                                   TK, DC, StartLoc, IdLoc,
741193326Sed                                                   SpecializedTemplate,
742218893Sdim                                                   Args, NumArgs,
743198092Srdivacky                                                   PrevDecl);
744252723Sdim  Result->MayHaveOutOfDateDef = false;
745252723Sdim
746193326Sed  Context.getTypeDeclType(Result, PrevDecl);
747193326Sed  return Result;
748193326Sed}
749193326Sed
750210299SedClassTemplateSpecializationDecl *
751235633SdimClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
752235633Sdim                                                    unsigned ID) {
753235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID,
754235633Sdim                                       sizeof(ClassTemplateSpecializationDecl));
755252723Sdim  ClassTemplateSpecializationDecl *Result =
756252723Sdim    new (Mem) ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
757252723Sdim  Result->MayHaveOutOfDateDef = false;
758252723Sdim  return Result;
759210299Sed}
760210299Sed
761252723Sdimvoid ClassTemplateSpecializationDecl::getNameForDiagnostic(
762252723Sdim    raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
763252723Sdim  NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
764198092Srdivacky
765198092Srdivacky  const TemplateArgumentList &TemplateArgs = getTemplateArgs();
766252723Sdim  TemplateSpecializationType::PrintTemplateArgumentList(
767252723Sdim      OS, TemplateArgs.data(), TemplateArgs.size(), Policy);
768198092Srdivacky}
769198092Srdivacky
770198092SrdivackyClassTemplateDecl *
771198092SrdivackyClassTemplateSpecializationDecl::getSpecializedTemplate() const {
772198092Srdivacky  if (SpecializedPartialSpecialization *PartialSpec
773198092Srdivacky      = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
774198092Srdivacky    return PartialSpec->PartialSpecialization->getSpecializedTemplate();
775198092Srdivacky  return SpecializedTemplate.get<ClassTemplateDecl*>();
776198092Srdivacky}
777198092Srdivacky
778221345SdimSourceRange
779221345SdimClassTemplateSpecializationDecl::getSourceRange() const {
780226890Sdim  if (ExplicitInfo) {
781245431Sdim    SourceLocation Begin = getTemplateKeywordLoc();
782245431Sdim    if (Begin.isValid()) {
783245431Sdim      // Here we have an explicit (partial) specialization or instantiation.
784245431Sdim      assert(getSpecializationKind() == TSK_ExplicitSpecialization ||
785245431Sdim             getSpecializationKind() == TSK_ExplicitInstantiationDeclaration ||
786245431Sdim             getSpecializationKind() == TSK_ExplicitInstantiationDefinition);
787245431Sdim      if (getExternLoc().isValid())
788245431Sdim        Begin = getExternLoc();
789245431Sdim      SourceLocation End = getRBraceLoc();
790245431Sdim      if (End.isInvalid())
791245431Sdim        End = getTypeAsWritten()->getTypeLoc().getEndLoc();
792245431Sdim      return SourceRange(Begin, End);
793245431Sdim    }
794245431Sdim    // An implicit instantiation of a class template partial specialization
795245431Sdim    // uses ExplicitInfo to record the TypeAsWritten, but the source
796245431Sdim    // locations should be retrieved from the instantiation pattern.
797245431Sdim    typedef ClassTemplatePartialSpecializationDecl CTPSDecl;
798245431Sdim    CTPSDecl *ctpsd = const_cast<CTPSDecl*>(cast<CTPSDecl>(this));
799245431Sdim    CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
800245431Sdim    assert(inst_from != 0);
801245431Sdim    return inst_from->getSourceRange();
802226890Sdim  }
803226890Sdim  else {
804226890Sdim    // No explicit info available.
805226890Sdim    llvm::PointerUnion<ClassTemplateDecl *,
806226890Sdim                       ClassTemplatePartialSpecializationDecl *>
807226890Sdim      inst_from = getInstantiatedFrom();
808226890Sdim    if (inst_from.isNull())
809226890Sdim      return getSpecializedTemplate()->getSourceRange();
810226890Sdim    if (ClassTemplateDecl *ctd = inst_from.dyn_cast<ClassTemplateDecl*>())
811226890Sdim      return ctd->getSourceRange();
812226890Sdim    return inst_from.get<ClassTemplatePartialSpecializationDecl*>()
813226890Sdim      ->getSourceRange();
814226890Sdim  }
815221345Sdim}
816221345Sdim
817193326Sed//===----------------------------------------------------------------------===//
818193326Sed// ClassTemplatePartialSpecializationDecl Implementation
819193326Sed//===----------------------------------------------------------------------===//
820235633Sdimvoid ClassTemplatePartialSpecializationDecl::anchor() { }
821235633Sdim
822221345SdimClassTemplatePartialSpecializationDecl::
823221345SdimClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
824221345Sdim                                       DeclContext *DC,
825221345Sdim                                       SourceLocation StartLoc,
826221345Sdim                                       SourceLocation IdLoc,
827221345Sdim                                       TemplateParameterList *Params,
828221345Sdim                                       ClassTemplateDecl *SpecializedTemplate,
829221345Sdim                                       const TemplateArgument *Args,
830221345Sdim                                       unsigned NumArgs,
831263509Sdim                               const ASTTemplateArgumentListInfo *ArgInfos,
832263509Sdim                               ClassTemplatePartialSpecializationDecl *PrevDecl)
833221345Sdim  : ClassTemplateSpecializationDecl(Context,
834221345Sdim                                    ClassTemplatePartialSpecialization,
835221345Sdim                                    TK, DC, StartLoc, IdLoc,
836221345Sdim                                    SpecializedTemplate,
837221345Sdim                                    Args, NumArgs, PrevDecl),
838221345Sdim    TemplateParams(Params), ArgsAsWritten(ArgInfos),
839221345Sdim    InstantiatedFromMember(0, false)
840263509Sdim{
841221345Sdim  AdoptTemplateParameterList(Params, this);
842221345Sdim}
843221345Sdim
844193326SedClassTemplatePartialSpecializationDecl *
845193326SedClassTemplatePartialSpecializationDecl::
846221345SdimCreate(ASTContext &Context, TagKind TK,DeclContext *DC,
847221345Sdim       SourceLocation StartLoc, SourceLocation IdLoc,
848193326Sed       TemplateParameterList *Params,
849193326Sed       ClassTemplateDecl *SpecializedTemplate,
850218893Sdim       const TemplateArgument *Args,
851218893Sdim       unsigned NumArgs,
852199990Srdivacky       const TemplateArgumentListInfo &ArgInfos,
853204962Srdivacky       QualType CanonInjectedType,
854263509Sdim       ClassTemplatePartialSpecializationDecl *PrevDecl) {
855263509Sdim  const ASTTemplateArgumentListInfo *ASTArgInfos =
856263509Sdim    ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
857198893Srdivacky
858193326Sed  ClassTemplatePartialSpecializationDecl *Result
859221345Sdim    = new (Context)ClassTemplatePartialSpecializationDecl(Context, TK, DC,
860221345Sdim                                                          StartLoc, IdLoc,
861221345Sdim                                                          Params,
862193326Sed                                                          SpecializedTemplate,
863218893Sdim                                                          Args, NumArgs,
864263509Sdim                                                          ASTArgInfos,
865263509Sdim                                                          PrevDecl);
866193326Sed  Result->setSpecializationKind(TSK_ExplicitSpecialization);
867252723Sdim  Result->MayHaveOutOfDateDef = false;
868204962Srdivacky
869204962Srdivacky  Context.getInjectedClassNameType(Result, CanonInjectedType);
870193326Sed  return Result;
871193326Sed}
872198092Srdivacky
873210299SedClassTemplatePartialSpecializationDecl *
874235633SdimClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
875235633Sdim                                                           unsigned ID) {
876235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID,
877235633Sdim                sizeof(ClassTemplatePartialSpecializationDecl));
878252723Sdim  ClassTemplatePartialSpecializationDecl *Result
879252723Sdim    = new (Mem) ClassTemplatePartialSpecializationDecl();
880252723Sdim  Result->MayHaveOutOfDateDef = false;
881252723Sdim  return Result;
882210299Sed}
883210299Sed
884198092Srdivacky//===----------------------------------------------------------------------===//
885198092Srdivacky// FriendTemplateDecl Implementation
886198092Srdivacky//===----------------------------------------------------------------------===//
887198092Srdivacky
888235633Sdimvoid FriendTemplateDecl::anchor() { }
889235633Sdim
890198092SrdivackyFriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
891198092Srdivacky                                               DeclContext *DC,
892198092Srdivacky                                               SourceLocation L,
893198092Srdivacky                                               unsigned NParams,
894198092Srdivacky                                               TemplateParameterList **Params,
895198092Srdivacky                                               FriendUnion Friend,
896198092Srdivacky                                               SourceLocation FLoc) {
897198092Srdivacky  FriendTemplateDecl *Result
898198092Srdivacky    = new (Context) FriendTemplateDecl(DC, L, NParams, Params, Friend, FLoc);
899198092Srdivacky  return Result;
900198092Srdivacky}
901212904Sdim
902235633SdimFriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
903235633Sdim                                                           unsigned ID) {
904235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FriendTemplateDecl));
905235633Sdim  return new (Mem) FriendTemplateDecl(EmptyShell());
906212904Sdim}
907223017Sdim
908223017Sdim//===----------------------------------------------------------------------===//
909223017Sdim// TypeAliasTemplateDecl Implementation
910223017Sdim//===----------------------------------------------------------------------===//
911223017Sdim
912223017SdimTypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
913223017Sdim                                                     DeclContext *DC,
914223017Sdim                                                     SourceLocation L,
915223017Sdim                                                     DeclarationName Name,
916223017Sdim                                                  TemplateParameterList *Params,
917223017Sdim                                                     NamedDecl *Decl) {
918223017Sdim  AdoptTemplateParameterList(Params, DC);
919223017Sdim  return new (C) TypeAliasTemplateDecl(DC, L, Name, Params, Decl);
920223017Sdim}
921223017Sdim
922235633SdimTypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
923235633Sdim                                                                 unsigned ID) {
924235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasTemplateDecl));
925235633Sdim  return new (Mem) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(),
926235633Sdim                                         0, 0);
927223017Sdim}
928223017Sdim
929223017Sdimvoid TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) {
930223017Sdim  static_cast<Common *>(Ptr)->~Common();
931223017Sdim}
932223017SdimRedeclarableTemplateDecl::CommonBase *
933252723SdimTypeAliasTemplateDecl::newCommon(ASTContext &C) const {
934223017Sdim  Common *CommonPtr = new (C) Common;
935223017Sdim  C.AddDeallocation(DeallocateCommon, CommonPtr);
936223017Sdim  return CommonPtr;
937223017Sdim}
938223017Sdim
939235633Sdim//===----------------------------------------------------------------------===//
940235633Sdim// ClassScopeFunctionSpecializationDecl Implementation
941235633Sdim//===----------------------------------------------------------------------===//
942235633Sdim
943235633Sdimvoid ClassScopeFunctionSpecializationDecl::anchor() { }
944235633Sdim
945235633SdimClassScopeFunctionSpecializationDecl *
946235633SdimClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
947235633Sdim                                                         unsigned ID) {
948235633Sdim  void *Mem = AllocateDeserializedDecl(C, ID,
949235633Sdim                sizeof(ClassScopeFunctionSpecializationDecl));
950245431Sdim  return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0,
951245431Sdim                                             false, TemplateArgumentListInfo());
952235633Sdim}
953263509Sdim
954263509Sdim//===----------------------------------------------------------------------===//
955263509Sdim// VarTemplateDecl Implementation
956263509Sdim//===----------------------------------------------------------------------===//
957263509Sdim
958263509Sdimvoid VarTemplateDecl::DeallocateCommon(void *Ptr) {
959263509Sdim  static_cast<Common *>(Ptr)->~Common();
960263509Sdim}
961263509Sdim
962263509SdimVarTemplateDecl *VarTemplateDecl::getDefinition() {
963263509Sdim  VarTemplateDecl *CurD = this;
964263509Sdim  while (CurD) {
965263509Sdim    if (CurD->isThisDeclarationADefinition())
966263509Sdim      return CurD;
967263509Sdim    CurD = CurD->getPreviousDecl();
968263509Sdim  }
969263509Sdim  return 0;
970263509Sdim}
971263509Sdim
972263509SdimVarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
973263509Sdim                                         SourceLocation L, DeclarationName Name,
974263509Sdim                                         TemplateParameterList *Params,
975263509Sdim                                         NamedDecl *Decl,
976263509Sdim                                         VarTemplateDecl *PrevDecl) {
977263509Sdim  VarTemplateDecl *New = new (C) VarTemplateDecl(DC, L, Name, Params, Decl);
978263509Sdim  New->setPreviousDecl(PrevDecl);
979263509Sdim  return New;
980263509Sdim}
981263509Sdim
982263509SdimVarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
983263509Sdim                                                     unsigned ID) {
984263509Sdim  void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarTemplateDecl));
985263509Sdim  return new (Mem) VarTemplateDecl(EmptyShell());
986263509Sdim}
987263509Sdim
988263509Sdim// TODO: Unify accross class, function and variable templates?
989263509Sdim//       May require moving this and Common to RedeclarableTemplateDecl.
990263509Sdimvoid VarTemplateDecl::LoadLazySpecializations() const {
991263509Sdim  Common *CommonPtr = getCommonPtr();
992263509Sdim  if (CommonPtr->LazySpecializations) {
993263509Sdim    ASTContext &Context = getASTContext();
994263509Sdim    uint32_t *Specs = CommonPtr->LazySpecializations;
995263509Sdim    CommonPtr->LazySpecializations = 0;
996263509Sdim    for (uint32_t I = 0, N = *Specs++; I != N; ++I)
997263509Sdim      (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
998263509Sdim  }
999263509Sdim}
1000263509Sdim
1001263509Sdimllvm::FoldingSetVector<VarTemplateSpecializationDecl> &
1002263509SdimVarTemplateDecl::getSpecializations() const {
1003263509Sdim  LoadLazySpecializations();
1004263509Sdim  return getCommonPtr()->Specializations;
1005263509Sdim}
1006263509Sdim
1007263509Sdimllvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
1008263509SdimVarTemplateDecl::getPartialSpecializations() {
1009263509Sdim  LoadLazySpecializations();
1010263509Sdim  return getCommonPtr()->PartialSpecializations;
1011263509Sdim}
1012263509Sdim
1013263509SdimRedeclarableTemplateDecl::CommonBase *
1014263509SdimVarTemplateDecl::newCommon(ASTContext &C) const {
1015263509Sdim  Common *CommonPtr = new (C) Common;
1016263509Sdim  C.AddDeallocation(DeallocateCommon, CommonPtr);
1017263509Sdim  return CommonPtr;
1018263509Sdim}
1019263509Sdim
1020263509SdimVarTemplateSpecializationDecl *
1021263509SdimVarTemplateDecl::findSpecialization(const TemplateArgument *Args,
1022263509Sdim                                    unsigned NumArgs, void *&InsertPos) {
1023263509Sdim  return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
1024263509Sdim}
1025263509Sdim
1026263509Sdimvoid VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
1027263509Sdim                                        void *InsertPos) {
1028263509Sdim  if (InsertPos)
1029263509Sdim    getSpecializations().InsertNode(D, InsertPos);
1030263509Sdim  else {
1031263509Sdim    VarTemplateSpecializationDecl *Existing =
1032263509Sdim        getSpecializations().GetOrInsertNode(D);
1033263509Sdim    (void)Existing;
1034263509Sdim    assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
1035263509Sdim  }
1036263509Sdim  if (ASTMutationListener *L = getASTMutationListener())
1037263509Sdim    L->AddedCXXTemplateSpecialization(this, D);
1038263509Sdim}
1039263509Sdim
1040263509SdimVarTemplatePartialSpecializationDecl *
1041263509SdimVarTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
1042263509Sdim                                           unsigned NumArgs, void *&InsertPos) {
1043263509Sdim  return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs,
1044263509Sdim                                InsertPos);
1045263509Sdim}
1046263509Sdim
1047263509Sdimvoid VarTemplateDecl::AddPartialSpecialization(
1048263509Sdim    VarTemplatePartialSpecializationDecl *D, void *InsertPos) {
1049263509Sdim  if (InsertPos)
1050263509Sdim    getPartialSpecializations().InsertNode(D, InsertPos);
1051263509Sdim  else {
1052263509Sdim    VarTemplatePartialSpecializationDecl *Existing =
1053263509Sdim        getPartialSpecializations().GetOrInsertNode(D);
1054263509Sdim    (void)Existing;
1055263509Sdim    assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
1056263509Sdim  }
1057263509Sdim
1058263509Sdim  if (ASTMutationListener *L = getASTMutationListener())
1059263509Sdim    L->AddedCXXTemplateSpecialization(this, D);
1060263509Sdim}
1061263509Sdim
1062263509Sdimvoid VarTemplateDecl::getPartialSpecializations(
1063263509Sdim    SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS) {
1064263509Sdim  llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &PartialSpecs =
1065263509Sdim      getPartialSpecializations();
1066263509Sdim  PS.clear();
1067263509Sdim  PS.reserve(PartialSpecs.size());
1068263509Sdim  for (llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>::iterator
1069263509Sdim           P = PartialSpecs.begin(),
1070263509Sdim           PEnd = PartialSpecs.end();
1071263509Sdim       P != PEnd; ++P)
1072263509Sdim    PS.push_back(P->getMostRecentDecl());
1073263509Sdim}
1074263509Sdim
1075263509SdimVarTemplatePartialSpecializationDecl *
1076263509SdimVarTemplateDecl::findPartialSpecInstantiatedFromMember(
1077263509Sdim    VarTemplatePartialSpecializationDecl *D) {
1078263509Sdim  Decl *DCanon = D->getCanonicalDecl();
1079263509Sdim  for (llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>::iterator
1080263509Sdim           P = getPartialSpecializations().begin(),
1081263509Sdim           PEnd = getPartialSpecializations().end();
1082263509Sdim       P != PEnd; ++P) {
1083263509Sdim    if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
1084263509Sdim      return P->getMostRecentDecl();
1085263509Sdim  }
1086263509Sdim
1087263509Sdim  return 0;
1088263509Sdim}
1089263509Sdim
1090263509Sdim//===----------------------------------------------------------------------===//
1091263509Sdim// VarTemplateSpecializationDecl Implementation
1092263509Sdim//===----------------------------------------------------------------------===//
1093263509SdimVarTemplateSpecializationDecl::VarTemplateSpecializationDecl(
1094263509Sdim    ASTContext &Context, Kind DK, DeclContext *DC, SourceLocation StartLoc,
1095263509Sdim    SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
1096263509Sdim    TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
1097263509Sdim    unsigned NumArgs)
1098263509Sdim    : VarDecl(DK, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), T,
1099263509Sdim              TInfo, S),
1100263509Sdim      SpecializedTemplate(SpecializedTemplate), ExplicitInfo(0),
1101263509Sdim      TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)),
1102263509Sdim      SpecializationKind(TSK_Undeclared) {}
1103263509Sdim
1104263509SdimVarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK)
1105263509Sdim    : VarDecl(DK, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0,
1106263509Sdim              SC_None),
1107263509Sdim      ExplicitInfo(0), SpecializationKind(TSK_Undeclared) {}
1108263509Sdim
1109263509SdimVarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
1110263509Sdim    ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1111263509Sdim    SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
1112263509Sdim    TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
1113263509Sdim    unsigned NumArgs) {
1114263509Sdim  VarTemplateSpecializationDecl *Result = new (Context)
1115263509Sdim      VarTemplateSpecializationDecl(Context, VarTemplateSpecialization, DC,
1116263509Sdim                                    StartLoc, IdLoc, SpecializedTemplate, T,
1117263509Sdim                                    TInfo, S, Args, NumArgs);
1118263509Sdim  return Result;
1119263509Sdim}
1120263509Sdim
1121263509SdimVarTemplateSpecializationDecl *
1122263509SdimVarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
1123263509Sdim  void *Mem =
1124263509Sdim      AllocateDeserializedDecl(C, ID, sizeof(VarTemplateSpecializationDecl));
1125263509Sdim  VarTemplateSpecializationDecl *Result =
1126263509Sdim      new (Mem) VarTemplateSpecializationDecl(VarTemplateSpecialization);
1127263509Sdim  return Result;
1128263509Sdim}
1129263509Sdim
1130263509Sdimvoid VarTemplateSpecializationDecl::getNameForDiagnostic(
1131263509Sdim    raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
1132263509Sdim  NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
1133263509Sdim
1134263509Sdim  const TemplateArgumentList &TemplateArgs = getTemplateArgs();
1135263509Sdim  TemplateSpecializationType::PrintTemplateArgumentList(
1136263509Sdim      OS, TemplateArgs.data(), TemplateArgs.size(), Policy);
1137263509Sdim}
1138263509Sdim
1139263509SdimVarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
1140263509Sdim  if (SpecializedPartialSpecialization *PartialSpec =
1141263509Sdim          SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
1142263509Sdim    return PartialSpec->PartialSpecialization->getSpecializedTemplate();
1143263509Sdim  return SpecializedTemplate.get<VarTemplateDecl *>();
1144263509Sdim}
1145263509Sdim
1146263509Sdimvoid VarTemplateSpecializationDecl::setTemplateArgsInfo(
1147263509Sdim    const TemplateArgumentListInfo &ArgsInfo) {
1148263509Sdim  unsigned N = ArgsInfo.size();
1149263509Sdim  TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc());
1150263509Sdim  TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc());
1151263509Sdim  for (unsigned I = 0; I != N; ++I)
1152263509Sdim    TemplateArgsInfo.addArgument(ArgsInfo[I]);
1153263509Sdim}
1154263509Sdim
1155263509Sdim//===----------------------------------------------------------------------===//
1156263509Sdim// VarTemplatePartialSpecializationDecl Implementation
1157263509Sdim//===----------------------------------------------------------------------===//
1158263509Sdimvoid VarTemplatePartialSpecializationDecl::anchor() {}
1159263509Sdim
1160263509SdimVarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
1161263509Sdim    ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1162263509Sdim    SourceLocation IdLoc, TemplateParameterList *Params,
1163263509Sdim    VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
1164263509Sdim    StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
1165263509Sdim    const ASTTemplateArgumentListInfo *ArgInfos)
1166263509Sdim    : VarTemplateSpecializationDecl(Context, VarTemplatePartialSpecialization,
1167263509Sdim                                    DC, StartLoc, IdLoc, SpecializedTemplate, T,
1168263509Sdim                                    TInfo, S, Args, NumArgs),
1169263509Sdim      TemplateParams(Params), ArgsAsWritten(ArgInfos),
1170263509Sdim      InstantiatedFromMember(0, false) {
1171263509Sdim  // TODO: The template parameters should be in DC by now. Verify.
1172263509Sdim  // AdoptTemplateParameterList(Params, DC);
1173263509Sdim}
1174263509Sdim
1175263509SdimVarTemplatePartialSpecializationDecl *
1176263509SdimVarTemplatePartialSpecializationDecl::Create(
1177263509Sdim    ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1178263509Sdim    SourceLocation IdLoc, TemplateParameterList *Params,
1179263509Sdim    VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
1180263509Sdim    StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
1181263509Sdim    const TemplateArgumentListInfo &ArgInfos) {
1182263509Sdim  const ASTTemplateArgumentListInfo *ASTArgInfos
1183263509Sdim    = ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
1184263509Sdim
1185263509Sdim  VarTemplatePartialSpecializationDecl *Result =
1186263509Sdim      new (Context) VarTemplatePartialSpecializationDecl(
1187263509Sdim          Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo,
1188263509Sdim          S, Args, NumArgs, ASTArgInfos);
1189263509Sdim  Result->setSpecializationKind(TSK_ExplicitSpecialization);
1190263509Sdim  return Result;
1191263509Sdim}
1192263509Sdim
1193263509SdimVarTemplatePartialSpecializationDecl *
1194263509SdimVarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
1195263509Sdim                                                         unsigned ID) {
1196263509Sdim  void *Mem = AllocateDeserializedDecl(
1197263509Sdim      C, ID, sizeof(VarTemplatePartialSpecializationDecl));
1198263509Sdim  VarTemplatePartialSpecializationDecl *Result =
1199263509Sdim      new (Mem) VarTemplatePartialSpecializationDecl();
1200263509Sdim  return Result;
1201263509Sdim}
1202