DeclTemplate.cpp revision b17120c5d87b1b078891071188b89ec4fe6857bf
1//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the C++ related Decl classes for templates.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/DeclCXX.h"
15#include "clang/AST/DeclTemplate.h"
16#include "clang/AST/Expr.h"
17#include "clang/AST/ASTContext.h"
18#include "clang/Basic/IdentifierTable.h"
19#include "llvm/ADT/STLExtras.h"
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
23// TemplateParameterList Implementation
24//===----------------------------------------------------------------------===//
25
26TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
27                                             SourceLocation LAngleLoc,
28                                             Decl **Params, unsigned NumParams,
29                                             SourceLocation RAngleLoc)
30  : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
31    NumParams(NumParams) {
32  for (unsigned Idx = 0; Idx < NumParams; ++Idx)
33    begin()[Idx] = Params[Idx];
34}
35
36TemplateParameterList *
37TemplateParameterList::Create(ASTContext &C, SourceLocation TemplateLoc,
38                              SourceLocation LAngleLoc, Decl **Params,
39                              unsigned NumParams, SourceLocation RAngleLoc) {
40  unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams;
41  unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment;
42  void *Mem = C.Allocate(Size, Align);
43  return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
44                                         NumParams, RAngleLoc);
45}
46
47unsigned TemplateParameterList::getMinRequiredArguments() const {
48  unsigned NumRequiredArgs = size();
49  iterator Param = const_cast<TemplateParameterList *>(this)->end(),
50      ParamBegin = const_cast<TemplateParameterList *>(this)->begin();
51  while (Param != ParamBegin) {
52    --Param;
53
54    if (!(*Param)->isTemplateParameterPack() &&
55        !(isa<TemplateTypeParmDecl>(*Param) &&
56          cast<TemplateTypeParmDecl>(*Param)->hasDefaultArgument()) &&
57        !(isa<NonTypeTemplateParmDecl>(*Param) &&
58          cast<NonTypeTemplateParmDecl>(*Param)->hasDefaultArgument()) &&
59        !(isa<TemplateTemplateParmDecl>(*Param) &&
60          cast<TemplateTemplateParmDecl>(*Param)->hasDefaultArgument()))
61      break;
62
63    --NumRequiredArgs;
64  }
65
66  return NumRequiredArgs;
67}
68
69//===----------------------------------------------------------------------===//
70// TemplateDecl Implementation
71//===----------------------------------------------------------------------===//
72
73TemplateDecl::~TemplateDecl() {
74}
75
76//===----------------------------------------------------------------------===//
77// FunctionTemplateDecl Implementation
78//===----------------------------------------------------------------------===//
79
80FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
81                                                   DeclContext *DC,
82                                                   SourceLocation L,
83                                                   DeclarationName Name,
84                                               TemplateParameterList *Params,
85                                                   NamedDecl *Decl) {
86  return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
87}
88
89void FunctionTemplateDecl::Destroy(ASTContext &C) {
90  if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) {
91    for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
92              Spec = CommonPtr->Specializations.begin(),
93           SpecEnd = CommonPtr->Specializations.end();
94         Spec != SpecEnd; ++Spec)
95      C.Deallocate(&*Spec);
96  }
97
98  Decl::Destroy(C);
99}
100
101FunctionTemplateDecl *FunctionTemplateDecl::getCanonicalDecl() {
102  FunctionTemplateDecl *FunTmpl = this;
103  while (FunTmpl->getPreviousDeclaration())
104    FunTmpl = FunTmpl->getPreviousDeclaration();
105  return FunTmpl;
106}
107
108FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() {
109  // Find the first declaration of this function template.
110  FunctionTemplateDecl *First = this;
111  while (First->getPreviousDeclaration())
112    First = First->getPreviousDeclaration();
113
114  if (First->CommonOrPrev.isNull()) {
115    // FIXME: Allocate with the ASTContext
116    First->CommonOrPrev = new Common;
117  }
118  return First->CommonOrPrev.get<Common*>();
119}
120
121//===----------------------------------------------------------------------===//
122// ClassTemplateDecl Implementation
123//===----------------------------------------------------------------------===//
124
125ClassTemplateDecl *ClassTemplateDecl::getCanonicalDecl() {
126  ClassTemplateDecl *Template = this;
127  while (Template->getPreviousDeclaration())
128    Template = Template->getPreviousDeclaration();
129  return Template;
130}
131
132ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
133                                             DeclContext *DC,
134                                             SourceLocation L,
135                                             DeclarationName Name,
136                                             TemplateParameterList *Params,
137                                             NamedDecl *Decl,
138                                             ClassTemplateDecl *PrevDecl) {
139  Common *CommonPtr;
140  if (PrevDecl)
141    CommonPtr = PrevDecl->CommonPtr;
142  else
143    CommonPtr = new (C) Common;
144
145  return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl,
146                                   CommonPtr);
147}
148
149ClassTemplateDecl::~ClassTemplateDecl() {
150  assert(CommonPtr == 0 && "ClassTemplateDecl must be explicitly destroyed");
151}
152
153void ClassTemplateDecl::Destroy(ASTContext& C) {
154  if (!PreviousDeclaration) {
155    CommonPtr->~Common();
156    C.Deallocate((void*)CommonPtr);
157  }
158  CommonPtr = 0;
159
160  this->~ClassTemplateDecl();
161  C.Deallocate((void*)this);
162}
163
164ClassTemplatePartialSpecializationDecl *
165ClassTemplateDecl::findPartialSpecialization(QualType T) {
166  ASTContext &Context = getASTContext();
167  typedef llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
168    partial_spec_iterator;
169  for (partial_spec_iterator P = getPartialSpecializations().begin(),
170                          PEnd = getPartialSpecializations().end();
171       P != PEnd; ++P) {
172    if (Context.hasSameType(Context.getTypeDeclType(&*P), T))
173      return &*P;
174  }
175
176  return 0;
177}
178
179QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
180  if (!CommonPtr->InjectedClassNameType.isNull())
181    return CommonPtr->InjectedClassNameType;
182
183  // FIXME: n2800 14.6.1p1 should say how the template arguments
184  // corresponding to template parameter packs should be pack
185  // expansions. We already say that in 14.6.2.1p2, so it would be
186  // better to fix that redundancy.
187
188  TemplateParameterList *Params = getTemplateParameters();
189  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
190  TemplateArgs.reserve(Params->size());
191  for (TemplateParameterList::iterator Param = Params->begin(),
192                                    ParamEnd = Params->end();
193       Param != ParamEnd; ++Param) {
194    if (isa<TemplateTypeParmDecl>(*Param)) {
195      QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param));
196      TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(),
197                                              ParamType));
198    } else if (NonTypeTemplateParmDecl *NTTP =
199                 dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
200      Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(),
201                                          NTTP->getLocation(),
202                                          NTTP->getType()->isDependentType(),
203                                          /*Value-dependent=*/true);
204      TemplateArgs.push_back(TemplateArgument(E));
205    } else {
206      TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
207      TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP));
208    }
209  }
210
211  CommonPtr->InjectedClassNameType
212    = Context.getTemplateSpecializationType(TemplateName(this),
213                                            &TemplateArgs[0],
214                                            TemplateArgs.size());
215  return CommonPtr->InjectedClassNameType;
216}
217
218//===----------------------------------------------------------------------===//
219// TemplateTypeParm Allocation/Deallocation Method Implementations
220//===----------------------------------------------------------------------===//
221
222TemplateTypeParmDecl *
223TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
224                             SourceLocation L, unsigned D, unsigned P,
225                             IdentifierInfo *Id, bool Typename,
226                             bool ParameterPack) {
227  QualType Type = C.getTemplateTypeParmType(D, P, ParameterPack, Id);
228  return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
229}
230
231//===----------------------------------------------------------------------===//
232// NonTypeTemplateParmDecl Method Implementations
233//===----------------------------------------------------------------------===//
234
235NonTypeTemplateParmDecl *
236NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
237                                SourceLocation L, unsigned D, unsigned P,
238                                IdentifierInfo *Id, QualType T,
239                                DeclaratorInfo *DInfo,
240                                SourceLocation TypeSpecStartLoc) {
241  return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, DInfo,
242                                         TypeSpecStartLoc);
243}
244
245SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
246  return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
247                        : SourceLocation();
248}
249
250//===----------------------------------------------------------------------===//
251// TemplateTemplateParmDecl Method Implementations
252//===----------------------------------------------------------------------===//
253
254TemplateTemplateParmDecl *
255TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
256                                 SourceLocation L, unsigned D, unsigned P,
257                                 IdentifierInfo *Id,
258                                 TemplateParameterList *Params) {
259  return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
260}
261
262SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
263  return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
264                        : SourceLocation();
265}
266
267//===----------------------------------------------------------------------===//
268// TemplateArgument Implementation
269//===----------------------------------------------------------------------===//
270
271TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
272  TypeOrValue = reinterpret_cast<uintptr_t>(E);
273  StartLoc = E->getSourceRange().getBegin();
274}
275
276/// \brief Construct a template argument pack.
277void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
278                                       bool CopyArgs) {
279  assert(isNull() && "Must call setArgumentPack on a null argument");
280
281  Kind = Pack;
282  Args.NumArgs = NumArgs;
283  Args.CopyArgs = CopyArgs;
284  if (!Args.CopyArgs) {
285    Args.Args = args;
286    return;
287  }
288
289  // FIXME: Allocate in ASTContext
290  Args.Args = new TemplateArgument[NumArgs];
291  for (unsigned I = 0; I != Args.NumArgs; ++I)
292    Args.Args[I] = args[I];
293}
294
295//===----------------------------------------------------------------------===//
296// TemplateArgumentListBuilder Implementation
297//===----------------------------------------------------------------------===//
298
299void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) {
300  switch (Arg.getKind()) {
301    default: break;
302    case TemplateArgument::Type:
303      assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
304      break;
305  }
306
307  assert(NumFlatArgs < MaxFlatArgs && "Argument list builder is full!");
308  assert(!StructuredArgs &&
309         "Can't append arguments when an argument pack has been added!");
310
311  if (!FlatArgs)
312    FlatArgs = new TemplateArgument[MaxFlatArgs];
313
314  FlatArgs[NumFlatArgs++] = Arg;
315}
316
317void TemplateArgumentListBuilder::BeginPack() {
318  assert(!AddingToPack && "Already adding to pack!");
319  assert(!StructuredArgs && "Argument list already contains a pack!");
320
321  AddingToPack = true;
322  PackBeginIndex = NumFlatArgs;
323}
324
325void TemplateArgumentListBuilder::EndPack() {
326  assert(AddingToPack && "Not adding to pack!");
327  assert(!StructuredArgs && "Argument list already contains a pack!");
328
329  AddingToPack = false;
330
331  StructuredArgs = new TemplateArgument[MaxStructuredArgs];
332
333  // First copy the flat entries over to the list  (if any)
334  for (unsigned I = 0; I != PackBeginIndex; ++I) {
335    NumStructuredArgs++;
336    StructuredArgs[I] = FlatArgs[I];
337  }
338
339  // Next, set the pack.
340  TemplateArgument *PackArgs = 0;
341  unsigned NumPackArgs = NumFlatArgs - PackBeginIndex;
342  if (NumPackArgs)
343    PackArgs = &FlatArgs[PackBeginIndex];
344
345  StructuredArgs[NumStructuredArgs++].setArgumentPack(PackArgs, NumPackArgs,
346                                                      /*CopyArgs=*/false);
347}
348
349void TemplateArgumentListBuilder::ReleaseArgs() {
350  FlatArgs = 0;
351  NumFlatArgs = 0;
352  MaxFlatArgs = 0;
353  StructuredArgs = 0;
354  NumStructuredArgs = 0;
355  MaxStructuredArgs = 0;
356}
357
358//===----------------------------------------------------------------------===//
359// TemplateArgumentList Implementation
360//===----------------------------------------------------------------------===//
361TemplateArgumentList::TemplateArgumentList(ASTContext &Context,
362                                           TemplateArgumentListBuilder &Builder,
363                                           bool TakeArgs)
364  : FlatArguments(Builder.getFlatArguments(), TakeArgs),
365    NumFlatArguments(Builder.flatSize()),
366    StructuredArguments(Builder.getStructuredArguments(), TakeArgs),
367    NumStructuredArguments(Builder.structuredSize()) {
368
369  if (!TakeArgs)
370    return;
371
372  if (Builder.getStructuredArguments() == Builder.getFlatArguments())
373    StructuredArguments.setInt(0);
374  Builder.ReleaseArgs();
375}
376
377TemplateArgumentList::~TemplateArgumentList() {
378  // FIXME: Deallocate template arguments
379}
380
381//===----------------------------------------------------------------------===//
382// ClassTemplateSpecializationDecl Implementation
383//===----------------------------------------------------------------------===//
384ClassTemplateSpecializationDecl::
385ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK,
386                                DeclContext *DC, SourceLocation L,
387                                ClassTemplateDecl *SpecializedTemplate,
388                                TemplateArgumentListBuilder &Builder,
389                                ClassTemplateSpecializationDecl *PrevDecl)
390  : CXXRecordDecl(DK,
391                  SpecializedTemplate->getTemplatedDecl()->getTagKind(),
392                  DC, L,
393                  // FIXME: Should we use DeclarationName for the name of
394                  // class template specializations?
395                  SpecializedTemplate->getIdentifier(),
396                  PrevDecl),
397    SpecializedTemplate(SpecializedTemplate),
398    TemplateArgs(Context, Builder, /*TakeArgs=*/true),
399    SpecializationKind(TSK_Undeclared) {
400}
401
402ClassTemplateSpecializationDecl *
403ClassTemplateSpecializationDecl::Create(ASTContext &Context,
404                                        DeclContext *DC, SourceLocation L,
405                                        ClassTemplateDecl *SpecializedTemplate,
406                                        TemplateArgumentListBuilder &Builder,
407                                   ClassTemplateSpecializationDecl *PrevDecl) {
408  ClassTemplateSpecializationDecl *Result
409    = new (Context)ClassTemplateSpecializationDecl(Context,
410                                                   ClassTemplateSpecialization,
411                                                   DC, L,
412                                                   SpecializedTemplate,
413                                                   Builder,
414                                                   PrevDecl);
415  Context.getTypeDeclType(Result, PrevDecl);
416  return Result;
417}
418
419void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) {
420  if (SpecializedPartialSpecialization *PartialSpec
421        = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
422    C.Deallocate(PartialSpec);
423
424  CXXRecordDecl::Destroy(C);
425}
426
427ClassTemplateDecl *
428ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
429  if (SpecializedPartialSpecialization *PartialSpec
430      = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
431    return PartialSpec->PartialSpecialization->getSpecializedTemplate();
432  return SpecializedTemplate.get<ClassTemplateDecl*>();
433}
434
435//===----------------------------------------------------------------------===//
436// ClassTemplatePartialSpecializationDecl Implementation
437//===----------------------------------------------------------------------===//
438ClassTemplatePartialSpecializationDecl *
439ClassTemplatePartialSpecializationDecl::
440Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
441       TemplateParameterList *Params,
442       ClassTemplateDecl *SpecializedTemplate,
443       TemplateArgumentListBuilder &Builder,
444       ClassTemplatePartialSpecializationDecl *PrevDecl) {
445  ClassTemplatePartialSpecializationDecl *Result
446    = new (Context)ClassTemplatePartialSpecializationDecl(Context,
447                                                          DC, L, Params,
448                                                          SpecializedTemplate,
449                                                          Builder, PrevDecl);
450  Result->setSpecializationKind(TSK_ExplicitSpecialization);
451  Context.getTypeDeclType(Result, PrevDecl);
452  return Result;
453}
454