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::Common *FunctionTemplateDecl::getCommonPtr() {
102   // Find the first declaration of this function template.
103   FunctionTemplateDecl *First = this;
104   while (First->getPreviousDeclaration())
105     First = First->getPreviousDeclaration();
106 
107   if (First->CommonOrPrev.isNull()) {
108     // FIXME: Allocate with the ASTContext
109     First->CommonOrPrev = new Common;
110   }
111   return First->CommonOrPrev.get<Common*>();
112 }
113 
114 //===----------------------------------------------------------------------===//
115 // ClassTemplateDecl Implementation
116 //===----------------------------------------------------------------------===//
117 
118 ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
119                                              DeclContext *DC,
120                                              SourceLocation L,
121                                              DeclarationName Name,
122                                              TemplateParameterList *Params,
123                                              NamedDecl *Decl,
124                                              ClassTemplateDecl *PrevDecl) {
125   Common *CommonPtr;
126   if (PrevDecl)
127     CommonPtr = PrevDecl->CommonPtr;
128   else
129     CommonPtr = new (C) Common;
130 
131   return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl,
132                                    CommonPtr);
133 }
134 
135 ClassTemplateDecl::~ClassTemplateDecl() {
136   assert(CommonPtr == 0 && "ClassTemplateDecl must be explicitly destroyed");
137 }
138 
139 void ClassTemplateDecl::Destroy(ASTContext& C) {
140   if (!PreviousDeclaration) {
141     CommonPtr->~Common();
142     C.Deallocate((void*)CommonPtr);
143   }
144   CommonPtr = 0;
145 
146   this->~ClassTemplateDecl();
147   C.Deallocate((void*)this);
148 }
149 
150 QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
151   if (!CommonPtr->InjectedClassNameType.isNull())
152     return CommonPtr->InjectedClassNameType;
153 
154   // FIXME: n2800 14.6.1p1 should say how the template arguments
155   // corresponding to template parameter packs should be pack
156   // expansions. We already say that in 14.6.2.1p2, so it would be
157   // better to fix that redundancy.
158 
159   TemplateParameterList *Params = getTemplateParameters();
160 
161   llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
162   llvm::SmallVector<TemplateArgument, 16> CanonTemplateArgs;
163   TemplateArgs.reserve(Params->size());
164   CanonTemplateArgs.reserve(Params->size());
165 
166   for (TemplateParameterList::iterator
167          Param = Params->begin(), ParamEnd = Params->end();
168        Param != ParamEnd; ++Param) {
169     if (isa<TemplateTypeParmDecl>(*Param)) {
170       QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param));
171       TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(),
172                                               ParamType));
173       CanonTemplateArgs.push_back(
174                          TemplateArgument((*Param)->getLocation(),
175                                           Context.getCanonicalType(ParamType)));
176     } else if (NonTypeTemplateParmDecl *NTTP =
177                  dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
178       // FIXME: Build canonical expression, too!
179       Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(),
180                                           NTTP->getLocation(),
181                                           NTTP->getType()->isDependentType(),
182                                           /*Value-dependent=*/true);
183       TemplateArgs.push_back(TemplateArgument(E));
184       CanonTemplateArgs.push_back(TemplateArgument(E));
185     } else {
186       TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
187       TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP));
188       CanonTemplateArgs.push_back(TemplateArgument(TTP->getLocation(),
189                                               Context.getCanonicalDecl(TTP)));
190     }
191   }
192 
193   // FIXME: I should really move the "build-the-canonical-type" logic
194   // into ASTContext::getTemplateSpecializationType.
195   TemplateName Name = TemplateName(this);
196   QualType CanonType = Context.getTemplateSpecializationType(
197                                        Context.getCanonicalTemplateName(Name),
198                                              &CanonTemplateArgs[0],
199                                              CanonTemplateArgs.size());
200 
201   CommonPtr->InjectedClassNameType
202     = Context.getTemplateSpecializationType(Name,
203                                             &TemplateArgs[0],
204                                             TemplateArgs.size(),
205                                             CanonType);
206   return CommonPtr->InjectedClassNameType;
207 }
208 
209 //===----------------------------------------------------------------------===//
210 // TemplateTypeParm Allocation/Deallocation Method Implementations
211 //===----------------------------------------------------------------------===//
212 
213 TemplateTypeParmDecl *
214 TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
215                              SourceLocation L, unsigned D, unsigned P,
216                              IdentifierInfo *Id, bool Typename,
217                              bool ParameterPack) {
218   QualType Type = C.getTemplateTypeParmType(D, P, ParameterPack, Id);
219   return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
220 }
221 
222 //===----------------------------------------------------------------------===//
223 // NonTypeTemplateParmDecl Method Implementations
224 //===----------------------------------------------------------------------===//
225 
226 NonTypeTemplateParmDecl *
227 NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
228                                 SourceLocation L, unsigned D, unsigned P,
229                                 IdentifierInfo *Id, QualType T,
230                                 SourceLocation TypeSpecStartLoc) {
231   return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T,
232                                          TypeSpecStartLoc);
233 }
234 
235 SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
236   return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
237                         : SourceLocation();
238 }
239 
240 //===----------------------------------------------------------------------===//
241 // TemplateTemplateParmDecl Method Implementations
242 //===----------------------------------------------------------------------===//
243 
244 TemplateTemplateParmDecl *
245 TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
246                                  SourceLocation L, unsigned D, unsigned P,
247                                  IdentifierInfo *Id,
248                                  TemplateParameterList *Params) {
249   return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
250 }
251 
252 SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
253   return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
254                         : SourceLocation();
255 }
256 
257 //===----------------------------------------------------------------------===//
258 // TemplateArgument Implementation
259 //===----------------------------------------------------------------------===//
260 
261 TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
262   TypeOrValue = reinterpret_cast<uintptr_t>(E);
263   StartLoc = E->getSourceRange().getBegin();
264 }
265 
266 /// \brief Construct a template argument pack.
267 void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
268                                        bool CopyArgs) {
269   assert(isNull() && "Must call setArgumentPack on a null argument");
270 
271   Kind = Pack;
272   Args.NumArgs = NumArgs;
273   Args.CopyArgs = CopyArgs;
274   if (!Args.CopyArgs) {
275     Args.Args = args;
276     return;
277   }
278 
279   Args.Args = new TemplateArgument[NumArgs];
280   for (unsigned I = 0; I != Args.NumArgs; ++I)
281     Args.Args[I] = args[I];
282 }
283 
284 //===----------------------------------------------------------------------===//
285 // TemplateArgumentListBuilder Implementation
286 //===----------------------------------------------------------------------===//
287 
288 void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) {
289   switch (Arg.getKind()) {
290     default: break;
291     case TemplateArgument::Type:
292       assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
293       break;
294   }
295 
296   assert(NumFlatArgs < MaxFlatArgs && "Argument list builder is full!");
297   assert(!StructuredArgs &&
298          "Can't append arguments when an argument pack has been added!");
299 
300   if (!FlatArgs)
301     FlatArgs = new TemplateArgument[MaxFlatArgs];
302 
303   FlatArgs[NumFlatArgs++] = Arg;
304 }
305 
306 void TemplateArgumentListBuilder::BeginPack() {
307   assert(!AddingToPack && "Already adding to pack!");
308   assert(!StructuredArgs && "Argument list already contains a pack!");
309 
310   AddingToPack = true;
311   PackBeginIndex = NumFlatArgs;
312 }
313 
314 void TemplateArgumentListBuilder::EndPack() {
315   assert(AddingToPack && "Not adding to pack!");
316   assert(!StructuredArgs && "Argument list already contains a pack!");
317 
318   AddingToPack = false;
319 
320   StructuredArgs = new TemplateArgument[MaxStructuredArgs];
321 
322   // First copy the flat entries over to the list  (if any)
323   for (unsigned I = 0; I != PackBeginIndex; ++I) {
324     NumStructuredArgs++;
325     StructuredArgs[I] = FlatArgs[I];
326   }
327 
328   // Next, set the pack.
329   TemplateArgument *PackArgs = 0;
330   unsigned NumPackArgs = NumFlatArgs - PackBeginIndex;
331   if (NumPackArgs)
332     PackArgs = &FlatArgs[PackBeginIndex];
333 
334   StructuredArgs[NumStructuredArgs++].setArgumentPack(PackArgs, NumPackArgs,
335                                                       /*CopyArgs=*/false);
336 }
337 
338 void TemplateArgumentListBuilder::ReleaseArgs() {
339   FlatArgs = 0;
340   NumFlatArgs = 0;
341   MaxFlatArgs = 0;
342   StructuredArgs = 0;
343   NumStructuredArgs = 0;
344   MaxStructuredArgs = 0;
345 }
346 
347 //===----------------------------------------------------------------------===//
348 // TemplateArgumentList Implementation
349 //===----------------------------------------------------------------------===//
350 TemplateArgumentList::TemplateArgumentList(ASTContext &Context,
351                                            TemplateArgumentListBuilder &Builder,
352                                            bool TakeArgs)
353   : FlatArguments(Builder.getFlatArguments(), TakeArgs),
354     NumFlatArguments(Builder.flatSize()),
355     StructuredArguments(Builder.getStructuredArguments(), TakeArgs),
356     NumStructuredArguments(Builder.structuredSize()) {
357 
358   if (!TakeArgs)
359     return;
360 
361   if (Builder.getStructuredArguments() == Builder.getFlatArguments())
362     StructuredArguments.setInt(0);
363   Builder.ReleaseArgs();
364 }
365 
366 TemplateArgumentList::~TemplateArgumentList() {
367   // FIXME: Deallocate template arguments
368 }
369 
370 //===----------------------------------------------------------------------===//
371 // ClassTemplateSpecializationDecl Implementation
372 //===----------------------------------------------------------------------===//
373 ClassTemplateSpecializationDecl::
374 ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK,
375                                 DeclContext *DC, SourceLocation L,
376                                 ClassTemplateDecl *SpecializedTemplate,
377                                 TemplateArgumentListBuilder &Builder)
378   : CXXRecordDecl(DK,
379                   SpecializedTemplate->getTemplatedDecl()->getTagKind(),
380                   DC, L,
381                   // FIXME: Should we use DeclarationName for the name of
382                   // class template specializations?
383                   SpecializedTemplate->getIdentifier()),
384     SpecializedTemplate(SpecializedTemplate),
385     TemplateArgs(Context, Builder, /*TakeArgs=*/true),
386     SpecializationKind(TSK_Undeclared) {
387 }
388 
389 ClassTemplateSpecializationDecl *
390 ClassTemplateSpecializationDecl::Create(ASTContext &Context,
391                                         DeclContext *DC, SourceLocation L,
392                                         ClassTemplateDecl *SpecializedTemplate,
393                                         TemplateArgumentListBuilder &Builder,
394                                    ClassTemplateSpecializationDecl *PrevDecl) {
395   ClassTemplateSpecializationDecl *Result
396     = new (Context)ClassTemplateSpecializationDecl(Context,
397                                                    ClassTemplateSpecialization,
398                                                    DC, L,
399                                                    SpecializedTemplate,
400                                                    Builder);
401   Context.getTypeDeclType(Result, PrevDecl);
402   return Result;
403 }
404 
405 //===----------------------------------------------------------------------===//
406 // ClassTemplatePartialSpecializationDecl Implementation
407 //===----------------------------------------------------------------------===//
408 ClassTemplatePartialSpecializationDecl *
409 ClassTemplatePartialSpecializationDecl::
410 Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
411        TemplateParameterList *Params,
412        ClassTemplateDecl *SpecializedTemplate,
413        TemplateArgumentListBuilder &Builder,
414        ClassTemplatePartialSpecializationDecl *PrevDecl) {
415   ClassTemplatePartialSpecializationDecl *Result
416     = new (Context)ClassTemplatePartialSpecializationDecl(Context,
417                                                           DC, L, Params,
418                                                           SpecializedTemplate,
419                                                           Builder);
420   Result->setSpecializationKind(TSK_ExplicitSpecialization);
421   Context.getTypeDeclType(Result, PrevDecl);
422   return Result;
423 }
424