blob: 527b33d710cb114c6b14e95318bc3b642f5b9c2a [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
28 public:
29 typedef Sema::OwningExprResult OwningExprResult;
30 typedef Sema::OwningStmtResult OwningStmtResult;
31
32 TemplateStmtInstantiator(Sema &SemaRef,
33 const TemplateArgumentList &TemplateArgs)
34 : SemaRef(SemaRef), TemplateArgs(TemplateArgs) { }
35
36 // FIXME: Once we get closer to completion, replace these
37 // manually-written declarations with automatically-generated ones
38 // from clang/AST/StmtNodes.def.
39 OwningStmtResult VisitDeclStmt(DeclStmt *S);
40 OwningStmtResult VisitNullStmt(NullStmt *S);
41 OwningStmtResult VisitCompoundStmt(CompoundStmt *S);
Douglas Gregordbb26db2009-05-15 23:57:33 +000042 OwningStmtResult VisitCaseStmt(CaseStmt *S);
43 OwningStmtResult VisitDefaultStmt(DefaultStmt *S);
Douglas Gregord06f6ca2009-05-15 18:53:42 +000044 OwningStmtResult VisitIfStmt(IfStmt *S);
Douglas Gregordbb26db2009-05-15 23:57:33 +000045 OwningStmtResult VisitSwitchStmt(SwitchStmt *S);
Douglas Gregor4a2e2042009-05-15 21:45:53 +000046 OwningStmtResult VisitWhileStmt(WhileStmt *S);
Douglas Gregor9f3ca2a2009-05-15 21:56:04 +000047 OwningStmtResult VisitDoStmt(DoStmt *S);
Douglas Gregor5831c6a2009-05-15 22:12:32 +000048 OwningStmtResult VisitForStmt(ForStmt *S);
Douglas Gregorb70ccad2009-05-15 18:22:25 +000049 OwningStmtResult VisitExpr(Expr *E);
50 OwningStmtResult VisitLabelStmt(LabelStmt *S);
51 OwningStmtResult VisitGotoStmt(GotoStmt *S);
Douglas Gregor5f1b9e62009-05-16 00:20:29 +000052 OwningStmtResult VisitIndirectGotoStmt(IndirectGotoStmt *S);
Douglas Gregor861ce312009-05-15 22:32:39 +000053 OwningStmtResult VisitBreakStmt(BreakStmt *S);
54 OwningStmtResult VisitContinueStmt(ContinueStmt *S);
Douglas Gregorb70ccad2009-05-15 18:22:25 +000055 OwningStmtResult VisitReturnStmt(ReturnStmt *S);
56
57 // Base case. I'm supposed to ignore this.
58 OwningStmtResult VisitStmt(Stmt *S) {
59 S->dump();
60 assert(false && "Cannot instantiate this kind of statement");
61 return SemaRef.StmtError();
62 }
63 };
64}
65
66Sema::OwningStmtResult TemplateStmtInstantiator::VisitDeclStmt(DeclStmt *S) {
67 llvm::SmallVector<Decl *, 8> Decls;
68 for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
69 D != DEnd; ++D) {
70 Decl *Instantiated = SemaRef.InstantiateDecl(*D, SemaRef.CurContext,
71 TemplateArgs);
72 if (!Instantiated)
73 return SemaRef.StmtError();
74
75 Decls.push_back(Instantiated);
76 SemaRef.CurrentInstantiationScope->InstantiatedLocal(cast<VarDecl>(*D),
77 cast<VarDecl>(Instantiated));
78 }
79
80 return SemaRef.Owned(new (SemaRef.Context) DeclStmt(
81 DeclGroupRef::Create(SemaRef.Context,
82 &Decls[0],
83 Decls.size()),
84 S->getStartLoc(),
85 S->getEndLoc()));
86}
87
88Sema::OwningStmtResult TemplateStmtInstantiator::VisitNullStmt(NullStmt *S) {
89 return SemaRef.Owned(S->Clone(SemaRef.Context));
90}
91
92Sema::OwningStmtResult TemplateStmtInstantiator::VisitLabelStmt(LabelStmt *S) {
93 OwningStmtResult SubStmt = Visit(S->getSubStmt());
94
95 if (SubStmt.isInvalid())
96 return SemaRef.StmtError();
97
98 // FIXME: Pass the real colon loc in.
99 return SemaRef.ActOnLabelStmt(S->getIdentLoc(), S->getID(), SourceLocation(),
100 move(SubStmt));
101}
102
103Sema::OwningStmtResult TemplateStmtInstantiator::VisitGotoStmt(GotoStmt *S) {
104 return SemaRef.ActOnGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
105 S->getLabel()->getID());
106}
107
Douglas Gregor5f1b9e62009-05-16 00:20:29 +0000108Sema::OwningStmtResult
109TemplateStmtInstantiator::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
110 OwningExprResult Target = SemaRef.InstantiateExpr(S->getTarget(),
111 TemplateArgs);
112 if (Target.isInvalid())
113 return SemaRef.StmtError();
114
115 return SemaRef.ActOnIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(),
116 move(Target));
117}
118
Douglas Gregor861ce312009-05-15 22:32:39 +0000119Sema::OwningStmtResult TemplateStmtInstantiator::VisitBreakStmt(BreakStmt *S) {
120 return SemaRef.Owned(S->Clone(SemaRef.Context));
121}
122
123Sema::OwningStmtResult
124TemplateStmtInstantiator::VisitContinueStmt(ContinueStmt *S) {
125 return SemaRef.Owned(S->Clone(SemaRef.Context));
126}
127
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000128Sema::OwningStmtResult
129TemplateStmtInstantiator::VisitReturnStmt(ReturnStmt *S) {
Anders Carlssone28be432009-05-15 20:29:28 +0000130 Sema::OwningExprResult Result = SemaRef.ExprEmpty();
131 if (Expr *E = S->getRetValue()) {
132 Result = SemaRef.InstantiateExpr(E, TemplateArgs);
133
134 if (Result.isInvalid())
135 return SemaRef.StmtError();
136 }
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000137
138 return SemaRef.ActOnReturnStmt(S->getReturnLoc(), move(Result));
139}
140
141Sema::OwningStmtResult
142TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) {
143 // FIXME: We need an *easy* RAII way to delete these statements if
144 // something goes wrong.
145 llvm::SmallVector<Stmt *, 16> Statements;
146
147 for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
148 B != BEnd; ++B) {
149 OwningStmtResult Result = Visit(*B);
150 if (Result.isInvalid()) {
151 // FIXME: This should be handled by an RAII destructor.
152 for (unsigned I = 0, N = Statements.size(); I != N; ++I)
153 Statements[I]->Destroy(SemaRef.Context);
154 return SemaRef.StmtError();
155 }
156
157 Statements.push_back(Result.takeAs<Stmt>());
158 }
159
160 return SemaRef.Owned(
161 new (SemaRef.Context) CompoundStmt(SemaRef.Context,
162 &Statements[0],
163 Statements.size(),
164 S->getLBracLoc(),
165 S->getRBracLoc()));
166}
167
Douglas Gregordbb26db2009-05-15 23:57:33 +0000168Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) {
169 // Instantiate left-hand case value.
170 OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs);
171 if (LHS.isInvalid())
172 return SemaRef.StmtError();
173
174 // Instantiate right-hand case value (for the GNU case-range extension).
175 OwningExprResult RHS = SemaRef.InstantiateExpr(S->getRHS(), TemplateArgs);
176 if (RHS.isInvalid())
177 return SemaRef.StmtError();
178
179 // Build the case statement.
180 OwningStmtResult Case = SemaRef.ActOnCaseStmt(S->getCaseLoc(),
181 move(LHS),
182 S->getEllipsisLoc(),
183 move(RHS),
184 S->getColonLoc());
185 if (Case.isInvalid())
186 return SemaRef.StmtError();
187
188 // Instantiate the statement following the case
189 OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(),
190 TemplateArgs);
191 if (SubStmt.isInvalid())
192 return SemaRef.StmtError();
193
194 SemaRef.ActOnCaseStmtBody(Case.get(), move(SubStmt));
195 return move(Case);
196}
197
198Sema::OwningStmtResult
199TemplateStmtInstantiator::VisitDefaultStmt(DefaultStmt *S) {
200 // Instantiate the statement following the default case
201 OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(),
202 TemplateArgs);
203 if (SubStmt.isInvalid())
204 return SemaRef.StmtError();
205
206 return SemaRef.ActOnDefaultStmt(S->getDefaultLoc(),
207 S->getColonLoc(),
208 move(SubStmt),
209 /*CurScope=*/0);
210}
211
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000212Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) {
213 // Instantiate the condition
214 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
215 if (Cond.isInvalid())
216 return SemaRef.StmtError();
217
218 // Instantiate the "then" branch.
219 OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs);
220 if (Then.isInvalid())
221 return SemaRef.StmtError();
222
223 // Instantiate the "else" branch.
224 OwningStmtResult Else = SemaRef.InstantiateStmt(S->getElse(), TemplateArgs);
225 if (Else.isInvalid())
226 return SemaRef.StmtError();
227
228 return SemaRef.ActOnIfStmt(S->getIfLoc(), move(Cond), move(Then),
229 S->getElseLoc(), move(Else));
230}
231
Douglas Gregordbb26db2009-05-15 23:57:33 +0000232Sema::OwningStmtResult
233TemplateStmtInstantiator::VisitSwitchStmt(SwitchStmt *S) {
234 // Instantiate the condition.
235 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
236 if (Cond.isInvalid())
237 return SemaRef.StmtError();
238
239 // Start the switch statement itself.
240 OwningStmtResult Switch = SemaRef.ActOnStartOfSwitchStmt(move(Cond));
241 if (Switch.isInvalid())
242 return SemaRef.StmtError();
243
244 // Instantiate the body of the switch statement.
245 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
246 if (Body.isInvalid())
247 return SemaRef.StmtError();
248
249 // Complete the switch statement.
250 return SemaRef.ActOnFinishSwitchStmt(S->getSwitchLoc(), move(Switch),
251 move(Body));
252}
253
Douglas Gregor4a2e2042009-05-15 21:45:53 +0000254Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *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.ActOnWhileStmt(S->getWhileLoc(), move(Cond), move(Body));
266}
267
Douglas Gregor9f3ca2a2009-05-15 21:56:04 +0000268Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) {
269 // Instantiate the condition
270 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
271 if (Cond.isInvalid())
272 return SemaRef.StmtError();
273
274 // Instantiate the body
275 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
276 if (Body.isInvalid())
277 return SemaRef.StmtError();
278
279 return SemaRef.ActOnDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(),
280 move(Cond));
281}
282
Douglas Gregor5831c6a2009-05-15 22:12:32 +0000283Sema::OwningStmtResult TemplateStmtInstantiator::VisitForStmt(ForStmt *S) {
284 // Instantiate the initialization statement
285 OwningStmtResult Init = SemaRef.InstantiateStmt(S->getInit(), TemplateArgs);
286 if (Init.isInvalid())
287 return SemaRef.StmtError();
288
289 // Instantiate the condition
290 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
291 if (Cond.isInvalid())
292 return SemaRef.StmtError();
293
294 // Instantiate the increment
295 OwningExprResult Inc = SemaRef.InstantiateExpr(S->getInc(), TemplateArgs);
296 if (Inc.isInvalid())
297 return SemaRef.StmtError();
298
299 // Instantiate the body
300 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
301 if (Body.isInvalid())
302 return SemaRef.StmtError();
303
304 return SemaRef.ActOnForStmt(S->getForLoc(), S->getLParenLoc(),
305 move(Init), move(Cond), move(Inc),
306 S->getRParenLoc(), move(Body));
307}
308
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000309Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) {
310 Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs);
311 if (Result.isInvalid())
312 return SemaRef.StmtError();
313
314 return SemaRef.Owned(Result.takeAs<Stmt>());
315}
316
317Sema::OwningStmtResult
318Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
Douglas Gregor50557a72009-05-15 20:47:12 +0000319 if (!S)
320 return Owned((Stmt *)0);
321
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000322 TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
323 return Instantiator.Visit(S);
324}