blob: d59f85953f8987a9b9fa252c4e25b8ebb20b3da6 [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 Gregord06f6ca2009-05-15 18:53:42 +000042 OwningStmtResult VisitIfStmt(IfStmt *S);
Douglas Gregor4a2e2042009-05-15 21:45:53 +000043 OwningStmtResult VisitWhileStmt(WhileStmt *S);
Douglas Gregor9f3ca2a2009-05-15 21:56:04 +000044 OwningStmtResult VisitDoStmt(DoStmt *S);
Douglas Gregor5831c6a2009-05-15 22:12:32 +000045 OwningStmtResult VisitForStmt(ForStmt *S);
Douglas Gregorb70ccad2009-05-15 18:22:25 +000046 OwningStmtResult VisitExpr(Expr *E);
47 OwningStmtResult VisitLabelStmt(LabelStmt *S);
48 OwningStmtResult VisitGotoStmt(GotoStmt *S);
Douglas Gregor861ce312009-05-15 22:32:39 +000049 OwningStmtResult VisitBreakStmt(BreakStmt *S);
50 OwningStmtResult VisitContinueStmt(ContinueStmt *S);
Douglas Gregorb70ccad2009-05-15 18:22:25 +000051 OwningStmtResult VisitReturnStmt(ReturnStmt *S);
52
53 // Base case. I'm supposed to ignore this.
54 OwningStmtResult VisitStmt(Stmt *S) {
55 S->dump();
56 assert(false && "Cannot instantiate this kind of statement");
57 return SemaRef.StmtError();
58 }
59 };
60}
61
62Sema::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 Gregor861ce312009-05-15 22:32:39 +0000104Sema::OwningStmtResult TemplateStmtInstantiator::VisitBreakStmt(BreakStmt *S) {
105 return SemaRef.Owned(S->Clone(SemaRef.Context));
106}
107
108Sema::OwningStmtResult
109TemplateStmtInstantiator::VisitContinueStmt(ContinueStmt *S) {
110 return SemaRef.Owned(S->Clone(SemaRef.Context));
111}
112
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000113Sema::OwningStmtResult
114TemplateStmtInstantiator::VisitReturnStmt(ReturnStmt *S) {
Anders Carlssone28be432009-05-15 20:29:28 +0000115 Sema::OwningExprResult Result = SemaRef.ExprEmpty();
116 if (Expr *E = S->getRetValue()) {
117 Result = SemaRef.InstantiateExpr(E, TemplateArgs);
118
119 if (Result.isInvalid())
120 return SemaRef.StmtError();
121 }
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000122
123 return SemaRef.ActOnReturnStmt(S->getReturnLoc(), move(Result));
124}
125
126Sema::OwningStmtResult
127TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) {
128 // FIXME: We need an *easy* RAII way to delete these statements if
129 // something goes wrong.
130 llvm::SmallVector<Stmt *, 16> Statements;
131
132 for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
133 B != BEnd; ++B) {
134 OwningStmtResult Result = Visit(*B);
135 if (Result.isInvalid()) {
136 // FIXME: This should be handled by an RAII destructor.
137 for (unsigned I = 0, N = Statements.size(); I != N; ++I)
138 Statements[I]->Destroy(SemaRef.Context);
139 return SemaRef.StmtError();
140 }
141
142 Statements.push_back(Result.takeAs<Stmt>());
143 }
144
145 return SemaRef.Owned(
146 new (SemaRef.Context) CompoundStmt(SemaRef.Context,
147 &Statements[0],
148 Statements.size(),
149 S->getLBracLoc(),
150 S->getRBracLoc()));
151}
152
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000153Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) {
154 // Instantiate the condition
155 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
156 if (Cond.isInvalid())
157 return SemaRef.StmtError();
158
159 // Instantiate the "then" branch.
160 OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs);
161 if (Then.isInvalid())
162 return SemaRef.StmtError();
163
164 // Instantiate the "else" branch.
165 OwningStmtResult Else = SemaRef.InstantiateStmt(S->getElse(), TemplateArgs);
166 if (Else.isInvalid())
167 return SemaRef.StmtError();
168
169 return SemaRef.ActOnIfStmt(S->getIfLoc(), move(Cond), move(Then),
170 S->getElseLoc(), move(Else));
171}
172
Douglas Gregor4a2e2042009-05-15 21:45:53 +0000173Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *S) {
174 // Instantiate the condition
175 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
176 if (Cond.isInvalid())
177 return SemaRef.StmtError();
178
179 // Instantiate the body
180 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
181 if (Body.isInvalid())
182 return SemaRef.StmtError();
183
184 return SemaRef.ActOnWhileStmt(S->getWhileLoc(), move(Cond), move(Body));
185}
186
Douglas Gregor9f3ca2a2009-05-15 21:56:04 +0000187Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) {
188 // Instantiate the condition
189 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
190 if (Cond.isInvalid())
191 return SemaRef.StmtError();
192
193 // Instantiate the body
194 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
195 if (Body.isInvalid())
196 return SemaRef.StmtError();
197
198 return SemaRef.ActOnDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(),
199 move(Cond));
200}
201
Douglas Gregor5831c6a2009-05-15 22:12:32 +0000202Sema::OwningStmtResult TemplateStmtInstantiator::VisitForStmt(ForStmt *S) {
203 // Instantiate the initialization statement
204 OwningStmtResult Init = SemaRef.InstantiateStmt(S->getInit(), TemplateArgs);
205 if (Init.isInvalid())
206 return SemaRef.StmtError();
207
208 // Instantiate the condition
209 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
210 if (Cond.isInvalid())
211 return SemaRef.StmtError();
212
213 // Instantiate the increment
214 OwningExprResult Inc = SemaRef.InstantiateExpr(S->getInc(), TemplateArgs);
215 if (Inc.isInvalid())
216 return SemaRef.StmtError();
217
218 // Instantiate the body
219 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
220 if (Body.isInvalid())
221 return SemaRef.StmtError();
222
223 return SemaRef.ActOnForStmt(S->getForLoc(), S->getLParenLoc(),
224 move(Init), move(Cond), move(Inc),
225 S->getRParenLoc(), move(Body));
226}
227
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000228Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) {
229 Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs);
230 if (Result.isInvalid())
231 return SemaRef.StmtError();
232
233 return SemaRef.Owned(Result.takeAs<Stmt>());
234}
235
236Sema::OwningStmtResult
237Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
Douglas Gregor50557a72009-05-15 20:47:12 +0000238 if (!S)
239 return Owned((Stmt *)0);
240
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000241 TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
242 return Instantiator.Visit(S);
243}