blob: 17e0014d981930ac2dcf3d086cf69f0aeb6e4125 [file] [log] [blame]
Douglas Gregorb70ccad2009-05-15 18:22:25 +00001//===--- SemaTemplateInstantiateStmt.cpp - C++ Template Stmt 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 statements.
10//
11//===----------------------------------------------------------------------===/
12#include "Sema.h"
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/DeclTemplate.h"
15#include "clang/AST/StmtVisitor.h"
16#include "clang/AST/Expr.h"
17#include "clang/AST/ExprCXX.h"
18#include "clang/Parse/DeclSpec.h"
19#include "llvm/Support/Compiler.h"
20using namespace clang;
21
22namespace {
23 class VISIBILITY_HIDDEN TemplateStmtInstantiator
24 : public StmtVisitor<TemplateStmtInstantiator, Sema::OwningStmtResult> {
25 Sema &SemaRef;
26 const TemplateArgumentList &TemplateArgs;
27
Anders Carlssondf3b2082009-05-17 19:34:11 +000028 template<typename T>
29 Sema::FullExprArg FullExpr(T &expr) {
Anders Carlssona99fad82009-05-17 18:26:53 +000030 return SemaRef.FullExpr(expr);
31 }
32
Douglas Gregorb70ccad2009-05-15 18:22:25 +000033 public:
34 typedef Sema::OwningExprResult OwningExprResult;
35 typedef Sema::OwningStmtResult OwningStmtResult;
36
37 TemplateStmtInstantiator(Sema &SemaRef,
38 const TemplateArgumentList &TemplateArgs)
39 : SemaRef(SemaRef), TemplateArgs(TemplateArgs) { }
40
Douglas Gregor68d10c42009-05-18 19:08:47 +000041 // Declare VisitXXXStmt nodes for all of the statement kinds.
42#define STMT(Type, Base) OwningStmtResult Visit##Type(Type *S);
43#define EXPR(Type, Base)
44#include "clang/AST/StmtNodes.def"
45
46 // Visit an expression (which will use the expression
47 // instantiator).
Douglas Gregorb70ccad2009-05-15 18:22:25 +000048 OwningStmtResult VisitExpr(Expr *E);
Douglas Gregorb70ccad2009-05-15 18:22:25 +000049
50 // Base case. I'm supposed to ignore this.
51 OwningStmtResult VisitStmt(Stmt *S) {
52 S->dump();
53 assert(false && "Cannot instantiate this kind of statement");
54 return SemaRef.StmtError();
55 }
56 };
57}
58
Douglas Gregor68d10c42009-05-18 19:08:47 +000059//===----------------------------------------------------------------------===/
60// Common/C statements
61//===----------------------------------------------------------------------===/
Douglas Gregorb70ccad2009-05-15 18:22:25 +000062Sema::OwningStmtResult TemplateStmtInstantiator::VisitDeclStmt(DeclStmt *S) {
Douglas Gregor0ca20ac2009-05-29 18:27:38 +000063 llvm::SmallVector<Decl *, 4> Decls;
Douglas Gregorb70ccad2009-05-15 18:22:25 +000064 for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
65 D != DEnd; ++D) {
66 Decl *Instantiated = SemaRef.InstantiateDecl(*D, SemaRef.CurContext,
67 TemplateArgs);
68 if (!Instantiated)
69 return SemaRef.StmtError();
70
71 Decls.push_back(Instantiated);
Douglas Gregor6569d682009-05-27 23:11:45 +000072 SemaRef.CurrentInstantiationScope->InstantiatedLocal(*D, Instantiated);
Douglas Gregorb70ccad2009-05-15 18:22:25 +000073 }
74
75 return SemaRef.Owned(new (SemaRef.Context) DeclStmt(
76 DeclGroupRef::Create(SemaRef.Context,
77 &Decls[0],
78 Decls.size()),
79 S->getStartLoc(),
80 S->getEndLoc()));
81}
82
83Sema::OwningStmtResult TemplateStmtInstantiator::VisitNullStmt(NullStmt *S) {
Anders Carlssond4972062009-08-08 02:50:17 +000084 return SemaRef.Owned(S->Retain());
Douglas Gregorb70ccad2009-05-15 18:22:25 +000085}
86
87Sema::OwningStmtResult TemplateStmtInstantiator::VisitLabelStmt(LabelStmt *S) {
88 OwningStmtResult SubStmt = Visit(S->getSubStmt());
89
90 if (SubStmt.isInvalid())
91 return SemaRef.StmtError();
92
93 // FIXME: Pass the real colon loc in.
94 return SemaRef.ActOnLabelStmt(S->getIdentLoc(), S->getID(), SourceLocation(),
95 move(SubStmt));
96}
97
98Sema::OwningStmtResult TemplateStmtInstantiator::VisitGotoStmt(GotoStmt *S) {
99 return SemaRef.ActOnGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
100 S->getLabel()->getID());
101}
102
Douglas Gregor5f1b9e62009-05-16 00:20:29 +0000103Sema::OwningStmtResult
104TemplateStmtInstantiator::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
105 OwningExprResult Target = SemaRef.InstantiateExpr(S->getTarget(),
106 TemplateArgs);
107 if (Target.isInvalid())
108 return SemaRef.StmtError();
109
110 return SemaRef.ActOnIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(),
111 move(Target));
112}
113
Douglas Gregor861ce312009-05-15 22:32:39 +0000114Sema::OwningStmtResult TemplateStmtInstantiator::VisitBreakStmt(BreakStmt *S) {
Anders Carlssond4972062009-08-08 02:50:17 +0000115 return SemaRef.Owned(S->Retain());
Douglas Gregor861ce312009-05-15 22:32:39 +0000116}
117
118Sema::OwningStmtResult
119TemplateStmtInstantiator::VisitContinueStmt(ContinueStmt *S) {
Anders Carlssond4972062009-08-08 02:50:17 +0000120 return SemaRef.Owned(S->Retain());
Douglas Gregor861ce312009-05-15 22:32:39 +0000121}
122
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000123Sema::OwningStmtResult
124TemplateStmtInstantiator::VisitReturnStmt(ReturnStmt *S) {
Anders Carlssone28be432009-05-15 20:29:28 +0000125 Sema::OwningExprResult Result = SemaRef.ExprEmpty();
126 if (Expr *E = S->getRetValue()) {
127 Result = SemaRef.InstantiateExpr(E, TemplateArgs);
128
129 if (Result.isInvalid())
130 return SemaRef.StmtError();
131 }
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000132
Anders Carlssonf53b4432009-08-18 16:11:00 +0000133 return SemaRef.ActOnReturnStmt(S->getReturnLoc(), move(Result));
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000134}
135
136Sema::OwningStmtResult
137TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) {
Douglas Gregor66b46be2009-05-20 22:57:03 +0000138 return SemaRef.InstantiateCompoundStmt(S, TemplateArgs, false);
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000139}
140
Douglas Gregor68d10c42009-05-18 19:08:47 +0000141Sema::OwningStmtResult
142TemplateStmtInstantiator::VisitSwitchCase(SwitchCase *S) {
143 assert(false && "SwitchCase statements are never directly instantiated");
144 return SemaRef.StmtError();
145}
146
Douglas Gregordbb26db2009-05-15 23:57:33 +0000147Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) {
Douglas Gregorac7610d2009-06-22 20:57:11 +0000148 // The case value expressions are not potentially evaluated.
149 EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
150
Douglas Gregordbb26db2009-05-15 23:57:33 +0000151 // Instantiate left-hand case value.
152 OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs);
153 if (LHS.isInvalid())
154 return SemaRef.StmtError();
155
156 // Instantiate right-hand case value (for the GNU case-range extension).
157 OwningExprResult RHS = SemaRef.InstantiateExpr(S->getRHS(), TemplateArgs);
158 if (RHS.isInvalid())
159 return SemaRef.StmtError();
160
161 // Build the case statement.
162 OwningStmtResult Case = SemaRef.ActOnCaseStmt(S->getCaseLoc(),
163 move(LHS),
164 S->getEllipsisLoc(),
165 move(RHS),
166 S->getColonLoc());
167 if (Case.isInvalid())
168 return SemaRef.StmtError();
169
170 // Instantiate the statement following the case
171 OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(),
172 TemplateArgs);
173 if (SubStmt.isInvalid())
174 return SemaRef.StmtError();
175
176 SemaRef.ActOnCaseStmtBody(Case.get(), move(SubStmt));
177 return move(Case);
178}
179
180Sema::OwningStmtResult
181TemplateStmtInstantiator::VisitDefaultStmt(DefaultStmt *S) {
182 // Instantiate the statement following the default case
183 OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(),
184 TemplateArgs);
185 if (SubStmt.isInvalid())
186 return SemaRef.StmtError();
187
188 return SemaRef.ActOnDefaultStmt(S->getDefaultLoc(),
189 S->getColonLoc(),
190 move(SubStmt),
191 /*CurScope=*/0);
192}
193
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000194Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) {
195 // Instantiate the condition
196 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
197 if (Cond.isInvalid())
198 return SemaRef.StmtError();
199
Anders Carlssonc4ee1702009-06-04 02:18:15 +0000200 Sema::FullExprArg FullCond(FullExpr(Cond));
201
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000202 // Instantiate the "then" branch.
203 OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs);
204 if (Then.isInvalid())
205 return SemaRef.StmtError();
206
207 // Instantiate the "else" branch.
208 OwningStmtResult Else = SemaRef.InstantiateStmt(S->getElse(), TemplateArgs);
209 if (Else.isInvalid())
210 return SemaRef.StmtError();
211
Anders Carlssonc4ee1702009-06-04 02:18:15 +0000212 return SemaRef.ActOnIfStmt(S->getIfLoc(), FullCond, move(Then),
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000213 S->getElseLoc(), move(Else));
214}
215
Douglas Gregordbb26db2009-05-15 23:57:33 +0000216Sema::OwningStmtResult
217TemplateStmtInstantiator::VisitSwitchStmt(SwitchStmt *S) {
218 // Instantiate the condition.
219 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
220 if (Cond.isInvalid())
221 return SemaRef.StmtError();
222
223 // Start the switch statement itself.
224 OwningStmtResult Switch = SemaRef.ActOnStartOfSwitchStmt(move(Cond));
225 if (Switch.isInvalid())
226 return SemaRef.StmtError();
227
228 // Instantiate the body of the switch statement.
229 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
230 if (Body.isInvalid())
231 return SemaRef.StmtError();
232
233 // Complete the switch statement.
234 return SemaRef.ActOnFinishSwitchStmt(S->getSwitchLoc(), move(Switch),
235 move(Body));
236}
237
Douglas Gregor4a2e2042009-05-15 21:45:53 +0000238Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *S) {
239 // Instantiate the condition
240 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
241 if (Cond.isInvalid())
242 return SemaRef.StmtError();
243
Anders Carlssonc4ee1702009-06-04 02:18:15 +0000244 Sema::FullExprArg FullCond(FullExpr(Cond));
245
Douglas Gregor4a2e2042009-05-15 21:45:53 +0000246 // Instantiate the body
247 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
248 if (Body.isInvalid())
249 return SemaRef.StmtError();
250
Anders Carlssonc4ee1702009-06-04 02:18:15 +0000251 return SemaRef.ActOnWhileStmt(S->getWhileLoc(), FullCond, move(Body));
Douglas Gregor4a2e2042009-05-15 21:45:53 +0000252}
253
Douglas Gregor9f3ca2a2009-05-15 21:56:04 +0000254Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) {
255 // Instantiate the condition
256 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
257 if (Cond.isInvalid())
258 return SemaRef.StmtError();
259
260 // Instantiate the body
261 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
262 if (Body.isInvalid())
263 return SemaRef.StmtError();
264
265 return SemaRef.ActOnDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(),
Chris Lattner98913592009-06-12 23:04:47 +0000266 SourceLocation(), move(Cond), S->getRParenLoc());
Douglas Gregor9f3ca2a2009-05-15 21:56:04 +0000267}
268
Douglas Gregor5831c6a2009-05-15 22:12:32 +0000269Sema::OwningStmtResult TemplateStmtInstantiator::VisitForStmt(ForStmt *S) {
270 // Instantiate the initialization statement
271 OwningStmtResult Init = SemaRef.InstantiateStmt(S->getInit(), TemplateArgs);
272 if (Init.isInvalid())
273 return SemaRef.StmtError();
274
275 // Instantiate the condition
276 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
277 if (Cond.isInvalid())
278 return SemaRef.StmtError();
279
280 // Instantiate the increment
281 OwningExprResult Inc = SemaRef.InstantiateExpr(S->getInc(), TemplateArgs);
282 if (Inc.isInvalid())
283 return SemaRef.StmtError();
284
285 // Instantiate the body
286 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
287 if (Body.isInvalid())
288 return SemaRef.StmtError();
289
290 return SemaRef.ActOnForStmt(S->getForLoc(), S->getLParenLoc(),
291 move(Init), move(Cond), move(Inc),
292 S->getRParenLoc(), move(Body));
293}
294
Douglas Gregor68d10c42009-05-18 19:08:47 +0000295Sema::OwningStmtResult
296TemplateStmtInstantiator::VisitAsmStmt(AsmStmt *S) {
297 // FIXME: Implement this
298 assert(false && "Cannot instantiate an 'asm' statement");
299 return SemaRef.StmtError();
300}
301
302//===----------------------------------------------------------------------===/
303// C++ statements
304//===----------------------------------------------------------------------===/
305Sema::OwningStmtResult
306TemplateStmtInstantiator::VisitCXXTryStmt(CXXTryStmt *S) {
Douglas Gregord308e622009-05-18 20:51:54 +0000307 // Instantiate the try block itself.
308 OwningStmtResult TryBlock = VisitCompoundStmt(S->getTryBlock());
309 if (TryBlock.isInvalid())
310 return SemaRef.StmtError();
311
312 // Instantiate the handlers.
Douglas Gregord7e27052009-05-20 22:33:37 +0000313 ASTOwningVector<&ActionBase::DeleteStmt> Handlers(SemaRef);
Douglas Gregord308e622009-05-18 20:51:54 +0000314 for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) {
315 OwningStmtResult Handler = VisitCXXCatchStmt(S->getHandler(I));
Douglas Gregord7e27052009-05-20 22:33:37 +0000316 if (Handler.isInvalid())
Douglas Gregord308e622009-05-18 20:51:54 +0000317 return SemaRef.StmtError();
Douglas Gregord308e622009-05-18 20:51:54 +0000318
319 Handlers.push_back(Handler.takeAs<Stmt>());
320 }
321
322 return SemaRef.ActOnCXXTryBlock(S->getTryLoc(), move(TryBlock),
Douglas Gregor45db71d2009-05-21 16:25:11 +0000323 move_arg(Handlers));
Douglas Gregor68d10c42009-05-18 19:08:47 +0000324}
325
326Sema::OwningStmtResult
327TemplateStmtInstantiator::VisitCXXCatchStmt(CXXCatchStmt *S) {
Douglas Gregord308e622009-05-18 20:51:54 +0000328 // Instantiate the exception declaration, if any.
329 VarDecl *Var = 0;
330 if (S->getExceptionDecl()) {
331 VarDecl *ExceptionDecl = S->getExceptionDecl();
332 QualType T = SemaRef.InstantiateType(ExceptionDecl->getType(),
333 TemplateArgs,
334 ExceptionDecl->getLocation(),
335 ExceptionDecl->getDeclName());
336 if (T.isNull())
337 return SemaRef.StmtError();
338
339 Var = SemaRef.BuildExceptionDeclaration(0, T,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +0000340 ExceptionDecl->getDeclaratorInfo(),
Douglas Gregord308e622009-05-18 20:51:54 +0000341 ExceptionDecl->getIdentifier(),
342 ExceptionDecl->getLocation(),
343 /*FIXME: Inaccurate*/
344 SourceRange(ExceptionDecl->getLocation()));
345 if (Var->isInvalidDecl()) {
346 Var->Destroy(SemaRef.Context);
347 return SemaRef.StmtError();
348 }
349
350 // Introduce the exception declaration into scope.
351 SemaRef.CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
352 }
353
354 // Instantiate the actual exception handler.
355 OwningStmtResult Handler = Visit(S->getHandlerBlock());
356 if (Handler.isInvalid()) {
357 if (Var)
358 Var->Destroy(SemaRef.Context);
359 return SemaRef.StmtError();
360 }
361
362 return SemaRef.Owned(new (SemaRef.Context) CXXCatchStmt(S->getCatchLoc(),
363 Var,
364 Handler.takeAs<Stmt>()));
Douglas Gregor68d10c42009-05-18 19:08:47 +0000365}
366
367//===----------------------------------------------------------------------===/
368// Objective-C statements
369//===----------------------------------------------------------------------===/
370Sema::OwningStmtResult
371TemplateStmtInstantiator::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
372 // FIXME: Implement this
373 assert(false && "Cannot instantiate an Objective-C @finally statement");
374 return SemaRef.StmtError();
375}
376
377Sema::OwningStmtResult
378TemplateStmtInstantiator::VisitObjCAtSynchronizedStmt(
379 ObjCAtSynchronizedStmt *S) {
380 // FIXME: Implement this
381 assert(false && "Cannot instantiate an Objective-C @synchronized statement");
382 return SemaRef.StmtError();
383}
384
385Sema::OwningStmtResult
386TemplateStmtInstantiator::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
387 // FIXME: Implement this
388 assert(false && "Cannot instantiate an Objective-C @try statement");
389 return SemaRef.StmtError();
390}
391
392Sema::OwningStmtResult
393TemplateStmtInstantiator::VisitObjCForCollectionStmt(
394 ObjCForCollectionStmt *S) {
395 // FIXME: Implement this
396 assert(false && "Cannot instantiate an Objective-C \"for\" statement");
397 return SemaRef.StmtError();
398}
399
400Sema::OwningStmtResult
401TemplateStmtInstantiator::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
402 // FIXME: Implement this
403 assert(false && "Cannot instantiate an Objective-C @throw statement");
404 return SemaRef.StmtError();
405}
406
407Sema::OwningStmtResult
408TemplateStmtInstantiator::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
409 // FIXME: Implement this
410 assert(false && "Cannot instantiate an Objective-C @catch statement");
411 return SemaRef.StmtError();
412}
413
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000414Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) {
415 Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs);
416 if (Result.isInvalid())
417 return SemaRef.StmtError();
418
419 return SemaRef.Owned(Result.takeAs<Stmt>());
420}
421
422Sema::OwningStmtResult
423Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
Douglas Gregor50557a72009-05-15 20:47:12 +0000424 if (!S)
425 return Owned((Stmt *)0);
426
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000427 TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
428 return Instantiator.Visit(S);
429}
Douglas Gregor66b46be2009-05-20 22:57:03 +0000430
431Sema::OwningStmtResult
432Sema::InstantiateCompoundStmt(CompoundStmt *S,
433 const TemplateArgumentList &TemplateArgs,
434 bool isStmtExpr) {
435 if (!S)
436 return Owned((Stmt *)0);
437
438 TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
439 ASTOwningVector<&ActionBase::DeleteStmt> Statements(*this);
440 for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
441 B != BEnd; ++B) {
442 OwningStmtResult Result = Instantiator.Visit(*B);
443 if (Result.isInvalid())
444 return StmtError();
445
446 Statements.push_back(Result.takeAs<Stmt>());
447 }
448
449 return ActOnCompoundStmt(S->getLBracLoc(), S->getRBracLoc(),
Douglas Gregor45db71d2009-05-21 16:25:11 +0000450 move_arg(Statements), isStmtExpr);
Douglas Gregor66b46be2009-05-20 22:57:03 +0000451}