blob: 9252677025acd46e220ab024be7feab122c67639 [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 Gregor861ce312009-05-15 22:32:39 +000052 OwningStmtResult VisitBreakStmt(BreakStmt *S);
53 OwningStmtResult VisitContinueStmt(ContinueStmt *S);
Douglas Gregorb70ccad2009-05-15 18:22:25 +000054 OwningStmtResult VisitReturnStmt(ReturnStmt *S);
55
56 // Base case. I'm supposed to ignore this.
57 OwningStmtResult VisitStmt(Stmt *S) {
58 S->dump();
59 assert(false && "Cannot instantiate this kind of statement");
60 return SemaRef.StmtError();
61 }
62 };
63}
64
65Sema::OwningStmtResult TemplateStmtInstantiator::VisitDeclStmt(DeclStmt *S) {
66 llvm::SmallVector<Decl *, 8> Decls;
67 for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
68 D != DEnd; ++D) {
69 Decl *Instantiated = SemaRef.InstantiateDecl(*D, SemaRef.CurContext,
70 TemplateArgs);
71 if (!Instantiated)
72 return SemaRef.StmtError();
73
74 Decls.push_back(Instantiated);
75 SemaRef.CurrentInstantiationScope->InstantiatedLocal(cast<VarDecl>(*D),
76 cast<VarDecl>(Instantiated));
77 }
78
79 return SemaRef.Owned(new (SemaRef.Context) DeclStmt(
80 DeclGroupRef::Create(SemaRef.Context,
81 &Decls[0],
82 Decls.size()),
83 S->getStartLoc(),
84 S->getEndLoc()));
85}
86
87Sema::OwningStmtResult TemplateStmtInstantiator::VisitNullStmt(NullStmt *S) {
88 return SemaRef.Owned(S->Clone(SemaRef.Context));
89}
90
91Sema::OwningStmtResult TemplateStmtInstantiator::VisitLabelStmt(LabelStmt *S) {
92 OwningStmtResult SubStmt = Visit(S->getSubStmt());
93
94 if (SubStmt.isInvalid())
95 return SemaRef.StmtError();
96
97 // FIXME: Pass the real colon loc in.
98 return SemaRef.ActOnLabelStmt(S->getIdentLoc(), S->getID(), SourceLocation(),
99 move(SubStmt));
100}
101
102Sema::OwningStmtResult TemplateStmtInstantiator::VisitGotoStmt(GotoStmt *S) {
103 return SemaRef.ActOnGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
104 S->getLabel()->getID());
105}
106
Douglas Gregor861ce312009-05-15 22:32:39 +0000107Sema::OwningStmtResult TemplateStmtInstantiator::VisitBreakStmt(BreakStmt *S) {
108 return SemaRef.Owned(S->Clone(SemaRef.Context));
109}
110
111Sema::OwningStmtResult
112TemplateStmtInstantiator::VisitContinueStmt(ContinueStmt *S) {
113 return SemaRef.Owned(S->Clone(SemaRef.Context));
114}
115
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000116Sema::OwningStmtResult
117TemplateStmtInstantiator::VisitReturnStmt(ReturnStmt *S) {
Anders Carlssone28be432009-05-15 20:29:28 +0000118 Sema::OwningExprResult Result = SemaRef.ExprEmpty();
119 if (Expr *E = S->getRetValue()) {
120 Result = SemaRef.InstantiateExpr(E, TemplateArgs);
121
122 if (Result.isInvalid())
123 return SemaRef.StmtError();
124 }
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000125
126 return SemaRef.ActOnReturnStmt(S->getReturnLoc(), move(Result));
127}
128
129Sema::OwningStmtResult
130TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) {
131 // FIXME: We need an *easy* RAII way to delete these statements if
132 // something goes wrong.
133 llvm::SmallVector<Stmt *, 16> Statements;
134
135 for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
136 B != BEnd; ++B) {
137 OwningStmtResult Result = Visit(*B);
138 if (Result.isInvalid()) {
139 // FIXME: This should be handled by an RAII destructor.
140 for (unsigned I = 0, N = Statements.size(); I != N; ++I)
141 Statements[I]->Destroy(SemaRef.Context);
142 return SemaRef.StmtError();
143 }
144
145 Statements.push_back(Result.takeAs<Stmt>());
146 }
147
148 return SemaRef.Owned(
149 new (SemaRef.Context) CompoundStmt(SemaRef.Context,
150 &Statements[0],
151 Statements.size(),
152 S->getLBracLoc(),
153 S->getRBracLoc()));
154}
155
Douglas Gregordbb26db2009-05-15 23:57:33 +0000156Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) {
157 // Instantiate left-hand case value.
158 OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs);
159 if (LHS.isInvalid())
160 return SemaRef.StmtError();
161
162 // Instantiate right-hand case value (for the GNU case-range extension).
163 OwningExprResult RHS = SemaRef.InstantiateExpr(S->getRHS(), TemplateArgs);
164 if (RHS.isInvalid())
165 return SemaRef.StmtError();
166
167 // Build the case statement.
168 OwningStmtResult Case = SemaRef.ActOnCaseStmt(S->getCaseLoc(),
169 move(LHS),
170 S->getEllipsisLoc(),
171 move(RHS),
172 S->getColonLoc());
173 if (Case.isInvalid())
174 return SemaRef.StmtError();
175
176 // Instantiate the statement following the case
177 OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(),
178 TemplateArgs);
179 if (SubStmt.isInvalid())
180 return SemaRef.StmtError();
181
182 SemaRef.ActOnCaseStmtBody(Case.get(), move(SubStmt));
183 return move(Case);
184}
185
186Sema::OwningStmtResult
187TemplateStmtInstantiator::VisitDefaultStmt(DefaultStmt *S) {
188 // Instantiate the statement following the default case
189 OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(),
190 TemplateArgs);
191 if (SubStmt.isInvalid())
192 return SemaRef.StmtError();
193
194 return SemaRef.ActOnDefaultStmt(S->getDefaultLoc(),
195 S->getColonLoc(),
196 move(SubStmt),
197 /*CurScope=*/0);
198}
199
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000200Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) {
201 // Instantiate the condition
202 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
203 if (Cond.isInvalid())
204 return SemaRef.StmtError();
205
206 // Instantiate the "then" branch.
207 OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs);
208 if (Then.isInvalid())
209 return SemaRef.StmtError();
210
211 // Instantiate the "else" branch.
212 OwningStmtResult Else = SemaRef.InstantiateStmt(S->getElse(), TemplateArgs);
213 if (Else.isInvalid())
214 return SemaRef.StmtError();
215
216 return SemaRef.ActOnIfStmt(S->getIfLoc(), move(Cond), move(Then),
217 S->getElseLoc(), move(Else));
218}
219
Douglas Gregordbb26db2009-05-15 23:57:33 +0000220Sema::OwningStmtResult
221TemplateStmtInstantiator::VisitSwitchStmt(SwitchStmt *S) {
222 // Instantiate the condition.
223 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
224 if (Cond.isInvalid())
225 return SemaRef.StmtError();
226
227 // Start the switch statement itself.
228 OwningStmtResult Switch = SemaRef.ActOnStartOfSwitchStmt(move(Cond));
229 if (Switch.isInvalid())
230 return SemaRef.StmtError();
231
232 // Instantiate the body of the switch statement.
233 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
234 if (Body.isInvalid())
235 return SemaRef.StmtError();
236
237 // Complete the switch statement.
238 return SemaRef.ActOnFinishSwitchStmt(S->getSwitchLoc(), move(Switch),
239 move(Body));
240}
241
Douglas Gregor4a2e2042009-05-15 21:45:53 +0000242Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *S) {
243 // Instantiate the condition
244 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
245 if (Cond.isInvalid())
246 return SemaRef.StmtError();
247
248 // Instantiate the body
249 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
250 if (Body.isInvalid())
251 return SemaRef.StmtError();
252
253 return SemaRef.ActOnWhileStmt(S->getWhileLoc(), move(Cond), move(Body));
254}
255
Douglas Gregor9f3ca2a2009-05-15 21:56:04 +0000256Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) {
257 // Instantiate the condition
258 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
259 if (Cond.isInvalid())
260 return SemaRef.StmtError();
261
262 // Instantiate the body
263 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
264 if (Body.isInvalid())
265 return SemaRef.StmtError();
266
267 return SemaRef.ActOnDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(),
268 move(Cond));
269}
270
Douglas Gregor5831c6a2009-05-15 22:12:32 +0000271Sema::OwningStmtResult TemplateStmtInstantiator::VisitForStmt(ForStmt *S) {
272 // Instantiate the initialization statement
273 OwningStmtResult Init = SemaRef.InstantiateStmt(S->getInit(), TemplateArgs);
274 if (Init.isInvalid())
275 return SemaRef.StmtError();
276
277 // Instantiate the condition
278 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
279 if (Cond.isInvalid())
280 return SemaRef.StmtError();
281
282 // Instantiate the increment
283 OwningExprResult Inc = SemaRef.InstantiateExpr(S->getInc(), TemplateArgs);
284 if (Inc.isInvalid())
285 return SemaRef.StmtError();
286
287 // Instantiate the body
288 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
289 if (Body.isInvalid())
290 return SemaRef.StmtError();
291
292 return SemaRef.ActOnForStmt(S->getForLoc(), S->getLParenLoc(),
293 move(Init), move(Cond), move(Inc),
294 S->getRParenLoc(), move(Body));
295}
296
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000297Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) {
298 Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs);
299 if (Result.isInvalid())
300 return SemaRef.StmtError();
301
302 return SemaRef.Owned(Result.takeAs<Stmt>());
303}
304
305Sema::OwningStmtResult
306Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
Douglas Gregor50557a72009-05-15 20:47:12 +0000307 if (!S)
308 return Owned((Stmt *)0);
309
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000310 TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
311 return Instantiator.Visit(S);
312}