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