blob: b7a8f7a515b2447c5005795dd9da42d223e817d5 [file] [log] [blame]
Douglas Gregor8dbc2692009-03-17 21:15:40 +00001//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/
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// This file implements C++ template instantiation for declarations.
10//
11//===----------------------------------------------------------------------===/
12#include "Sema.h"
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/DeclTemplate.h"
15#include "clang/AST/DeclVisitor.h"
16#include "clang/AST/Expr.h"
17#include "llvm/Support/Compiler.h"
18
19using namespace clang;
20
21namespace {
22 class VISIBILITY_HIDDEN TemplateDeclInstantiator
23 : public DeclVisitor<TemplateDeclInstantiator, Decl *>
24 {
25 Sema &SemaRef;
26 DeclContext *Owner;
27 const TemplateArgument *TemplateArgs;
28 unsigned NumTemplateArgs;
29
30 public:
31 typedef Sema::OwningExprResult OwningExprResult;
32
33 TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
34 const TemplateArgument *TemplateArgs,
35 unsigned NumTemplateArgs)
36 : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs),
37 NumTemplateArgs(NumTemplateArgs) { }
38
39 // FIXME: Once we get closer to completion, replace these
40 // manually-written declarations with automatically-generated ones
41 // from clang/AST/DeclNodes.def.
42 Decl *VisitTypedefDecl(TypedefDecl *D);
43 Decl *VisitFieldDecl(FieldDecl *D);
44 Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
45 Decl *VisitEnumDecl(EnumDecl *D);
Douglas Gregor2dc0e642009-03-23 23:06:20 +000046 Decl *VisitCXXMethodDecl(CXXMethodDecl *D);
Douglas Gregor03b2b072009-03-24 00:15:49 +000047 Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
Douglas Gregor2dc0e642009-03-23 23:06:20 +000048 Decl *VisitParmVarDecl(ParmVarDecl *D);
49 Decl *VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
Douglas Gregor5545e162009-03-24 00:38:23 +000050
Douglas Gregor8dbc2692009-03-17 21:15:40 +000051 // Base case. FIXME: Remove once we can instantiate everything.
52 Decl *VisitDecl(Decl *) {
53 return 0;
54 }
Douglas Gregor5545e162009-03-24 00:38:23 +000055
56 // Helper functions for instantiating methods.
57 QualType InstantiateFunctionType(FunctionDecl *D,
58 llvm::SmallVectorImpl<ParmVarDecl *> &Params);
59 bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
Douglas Gregor8dbc2692009-03-17 21:15:40 +000060 };
61}
62
63Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
64 bool Invalid = false;
65 QualType T = D->getUnderlyingType();
66 if (T->isDependentType()) {
67 T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
68 D->getLocation(),
69 D->getDeclName());
70 if (T.isNull()) {
71 Invalid = true;
72 T = SemaRef.Context.IntTy;
73 }
74 }
75
76 // Create the new typedef
77 TypedefDecl *Typedef
78 = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(),
79 D->getIdentifier(), T);
80 if (Invalid)
81 Typedef->setInvalidDecl();
82
83 Owner->addDecl(Typedef);
84 return Typedef;
85}
86
87Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
88 bool Invalid = false;
89 QualType T = D->getType();
90 if (T->isDependentType()) {
91 T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
92 D->getLocation(),
93 D->getDeclName());
94 if (!T.isNull() && T->isFunctionType()) {
95 // C++ [temp.arg.type]p3:
96 // If a declaration acquires a function type through a type
97 // dependent on a template-parameter and this causes a
98 // declaration that does not use the syntactic form of a
99 // function declarator to have function type, the program is
100 // ill-formed.
101 SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
102 << T;
103 T = QualType();
104 Invalid = true;
105 }
106 }
107
108 Expr *BitWidth = D->getBitWidth();
109 if (Invalid)
110 BitWidth = 0;
111 else if (BitWidth) {
112 OwningExprResult InstantiatedBitWidth
113 = SemaRef.InstantiateExpr(BitWidth, TemplateArgs, NumTemplateArgs);
114 if (InstantiatedBitWidth.isInvalid()) {
115 Invalid = true;
116 BitWidth = 0;
117 } else
118 BitWidth = (Expr *)InstantiatedBitWidth.release();
119 }
120
121 FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), T,
122 cast<RecordDecl>(Owner),
123 D->getLocation(),
124 D->isMutable(),
125 BitWidth,
126 D->getAccess(),
127 0);
128 if (Field) {
129 if (Invalid)
130 Field->setInvalidDecl();
131
132 Owner->addDecl(Field);
133 }
134
135 return Field;
136}
137
138Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
139 Expr *AssertExpr = D->getAssertExpr();
140
141 OwningExprResult InstantiatedAssertExpr
142 = SemaRef.InstantiateExpr(AssertExpr, TemplateArgs, NumTemplateArgs);
143 if (InstantiatedAssertExpr.isInvalid())
144 return 0;
145
146 OwningExprResult Message = SemaRef.Clone(D->getMessage());
147 Decl *StaticAssert
148 = (Decl *)SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
149 move(InstantiatedAssertExpr),
150 move(Message));
151 return StaticAssert;
152}
153
154Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
155 EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner,
156 D->getLocation(), D->getIdentifier(),
157 /*PrevDecl=*/0);
158 Owner->addDecl(Enum);
159 Enum->startDefinition();
160
161 llvm::SmallVector<Sema::DeclTy *, 16> Enumerators;
162
163 EnumConstantDecl *LastEnumConst = 0;
164 for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(),
165 ECEnd = D->enumerator_end();
166 EC != ECEnd; ++EC) {
167 // The specified value for the enumerator.
168 OwningExprResult Value = SemaRef.Owned((Expr *)0);
169 if (Expr *UninstValue = EC->getInitExpr())
170 Value = SemaRef.InstantiateExpr(UninstValue,
171 TemplateArgs, NumTemplateArgs);
172
173 // Drop the initial value and continue.
174 bool isInvalid = false;
175 if (Value.isInvalid()) {
176 Value = SemaRef.Owned((Expr *)0);
177 isInvalid = true;
178 }
179
180 EnumConstantDecl *EnumConst
181 = SemaRef.CheckEnumConstant(Enum, LastEnumConst,
182 EC->getLocation(), EC->getIdentifier(),
183 move(Value));
184
185 if (isInvalid) {
186 if (EnumConst)
187 EnumConst->setInvalidDecl();
188 Enum->setInvalidDecl();
189 }
190
191 if (EnumConst) {
192 Enum->addDecl(EnumConst);
193 Enumerators.push_back(EnumConst);
194 LastEnumConst = EnumConst;
195 }
196 }
197
198 SemaRef.ActOnEnumBody(Enum->getLocation(), Enum,
199 &Enumerators[0], Enumerators.size());
200
201 return Enum;
202}
203
Douglas Gregor2dc0e642009-03-23 23:06:20 +0000204Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
205 // Only handle actual methods; we'll deal with constructors,
206 // destructors, etc. separately.
207 if (D->getKind() != Decl::CXXMethod)
208 return 0;
209
Douglas Gregor5545e162009-03-24 00:38:23 +0000210 llvm::SmallVector<ParmVarDecl *, 16> Params;
211 QualType T = InstantiateFunctionType(D, Params);
Douglas Gregor2dc0e642009-03-23 23:06:20 +0000212 if (T.isNull())
213 return 0;
214
215 // Build the instantiated method declaration.
216 CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
217 CXXMethodDecl *Method
218 = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(),
219 D->getDeclName(), T, D->isStatic(),
220 D->isInline());
Douglas Gregor2dc0e642009-03-23 23:06:20 +0000221
Douglas Gregor5545e162009-03-24 00:38:23 +0000222 // Attach the parameters
223 for (unsigned P = 0; P < Params.size(); ++P)
224 Params[P]->setOwningFunction(Method);
225 Method->setParams(SemaRef.Context, &Params[0], Params.size());
226
227 if (InitMethodInstantiation(Method, D))
228 Method->setInvalidDecl();
Douglas Gregor2dc0e642009-03-23 23:06:20 +0000229
230 NamedDecl *PrevDecl
231 = SemaRef.LookupQualifiedName(Owner, Method->getDeclName(),
232 Sema::LookupOrdinaryName, true);
233 // In C++, the previous declaration we find might be a tag type
234 // (class or enum). In this case, the new declaration will hide the
235 // tag type. Note that this does does not apply if we're declaring a
236 // typedef (C++ [dcl.typedef]p4).
237 if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
238 PrevDecl = 0;
239 bool Redeclaration = false;
240 bool OverloadableAttrRequired = false;
241 if (SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
242 /*FIXME:*/OverloadableAttrRequired))
243 Method->setInvalidDecl();
244
245 if (!Method->isInvalidDecl() || !PrevDecl)
246 Owner->addDecl(Method);
247 return Method;
248}
249
Douglas Gregor03b2b072009-03-24 00:15:49 +0000250Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
Douglas Gregor5545e162009-03-24 00:38:23 +0000251 llvm::SmallVector<ParmVarDecl *, 16> Params;
252 QualType T = InstantiateFunctionType(D, Params);
Douglas Gregor03b2b072009-03-24 00:15:49 +0000253 if (T.isNull())
254 return 0;
Douglas Gregor5545e162009-03-24 00:38:23 +0000255 assert(Params.size() == 0 && "Destructor with parameters?");
256
Douglas Gregor03b2b072009-03-24 00:15:49 +0000257 // Build the instantiated destructor declaration.
258 CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
259 QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
260 CXXDestructorDecl *Destructor
261 = CXXDestructorDecl::Create(SemaRef.Context, Record,
262 D->getLocation(),
263 SemaRef.Context.DeclarationNames.getCXXDestructorName(ClassTy),
264 T, D->isInline(), false);
Douglas Gregor5545e162009-03-24 00:38:23 +0000265 if (InitMethodInstantiation(Destructor, D))
266 Destructor->setInvalidDecl();
Douglas Gregor03b2b072009-03-24 00:15:49 +0000267
268 bool Redeclaration = false;
269 bool OverloadableAttrRequired = false;
270 NamedDecl *PrevDecl = 0;
271 if (SemaRef.CheckFunctionDeclaration(Destructor, PrevDecl, Redeclaration,
272 /*FIXME:*/OverloadableAttrRequired))
273 Destructor->setInvalidDecl();
274 Owner->addDecl(Destructor);
275 return Destructor;
276}
277
Douglas Gregor2dc0e642009-03-23 23:06:20 +0000278Decl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
279 QualType OrigT = SemaRef.InstantiateType(D->getOriginalType(), TemplateArgs,
280 NumTemplateArgs, D->getLocation(),
281 D->getDeclName());
282 if (OrigT.isNull())
283 return 0;
284
285 QualType T = SemaRef.adjustParameterType(OrigT);
286
287 if (D->getDefaultArg()) {
288 // FIXME: Leave a marker for "uninstantiated" default
289 // arguments. They only get instantiated on demand at the call
290 // site.
291 unsigned DiagID = SemaRef.Diags.getCustomDiagID(Diagnostic::Warning,
292 "sorry, dropping default argument during template instantiation");
293 SemaRef.Diag(D->getDefaultArg()->getSourceRange().getBegin(), DiagID)
294 << D->getDefaultArg()->getSourceRange();
295 }
296
297 // Allocate the parameter
298 ParmVarDecl *Param = 0;
299 if (T == OrigT)
300 Param = ParmVarDecl::Create(SemaRef.Context, Owner, D->getLocation(),
301 D->getIdentifier(), T, D->getStorageClass(),
302 0);
303 else
304 Param = OriginalParmVarDecl::Create(SemaRef.Context, Owner,
305 D->getLocation(), D->getIdentifier(),
306 T, OrigT, D->getStorageClass(), 0);
307
308 // Note: we don't try to instantiate function parameters until after
309 // we've instantiated the function's type. Therefore, we don't have
310 // to check for 'void' parameter types here.
311 return Param;
312}
313
314Decl *
315TemplateDeclInstantiator::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
316 // Since parameter types can decay either before or after
317 // instantiation, we simply treat OriginalParmVarDecls as
318 // ParmVarDecls the same way, and create one or the other depending
319 // on what happens after template instantiation.
320 return VisitParmVarDecl(D);
321}
322
Douglas Gregor8dbc2692009-03-17 21:15:40 +0000323Decl *Sema::InstantiateDecl(Decl *D, DeclContext *Owner,
324 const TemplateArgument *TemplateArgs,
325 unsigned NumTemplateArgs) {
326 TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs,
327 NumTemplateArgs);
328 return Instantiator.Visit(D);
329}
330
Douglas Gregor5545e162009-03-24 00:38:23 +0000331/// \brief Instantiates the type of the given function, including
332/// instantiating all of the function parameters.
333///
334/// \param D The function that we will be instantiated
335///
336/// \param Params the instantiated parameter declarations
337
338/// \returns the instantiated function's type if successfull, a NULL
339/// type if there was an error.
340QualType
341TemplateDeclInstantiator::InstantiateFunctionType(FunctionDecl *D,
342 llvm::SmallVectorImpl<ParmVarDecl *> &Params) {
343 bool InvalidDecl = false;
344
345 // Instantiate the function parameters
346 TemplateDeclInstantiator ParamInstantiator(SemaRef, 0,
347 TemplateArgs, NumTemplateArgs);
348 llvm::SmallVector<QualType, 16> ParamTys;
349 for (FunctionDecl::param_iterator P = D->param_begin(),
350 PEnd = D->param_end();
351 P != PEnd; ++P) {
352 if (ParmVarDecl *PInst = (ParmVarDecl *)ParamInstantiator.Visit(*P)) {
353 if (PInst->getType()->isVoidType()) {
354 SemaRef.Diag(PInst->getLocation(), diag::err_param_with_void_type);
355 PInst->setInvalidDecl();
356 }
357 else if (SemaRef.RequireNonAbstractType(PInst->getLocation(),
358 PInst->getType(),
359 diag::err_abstract_type_in_decl,
360 1 /* parameter type */))
361 PInst->setInvalidDecl();
362
363 Params.push_back(PInst);
364 ParamTys.push_back(PInst->getType());
365
366 if (PInst->isInvalidDecl())
367 InvalidDecl = true;
368 } else
369 InvalidDecl = true;
370 }
371
372 // FIXME: Deallocate dead declarations.
373 if (InvalidDecl)
374 return QualType();
375
376 const FunctionProtoType *Proto = D->getType()->getAsFunctionProtoType();
377 assert(Proto && "Missing prototype?");
378 QualType ResultType
379 = SemaRef.InstantiateType(Proto->getResultType(),
380 TemplateArgs, NumTemplateArgs,
381 D->getLocation(), D->getDeclName());
382 if (ResultType.isNull())
383 return QualType();
384
385 return SemaRef.BuildFunctionType(ResultType, &ParamTys[0], ParamTys.size(),
386 Proto->isVariadic(), Proto->getTypeQuals(),
387 D->getLocation(), D->getDeclName());
388}
389
390/// \brief Initializes common fields of an instantiated method
391/// declaration (New) from the corresponding fields of its template
392/// (Tmpl).
393///
394/// \returns true if there was an error
395bool
396TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
397 CXXMethodDecl *Tmpl) {
398 CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
399 New->setAccess(Tmpl->getAccess());
400 if (Tmpl->isVirtual()) {
401 New->setVirtual();
402 Record->setAggregate(false);
403 Record->setPOD(false);
404 Record->setPolymorphic(true);
405 }
406 if (Tmpl->isDeleted())
407 New->setDeleted();
408 if (Tmpl->isPure()) {
409 New->setPure();
410 Record->setAbstract(true);
411 }
412
413 // FIXME: attributes
414 // FIXME: New needs a pointer to Tmpl
415 return false;
416}