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"
20 using namespace clang;
21 
22 //===----------------------------------------------------------------------===//
23 // TemplateParameterList Implementation
24 //===----------------------------------------------------------------------===//
25 
26 TemplateParameterList::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 
36 TemplateParameterList *
37 TemplateParameterList::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 
47 unsigned 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 
73 TemplateDecl::~TemplateDecl() {
74 }
75 
76 //===----------------------------------------------------------------------===//
77 // FunctionTemplateDecl Implementation
78 //===----------------------------------------------------------------------===//
79 
80 FunctionTemplateDecl *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 
89 void 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 
101 FunctionTemplateDecl *FunctionTemplateDecl::getCanonicalDecl() {
102   FunctionTemplateDecl *FunTmpl = this;
103   while (FunTmpl->getPreviousDeclaration())
104     FunTmpl = FunTmpl->getPreviousDeclaration();
105   return FunTmpl;
106 }
107 
108 FunctionTemplateDecl::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 
125 ClassTemplateDecl *ClassTemplateDecl::getCanonicalDecl() {
126   ClassTemplateDecl *Template = this;
127   while (Template->getPreviousDeclaration())
128     Template = Template->getPreviousDeclaration();
129   return Template;
130 }
131 
132 ClassTemplateDecl *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 
149 ClassTemplateDecl::~ClassTemplateDecl() {
150   assert(CommonPtr == 0 && "ClassTemplateDecl must be explicitly destroyed");
151 }
152 
153 void 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 
164 ClassTemplatePartialSpecializationDecl *
165 ClassTemplateDecl::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 
179 QualType 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 
222 TemplateTypeParmDecl *
223 TemplateTypeParmDecl::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 
235 NonTypeTemplateParmDecl *
236 NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
237                                 SourceLocation L, unsigned D, unsigned P,
238                                 IdentifierInfo *Id, QualType T,
239                                 SourceLocation TypeSpecStartLoc) {
240   return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T,
241                                          TypeSpecStartLoc);
242 }
243 
244 SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
245   return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
246                         : SourceLocation();
247 }
248 
249 //===----------------------------------------------------------------------===//
250 // TemplateTemplateParmDecl Method Implementations
251 //===----------------------------------------------------------------------===//
252 
253 TemplateTemplateParmDecl *
254 TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
255                                  SourceLocation L, unsigned D, unsigned P,
256                                  IdentifierInfo *Id,
257                                  TemplateParameterList *Params) {
258   return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
259 }
260 
261 SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
262   return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
263                         : SourceLocation();
264 }
265 
266 //===----------------------------------------------------------------------===//
267 // TemplateArgument Implementation
268 //===----------------------------------------------------------------------===//
269 
270 TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
271   TypeOrValue = reinterpret_cast<uintptr_t>(E);
272   StartLoc = E->getSourceRange().getBegin();
273 }
274 
275 /// \brief Construct a template argument pack.
276 void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
277                                        bool CopyArgs) {
278   assert(isNull() && "Must call setArgumentPack on a null argument");
279 
280   Kind = Pack;
281   Args.NumArgs = NumArgs;
282   Args.CopyArgs = CopyArgs;
283   if (!Args.CopyArgs) {
284     Args.Args = args;
285     return;
286   }
287 
288   // FIXME: Allocate in ASTContext
289   Args.Args = new TemplateArgument[NumArgs];
290   for (unsigned I = 0; I != Args.NumArgs; ++I)
291     Args.Args[I] = args[I];
292 }
293 
294 //===----------------------------------------------------------------------===//
295 // TemplateArgumentListBuilder Implementation
296 //===----------------------------------------------------------------------===//
297 
298 void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) {
299   switch (Arg.getKind()) {
300     default: break;
301     case TemplateArgument::Type:
302       assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
303       break;
304   }
305 
306   assert(NumFlatArgs < MaxFlatArgs && "Argument list builder is full!");
307   assert(!StructuredArgs &&
308          "Can't append arguments when an argument pack has been added!");
309 
310   if (!FlatArgs)
311     FlatArgs = new TemplateArgument[MaxFlatArgs];
312 
313   FlatArgs[NumFlatArgs++] = Arg;
314 }
315 
316 void TemplateArgumentListBuilder::BeginPack() {
317   assert(!AddingToPack && "Already adding to pack!");
318   assert(!StructuredArgs && "Argument list already contains a pack!");
319 
320   AddingToPack = true;
321   PackBeginIndex = NumFlatArgs;
322 }
323 
324 void TemplateArgumentListBuilder::EndPack() {
325   assert(AddingToPack && "Not adding to pack!");
326   assert(!StructuredArgs && "Argument list already contains a pack!");
327 
328   AddingToPack = false;
329 
330   StructuredArgs = new TemplateArgument[MaxStructuredArgs];
331 
332   // First copy the flat entries over to the list  (if any)
333   for (unsigned I = 0; I != PackBeginIndex; ++I) {
334     NumStructuredArgs++;
335     StructuredArgs[I] = FlatArgs[I];
336   }
337 
338   // Next, set the pack.
339   TemplateArgument *PackArgs = 0;
340   unsigned NumPackArgs = NumFlatArgs - PackBeginIndex;
341   if (NumPackArgs)
342     PackArgs = &FlatArgs[PackBeginIndex];
343 
344   StructuredArgs[NumStructuredArgs++].setArgumentPack(PackArgs, NumPackArgs,
345                                                       /*CopyArgs=*/false);
346 }
347 
348 void TemplateArgumentListBuilder::ReleaseArgs() {
349   FlatArgs = 0;
350   NumFlatArgs = 0;
351   MaxFlatArgs = 0;
352   StructuredArgs = 0;
353   NumStructuredArgs = 0;
354   MaxStructuredArgs = 0;
355 }
356 
357 //===----------------------------------------------------------------------===//
358 // TemplateArgumentList Implementation
359 //===----------------------------------------------------------------------===//
360 TemplateArgumentList::TemplateArgumentList(ASTContext &Context,
361                                            TemplateArgumentListBuilder &Builder,
362                                            bool TakeArgs)
363   : FlatArguments(Builder.getFlatArguments(), TakeArgs),
364     NumFlatArguments(Builder.flatSize()),
365     StructuredArguments(Builder.getStructuredArguments(), TakeArgs),
366     NumStructuredArguments(Builder.structuredSize()) {
367 
368   if (!TakeArgs)
369     return;
370 
371   if (Builder.getStructuredArguments() == Builder.getFlatArguments())
372     StructuredArguments.setInt(0);
373   Builder.ReleaseArgs();
374 }
375 
376 TemplateArgumentList::~TemplateArgumentList() {
377   // FIXME: Deallocate template arguments
378 }
379 
380 //===----------------------------------------------------------------------===//
381 // ClassTemplateSpecializationDecl Implementation
382 //===----------------------------------------------------------------------===//
383 ClassTemplateSpecializationDecl::
384 ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK,
385                                 DeclContext *DC, SourceLocation L,
386                                 ClassTemplateDecl *SpecializedTemplate,
387                                 TemplateArgumentListBuilder &Builder,
388                                 ClassTemplateSpecializationDecl *PrevDecl)
389   : CXXRecordDecl(DK,
390                   SpecializedTemplate->getTemplatedDecl()->getTagKind(),
391                   DC, L,
392                   // FIXME: Should we use DeclarationName for the name of
393                   // class template specializations?
394                   SpecializedTemplate->getIdentifier(),
395                   PrevDecl),
396     SpecializedTemplate(SpecializedTemplate),
397     TemplateArgs(Context, Builder, /*TakeArgs=*/true),
398     SpecializationKind(TSK_Undeclared) {
399 }
400 
401 ClassTemplateSpecializationDecl *
402 ClassTemplateSpecializationDecl::Create(ASTContext &Context,
403                                         DeclContext *DC, SourceLocation L,
404                                         ClassTemplateDecl *SpecializedTemplate,
405                                         TemplateArgumentListBuilder &Builder,
406                                    ClassTemplateSpecializationDecl *PrevDecl) {
407   ClassTemplateSpecializationDecl *Result
408     = new (Context)ClassTemplateSpecializationDecl(Context,
409                                                    ClassTemplateSpecialization,
410                                                    DC, L,
411                                                    SpecializedTemplate,
412                                                    Builder,
413                                                    PrevDecl);
414   Context.getTypeDeclType(Result, PrevDecl);
415   return Result;
416 }
417 
418 void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) {
419   if (SpecializedPartialSpecialization *PartialSpec
420         = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
421     C.Deallocate(PartialSpec);
422 
423   CXXRecordDecl::Destroy(C);
424 }
425 
426 ClassTemplateDecl *
427 ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
428   if (SpecializedPartialSpecialization *PartialSpec
429       = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
430     return PartialSpec->PartialSpecialization->getSpecializedTemplate();
431   return SpecializedTemplate.get<ClassTemplateDecl*>();
432 }
433 
434 //===----------------------------------------------------------------------===//
435 // ClassTemplatePartialSpecializationDecl Implementation
436 //===----------------------------------------------------------------------===//
437 ClassTemplatePartialSpecializationDecl *
438 ClassTemplatePartialSpecializationDecl::
439 Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
440        TemplateParameterList *Params,
441        ClassTemplateDecl *SpecializedTemplate,
442        TemplateArgumentListBuilder &Builder,
443        ClassTemplatePartialSpecializationDecl *PrevDecl) {
444   ClassTemplatePartialSpecializationDecl *Result
445     = new (Context)ClassTemplatePartialSpecializationDecl(Context,
446                                                           DC, L, Params,
447                                                           SpecializedTemplate,
448                                                           Builder, PrevDecl);
449   Result->setSpecializationKind(TSK_ExplicitSpecialization);
450   Context.getTypeDeclType(Result, PrevDecl);
451   return Result;
452 }
453