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     if (!(isa<TemplateTypeParmDecl>(*Param) &&
54           cast<TemplateTypeParmDecl>(*Param)->hasDefaultArgument()) &&
55         !(isa<NonTypeTemplateParmDecl>(*Param) &&
56           cast<NonTypeTemplateParmDecl>(*Param)->hasDefaultArgument()) &&
57         !(isa<TemplateTemplateParmDecl>(*Param) &&
58           cast<TemplateTemplateParmDecl>(*Param)->hasDefaultArgument()))
59       break;
60 
61     --NumRequiredArgs;
62   }
63 
64   return NumRequiredArgs;
65 }
66 
67 //===----------------------------------------------------------------------===//
68 // TemplateDecl Implementation
69 //===----------------------------------------------------------------------===//
70 
71 TemplateDecl::~TemplateDecl() {
72 }
73 
74 //===----------------------------------------------------------------------===//
75 // FunctionTemplateDecl Implementation
76 //===----------------------------------------------------------------------===//
77 
78 FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
79                                                    DeclContext *DC,
80                                                    SourceLocation L,
81                                                    DeclarationName Name,
82                                                    TemplateParameterList *Params,
83                                                    NamedDecl *Decl) {
84   return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
85 }
86 
87 //===----------------------------------------------------------------------===//
88 // ClassTemplateDecl Implementation
89 //===----------------------------------------------------------------------===//
90 
91 ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
92                                              DeclContext *DC,
93                                              SourceLocation L,
94                                              DeclarationName Name,
95                                              TemplateParameterList *Params,
96                                              NamedDecl *Decl,
97                                              ClassTemplateDecl *PrevDecl) {
98   Common *CommonPtr;
99   if (PrevDecl)
100     CommonPtr = PrevDecl->CommonPtr;
101   else
102     CommonPtr = new (C) Common;
103 
104   return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl,
105                                    CommonPtr);
106 }
107 
108 ClassTemplateDecl::~ClassTemplateDecl() {
109   assert(CommonPtr == 0 && "ClassTemplateDecl must be explicitly destroyed");
110 }
111 
112 void ClassTemplateDecl::Destroy(ASTContext& C) {
113   if (!PreviousDeclaration) {
114     CommonPtr->~Common();
115     C.Deallocate((void*)CommonPtr);
116   }
117   CommonPtr = 0;
118 
119   this->~ClassTemplateDecl();
120   C.Deallocate((void*)this);
121 }
122 
123 QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
124   if (!CommonPtr->InjectedClassNameType.isNull())
125     return CommonPtr->InjectedClassNameType;
126 
127   // FIXME: n2800 14.6.1p1 should say how the template arguments
128   // corresponding to template parameter packs should be pack
129   // expansions. We already say that in 14.6.2.1p2, so it would be
130   // better to fix that redundancy.
131 
132   TemplateParameterList *Params = getTemplateParameters();
133 
134   llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
135   llvm::SmallVector<TemplateArgument, 16> CanonTemplateArgs;
136   TemplateArgs.reserve(Params->size());
137   CanonTemplateArgs.reserve(Params->size());
138 
139   for (TemplateParameterList::iterator
140          Param = Params->begin(), ParamEnd = Params->end();
141        Param != ParamEnd; ++Param) {
142     if (isa<TemplateTypeParmDecl>(*Param)) {
143       QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param));
144       TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(),
145                                               ParamType));
146       CanonTemplateArgs.push_back(
147                          TemplateArgument((*Param)->getLocation(),
148                                           Context.getCanonicalType(ParamType)));
149     } else if (NonTypeTemplateParmDecl *NTTP =
150                  dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
151       // FIXME: Build canonical expression, too!
152       Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(),
153                                           NTTP->getLocation(),
154                                           NTTP->getType()->isDependentType(),
155                                           /*Value-dependent=*/true);
156       TemplateArgs.push_back(TemplateArgument(E));
157       CanonTemplateArgs.push_back(TemplateArgument(E));
158     } else {
159       TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
160       TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP));
161       CanonTemplateArgs.push_back(TemplateArgument(TTP->getLocation(),
162                                               Context.getCanonicalDecl(TTP)));
163     }
164   }
165 
166   // FIXME: I should really move the "build-the-canonical-type" logic
167   // into ASTContext::getTemplateSpecializationType.
168   TemplateName Name = TemplateName(this);
169   QualType CanonType = Context.getTemplateSpecializationType(
170                                        Context.getCanonicalTemplateName(Name),
171                                              &CanonTemplateArgs[0],
172                                              CanonTemplateArgs.size());
173 
174   CommonPtr->InjectedClassNameType
175     = Context.getTemplateSpecializationType(Name,
176                                             &TemplateArgs[0],
177                                             TemplateArgs.size(),
178                                             CanonType);
179   return CommonPtr->InjectedClassNameType;
180 }
181 
182 //===----------------------------------------------------------------------===//
183 // TemplateTypeParm Allocation/Deallocation Method Implementations
184 //===----------------------------------------------------------------------===//
185 
186 TemplateTypeParmDecl *
187 TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
188                              SourceLocation L, unsigned D, unsigned P,
189                              IdentifierInfo *Id, bool Typename) {
190   QualType Type = C.getTemplateTypeParmType(D, P, Id);
191   return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type);
192 }
193 
194 //===----------------------------------------------------------------------===//
195 // NonTypeTemplateParmDecl Method Implementations
196 //===----------------------------------------------------------------------===//
197 
198 NonTypeTemplateParmDecl *
199 NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
200                                 SourceLocation L, unsigned D, unsigned P,
201                                 IdentifierInfo *Id, QualType T,
202                                 SourceLocation TypeSpecStartLoc) {
203   return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T,
204                                          TypeSpecStartLoc);
205 }
206 
207 SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
208   return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
209                         : SourceLocation();
210 }
211 
212 //===----------------------------------------------------------------------===//
213 // TemplateTemplateParmDecl Method Implementations
214 //===----------------------------------------------------------------------===//
215 
216 TemplateTemplateParmDecl *
217 TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
218                                  SourceLocation L, unsigned D, unsigned P,
219                                  IdentifierInfo *Id,
220                                  TemplateParameterList *Params) {
221   return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
222 }
223 
224 SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
225   return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
226                         : SourceLocation();
227 }
228 
229 //===----------------------------------------------------------------------===//
230 // TemplateArgument Implementation
231 //===----------------------------------------------------------------------===//
232 
233 TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
234   TypeOrValue = reinterpret_cast<uintptr_t>(E);
235   StartLoc = E->getSourceRange().getBegin();
236 }
237 
238 //===----------------------------------------------------------------------===//
239 // TemplateArgumentListBuilder Implementation
240 //===----------------------------------------------------------------------===//
241 void TemplateArgumentListBuilder::push_back(const TemplateArgument& Arg) {
242   switch (Arg.getKind()) {
243   default: break;
244   case TemplateArgument::Type:
245     assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
246     break;
247   }
248 
249   Args.push_back(Arg);
250 }
251 
252 //===----------------------------------------------------------------------===//
253 // TemplateArgumentList Implementation
254 //===----------------------------------------------------------------------===//
255 TemplateArgumentList::TemplateArgumentList(ASTContext &Context,
256                                            TemplateArgumentListBuilder &Builder,
257                                            bool CopyArgs, bool FlattenArgs)
258   : NumArguments(Builder.flatSize()) {
259   if (!CopyArgs) {
260     Arguments.setPointer(Builder.getFlatArgumentList());
261     Arguments.setInt(1);
262     return;
263   }
264 
265 
266   unsigned Size = sizeof(TemplateArgument) * Builder.flatSize();
267   unsigned Align = llvm::AlignOf<TemplateArgument>::Alignment;
268   void *Mem = Context.Allocate(Size, Align);
269   Arguments.setPointer((TemplateArgument *)Mem);
270   Arguments.setInt(0);
271 
272   TemplateArgument *Args = (TemplateArgument *)Mem;
273   for (unsigned I = 0; I != NumArguments; ++I)
274     new (Args + I) TemplateArgument(Builder.getFlatArgumentList()[I]);
275 }
276 
277 TemplateArgumentList::~TemplateArgumentList() {
278   // FIXME: Deallocate template arguments
279 }
280 
281 //===----------------------------------------------------------------------===//
282 // ClassTemplateSpecializationDecl Implementation
283 //===----------------------------------------------------------------------===//
284 ClassTemplateSpecializationDecl::
285 ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK,
286                                 DeclContext *DC, SourceLocation L,
287                                 ClassTemplateDecl *SpecializedTemplate,
288                                 TemplateArgumentListBuilder &Builder)
289   : CXXRecordDecl(DK,
290                   SpecializedTemplate->getTemplatedDecl()->getTagKind(),
291                   DC, L,
292                   // FIXME: Should we use DeclarationName for the name of
293                   // class template specializations?
294                   SpecializedTemplate->getIdentifier()),
295     SpecializedTemplate(SpecializedTemplate),
296     TemplateArgs(Context, Builder, /*CopyArgs=*/true, /*FlattenArgs=*/true),
297     SpecializationKind(TSK_Undeclared) {
298 }
299 
300 ClassTemplateSpecializationDecl *
301 ClassTemplateSpecializationDecl::Create(ASTContext &Context,
302                                         DeclContext *DC, SourceLocation L,
303                                         ClassTemplateDecl *SpecializedTemplate,
304                                         TemplateArgumentListBuilder &Builder,
305                                    ClassTemplateSpecializationDecl *PrevDecl) {
306   ClassTemplateSpecializationDecl *Result
307     = new (Context)ClassTemplateSpecializationDecl(Context,
308                                                    ClassTemplateSpecialization,
309                                                    DC, L,
310                                                    SpecializedTemplate,
311                                                    Builder);
312   Context.getTypeDeclType(Result, PrevDecl);
313   return Result;
314 }
315 
316 //===----------------------------------------------------------------------===//
317 // ClassTemplatePartialSpecializationDecl Implementation
318 //===----------------------------------------------------------------------===//
319 ClassTemplatePartialSpecializationDecl *
320 ClassTemplatePartialSpecializationDecl::
321 Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
322        TemplateParameterList *Params,
323        ClassTemplateDecl *SpecializedTemplate,
324        TemplateArgumentListBuilder &Builder,
325        ClassTemplatePartialSpecializationDecl *PrevDecl) {
326   ClassTemplatePartialSpecializationDecl *Result
327     = new (Context)ClassTemplatePartialSpecializationDecl(Context,
328                                                           DC, L, Params,
329                                                           SpecializedTemplate,
330                                                           Builder);
331   Result->setSpecializationKind(TSK_ExplicitSpecialization);
332   Context.getTypeDeclType(Result, PrevDecl);
333   return Result;
334 }
335