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