blob: d635dff94c667f646ee1064f1b354483f4fa3f9b [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) {
63 llvm::SmallVector<Decl *, 8> Decls;
64 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);
72 SemaRef.CurrentInstantiationScope->InstantiatedLocal(cast<VarDecl>(*D),
73 cast<VarDecl>(Instantiated));
74 }
75
76 return SemaRef.Owned(new (SemaRef.Context) DeclStmt(
77 DeclGroupRef::Create(SemaRef.Context,
78 &Decls[0],
79 Decls.size()),
80 S->getStartLoc(),
81 S->getEndLoc()));
82}
83
84Sema::OwningStmtResult TemplateStmtInstantiator::VisitNullStmt(NullStmt *S) {
85 return SemaRef.Owned(S->Clone(SemaRef.Context));
86}
87
88Sema::OwningStmtResult TemplateStmtInstantiator::VisitLabelStmt(LabelStmt *S) {
89 OwningStmtResult SubStmt = Visit(S->getSubStmt());
90
91 if (SubStmt.isInvalid())
92 return SemaRef.StmtError();
93
94 // FIXME: Pass the real colon loc in.
95 return SemaRef.ActOnLabelStmt(S->getIdentLoc(), S->getID(), SourceLocation(),
96 move(SubStmt));
97}
98
99Sema::OwningStmtResult TemplateStmtInstantiator::VisitGotoStmt(GotoStmt *S) {
100 return SemaRef.ActOnGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
101 S->getLabel()->getID());
102}
103
Douglas Gregor5f1b9e62009-05-16 00:20:29 +0000104Sema::OwningStmtResult
105TemplateStmtInstantiator::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
106 OwningExprResult Target = SemaRef.InstantiateExpr(S->getTarget(),
107 TemplateArgs);
108 if (Target.isInvalid())
109 return SemaRef.StmtError();
110
111 return SemaRef.ActOnIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(),
112 move(Target));
113}
114
Douglas Gregor861ce312009-05-15 22:32:39 +0000115Sema::OwningStmtResult TemplateStmtInstantiator::VisitBreakStmt(BreakStmt *S) {
116 return SemaRef.Owned(S->Clone(SemaRef.Context));
117}
118
119Sema::OwningStmtResult
120TemplateStmtInstantiator::VisitContinueStmt(ContinueStmt *S) {
121 return SemaRef.Owned(S->Clone(SemaRef.Context));
122}
123
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000124Sema::OwningStmtResult
125TemplateStmtInstantiator::VisitReturnStmt(ReturnStmt *S) {
Anders Carlssone28be432009-05-15 20:29:28 +0000126 Sema::OwningExprResult Result = SemaRef.ExprEmpty();
127 if (Expr *E = S->getRetValue()) {
128 Result = SemaRef.InstantiateExpr(E, TemplateArgs);
129
130 if (Result.isInvalid())
131 return SemaRef.StmtError();
132 }
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000133
134 return SemaRef.ActOnReturnStmt(S->getReturnLoc(), move(Result));
135}
136
137Sema::OwningStmtResult
138TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) {
Douglas Gregor66b46be2009-05-20 22:57:03 +0000139 return SemaRef.InstantiateCompoundStmt(S, TemplateArgs, false);
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000140}
141
Douglas Gregor68d10c42009-05-18 19:08:47 +0000142Sema::OwningStmtResult
143TemplateStmtInstantiator::VisitSwitchCase(SwitchCase *S) {
144 assert(false && "SwitchCase statements are never directly instantiated");
145 return SemaRef.StmtError();
146}
147
Douglas Gregordbb26db2009-05-15 23:57:33 +0000148Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) {
149 // Instantiate left-hand case value.
150 OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs);
151 if (LHS.isInvalid())
152 return SemaRef.StmtError();
153
154 // Instantiate right-hand case value (for the GNU case-range extension).
155 OwningExprResult RHS = SemaRef.InstantiateExpr(S->getRHS(), TemplateArgs);
156 if (RHS.isInvalid())
157 return SemaRef.StmtError();
158
159 // Build the case statement.
160 OwningStmtResult Case = SemaRef.ActOnCaseStmt(S->getCaseLoc(),
161 move(LHS),
162 S->getEllipsisLoc(),
163 move(RHS),
164 S->getColonLoc());
165 if (Case.isInvalid())
166 return SemaRef.StmtError();
167
168 // Instantiate the statement following the case
169 OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(),
170 TemplateArgs);
171 if (SubStmt.isInvalid())
172 return SemaRef.StmtError();
173
174 SemaRef.ActOnCaseStmtBody(Case.get(), move(SubStmt));
175 return move(Case);
176}
177
178Sema::OwningStmtResult
179TemplateStmtInstantiator::VisitDefaultStmt(DefaultStmt *S) {
180 // Instantiate the statement following the default case
181 OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(),
182 TemplateArgs);
183 if (SubStmt.isInvalid())
184 return SemaRef.StmtError();
185
186 return SemaRef.ActOnDefaultStmt(S->getDefaultLoc(),
187 S->getColonLoc(),
188 move(SubStmt),
189 /*CurScope=*/0);
190}
191
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000192Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) {
193 // Instantiate the condition
194 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
195 if (Cond.isInvalid())
196 return SemaRef.StmtError();
197
198 // Instantiate the "then" branch.
199 OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs);
200 if (Then.isInvalid())
201 return SemaRef.StmtError();
202
203 // Instantiate the "else" branch.
204 OwningStmtResult Else = SemaRef.InstantiateStmt(S->getElse(), TemplateArgs);
205 if (Else.isInvalid())
206 return SemaRef.StmtError();
207
Anders Carlssona99fad82009-05-17 18:26:53 +0000208 return SemaRef.ActOnIfStmt(S->getIfLoc(), FullExpr(Cond), move(Then),
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000209 S->getElseLoc(), move(Else));
210}
211
Douglas Gregordbb26db2009-05-15 23:57:33 +0000212Sema::OwningStmtResult
213TemplateStmtInstantiator::VisitSwitchStmt(SwitchStmt *S) {
214 // Instantiate the condition.
215 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
216 if (Cond.isInvalid())
217 return SemaRef.StmtError();
218
219 // Start the switch statement itself.
220 OwningStmtResult Switch = SemaRef.ActOnStartOfSwitchStmt(move(Cond));
221 if (Switch.isInvalid())
222 return SemaRef.StmtError();
223
224 // Instantiate the body of the switch statement.
225 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
226 if (Body.isInvalid())
227 return SemaRef.StmtError();
228
229 // Complete the switch statement.
230 return SemaRef.ActOnFinishSwitchStmt(S->getSwitchLoc(), move(Switch),
231 move(Body));
232}
233
Douglas Gregor4a2e2042009-05-15 21:45:53 +0000234Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *S) {
235 // Instantiate the condition
236 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
237 if (Cond.isInvalid())
238 return SemaRef.StmtError();
239
240 // Instantiate the body
241 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
242 if (Body.isInvalid())
243 return SemaRef.StmtError();
244
Anders Carlsson7f537c12009-05-17 21:22:26 +0000245 return SemaRef.ActOnWhileStmt(S->getWhileLoc(), FullExpr(Cond), move(Body));
Douglas Gregor4a2e2042009-05-15 21:45:53 +0000246}
247
Douglas Gregor9f3ca2a2009-05-15 21:56:04 +0000248Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) {
249 // Instantiate the condition
250 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
251 if (Cond.isInvalid())
252 return SemaRef.StmtError();
253
254 // Instantiate the body
255 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
256 if (Body.isInvalid())
257 return SemaRef.StmtError();
258
259 return SemaRef.ActOnDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(),
260 move(Cond));
261}
262
Douglas Gregor5831c6a2009-05-15 22:12:32 +0000263Sema::OwningStmtResult TemplateStmtInstantiator::VisitForStmt(ForStmt *S) {
264 // Instantiate the initialization statement
265 OwningStmtResult Init = SemaRef.InstantiateStmt(S->getInit(), TemplateArgs);
266 if (Init.isInvalid())
267 return SemaRef.StmtError();
268
269 // Instantiate the condition
270 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
271 if (Cond.isInvalid())
272 return SemaRef.StmtError();
273
274 // Instantiate the increment
275 OwningExprResult Inc = SemaRef.InstantiateExpr(S->getInc(), TemplateArgs);
276 if (Inc.isInvalid())
277 return SemaRef.StmtError();
278
279 // Instantiate the body
280 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
281 if (Body.isInvalid())
282 return SemaRef.StmtError();
283
284 return SemaRef.ActOnForStmt(S->getForLoc(), S->getLParenLoc(),
285 move(Init), move(Cond), move(Inc),
286 S->getRParenLoc(), move(Body));
287}
288
Douglas Gregor68d10c42009-05-18 19:08:47 +0000289Sema::OwningStmtResult
290TemplateStmtInstantiator::VisitAsmStmt(AsmStmt *S) {
291 // FIXME: Implement this
292 assert(false && "Cannot instantiate an 'asm' statement");
293 return SemaRef.StmtError();
294}
295
296//===----------------------------------------------------------------------===/
297// C++ statements
298//===----------------------------------------------------------------------===/
299Sema::OwningStmtResult
300TemplateStmtInstantiator::VisitCXXTryStmt(CXXTryStmt *S) {
Douglas Gregord308e622009-05-18 20:51:54 +0000301 // Instantiate the try block itself.
302 OwningStmtResult TryBlock = VisitCompoundStmt(S->getTryBlock());
303 if (TryBlock.isInvalid())
304 return SemaRef.StmtError();
305
306 // Instantiate the handlers.
Douglas Gregord7e27052009-05-20 22:33:37 +0000307 ASTOwningVector<&ActionBase::DeleteStmt> Handlers(SemaRef);
Douglas Gregord308e622009-05-18 20:51:54 +0000308 for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) {
309 OwningStmtResult Handler = VisitCXXCatchStmt(S->getHandler(I));
Douglas Gregord7e27052009-05-20 22:33:37 +0000310 if (Handler.isInvalid())
Douglas Gregord308e622009-05-18 20:51:54 +0000311 return SemaRef.StmtError();
Douglas Gregord308e622009-05-18 20:51:54 +0000312
313 Handlers.push_back(Handler.takeAs<Stmt>());
314 }
315
316 return SemaRef.ActOnCXXTryBlock(S->getTryLoc(), move(TryBlock),
317 Sema::MultiStmtArg(SemaRef,
Douglas Gregord7e27052009-05-20 22:33:37 +0000318 Handlers.take(),
Douglas Gregord308e622009-05-18 20:51:54 +0000319 Handlers.size()));
Douglas Gregor68d10c42009-05-18 19:08:47 +0000320}
321
322Sema::OwningStmtResult
323TemplateStmtInstantiator::VisitCXXCatchStmt(CXXCatchStmt *S) {
Douglas Gregord308e622009-05-18 20:51:54 +0000324 // Instantiate the exception declaration, if any.
325 VarDecl *Var = 0;
326 if (S->getExceptionDecl()) {
327 VarDecl *ExceptionDecl = S->getExceptionDecl();
328 QualType T = SemaRef.InstantiateType(ExceptionDecl->getType(),
329 TemplateArgs,
330 ExceptionDecl->getLocation(),
331 ExceptionDecl->getDeclName());
332 if (T.isNull())
333 return SemaRef.StmtError();
334
335 Var = SemaRef.BuildExceptionDeclaration(0, T,
336 ExceptionDecl->getIdentifier(),
337 ExceptionDecl->getLocation(),
338 /*FIXME: Inaccurate*/
339 SourceRange(ExceptionDecl->getLocation()));
340 if (Var->isInvalidDecl()) {
341 Var->Destroy(SemaRef.Context);
342 return SemaRef.StmtError();
343 }
344
345 // Introduce the exception declaration into scope.
346 SemaRef.CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
347 }
348
349 // Instantiate the actual exception handler.
350 OwningStmtResult Handler = Visit(S->getHandlerBlock());
351 if (Handler.isInvalid()) {
352 if (Var)
353 Var->Destroy(SemaRef.Context);
354 return SemaRef.StmtError();
355 }
356
357 return SemaRef.Owned(new (SemaRef.Context) CXXCatchStmt(S->getCatchLoc(),
358 Var,
359 Handler.takeAs<Stmt>()));
Douglas Gregor68d10c42009-05-18 19:08:47 +0000360}
361
362//===----------------------------------------------------------------------===/
363// Objective-C statements
364//===----------------------------------------------------------------------===/
365Sema::OwningStmtResult
366TemplateStmtInstantiator::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
367 // FIXME: Implement this
368 assert(false && "Cannot instantiate an Objective-C @finally statement");
369 return SemaRef.StmtError();
370}
371
372Sema::OwningStmtResult
373TemplateStmtInstantiator::VisitObjCAtSynchronizedStmt(
374 ObjCAtSynchronizedStmt *S) {
375 // FIXME: Implement this
376 assert(false && "Cannot instantiate an Objective-C @synchronized statement");
377 return SemaRef.StmtError();
378}
379
380Sema::OwningStmtResult
381TemplateStmtInstantiator::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
382 // FIXME: Implement this
383 assert(false && "Cannot instantiate an Objective-C @try statement");
384 return SemaRef.StmtError();
385}
386
387Sema::OwningStmtResult
388TemplateStmtInstantiator::VisitObjCForCollectionStmt(
389 ObjCForCollectionStmt *S) {
390 // FIXME: Implement this
391 assert(false && "Cannot instantiate an Objective-C \"for\" statement");
392 return SemaRef.StmtError();
393}
394
395Sema::OwningStmtResult
396TemplateStmtInstantiator::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
397 // FIXME: Implement this
398 assert(false && "Cannot instantiate an Objective-C @throw statement");
399 return SemaRef.StmtError();
400}
401
402Sema::OwningStmtResult
403TemplateStmtInstantiator::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
404 // FIXME: Implement this
405 assert(false && "Cannot instantiate an Objective-C @catch statement");
406 return SemaRef.StmtError();
407}
408
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000409Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) {
410 Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs);
411 if (Result.isInvalid())
412 return SemaRef.StmtError();
413
414 return SemaRef.Owned(Result.takeAs<Stmt>());
415}
416
417Sema::OwningStmtResult
418Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
Douglas Gregor50557a72009-05-15 20:47:12 +0000419 if (!S)
420 return Owned((Stmt *)0);
421
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000422 TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
423 return Instantiator.Visit(S);
424}
Douglas Gregor66b46be2009-05-20 22:57:03 +0000425
426Sema::OwningStmtResult
427Sema::InstantiateCompoundStmt(CompoundStmt *S,
428 const TemplateArgumentList &TemplateArgs,
429 bool isStmtExpr) {
430 if (!S)
431 return Owned((Stmt *)0);
432
433 TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
434 ASTOwningVector<&ActionBase::DeleteStmt> Statements(*this);
435 for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
436 B != BEnd; ++B) {
437 OwningStmtResult Result = Instantiator.Visit(*B);
438 if (Result.isInvalid())
439 return StmtError();
440
441 Statements.push_back(Result.takeAs<Stmt>());
442 }
443
444 return ActOnCompoundStmt(S->getLBracLoc(), S->getRBracLoc(),
445 Sema::MultiStmtArg(*this,
446 Statements.take(),
447 Statements.size()),
448 isStmtExpr);
449}