blob: c7682342ff00468ac816e19d2f045b6777b4a912 [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);
49 OwningStmtResult VisitReturnStmt(ReturnStmt *S);
50
51 // Base case. I'm supposed to ignore this.
52 OwningStmtResult VisitStmt(Stmt *S) {
53 S->dump();
54 assert(false && "Cannot instantiate this kind of statement");
55 return SemaRef.StmtError();
56 }
57 };
58}
59
60Sema::OwningStmtResult TemplateStmtInstantiator::VisitDeclStmt(DeclStmt *S) {
61 llvm::SmallVector<Decl *, 8> Decls;
62 for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
63 D != DEnd; ++D) {
64 Decl *Instantiated = SemaRef.InstantiateDecl(*D, SemaRef.CurContext,
65 TemplateArgs);
66 if (!Instantiated)
67 return SemaRef.StmtError();
68
69 Decls.push_back(Instantiated);
70 SemaRef.CurrentInstantiationScope->InstantiatedLocal(cast<VarDecl>(*D),
71 cast<VarDecl>(Instantiated));
72 }
73
74 return SemaRef.Owned(new (SemaRef.Context) DeclStmt(
75 DeclGroupRef::Create(SemaRef.Context,
76 &Decls[0],
77 Decls.size()),
78 S->getStartLoc(),
79 S->getEndLoc()));
80}
81
82Sema::OwningStmtResult TemplateStmtInstantiator::VisitNullStmt(NullStmt *S) {
83 return SemaRef.Owned(S->Clone(SemaRef.Context));
84}
85
86Sema::OwningStmtResult TemplateStmtInstantiator::VisitLabelStmt(LabelStmt *S) {
87 OwningStmtResult SubStmt = Visit(S->getSubStmt());
88
89 if (SubStmt.isInvalid())
90 return SemaRef.StmtError();
91
92 // FIXME: Pass the real colon loc in.
93 return SemaRef.ActOnLabelStmt(S->getIdentLoc(), S->getID(), SourceLocation(),
94 move(SubStmt));
95}
96
97Sema::OwningStmtResult TemplateStmtInstantiator::VisitGotoStmt(GotoStmt *S) {
98 return SemaRef.ActOnGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
99 S->getLabel()->getID());
100}
101
102Sema::OwningStmtResult
103TemplateStmtInstantiator::VisitReturnStmt(ReturnStmt *S) {
Anders Carlssone28be432009-05-15 20:29:28 +0000104 Sema::OwningExprResult Result = SemaRef.ExprEmpty();
105 if (Expr *E = S->getRetValue()) {
106 Result = SemaRef.InstantiateExpr(E, TemplateArgs);
107
108 if (Result.isInvalid())
109 return SemaRef.StmtError();
110 }
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000111
112 return SemaRef.ActOnReturnStmt(S->getReturnLoc(), move(Result));
113}
114
115Sema::OwningStmtResult
116TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) {
117 // FIXME: We need an *easy* RAII way to delete these statements if
118 // something goes wrong.
119 llvm::SmallVector<Stmt *, 16> Statements;
120
121 for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
122 B != BEnd; ++B) {
123 OwningStmtResult Result = Visit(*B);
124 if (Result.isInvalid()) {
125 // FIXME: This should be handled by an RAII destructor.
126 for (unsigned I = 0, N = Statements.size(); I != N; ++I)
127 Statements[I]->Destroy(SemaRef.Context);
128 return SemaRef.StmtError();
129 }
130
131 Statements.push_back(Result.takeAs<Stmt>());
132 }
133
134 return SemaRef.Owned(
135 new (SemaRef.Context) CompoundStmt(SemaRef.Context,
136 &Statements[0],
137 Statements.size(),
138 S->getLBracLoc(),
139 S->getRBracLoc()));
140}
141
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000142Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) {
143 // Instantiate the condition
144 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
145 if (Cond.isInvalid())
146 return SemaRef.StmtError();
147
148 // Instantiate the "then" branch.
149 OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs);
150 if (Then.isInvalid())
151 return SemaRef.StmtError();
152
153 // Instantiate the "else" branch.
154 OwningStmtResult Else = SemaRef.InstantiateStmt(S->getElse(), TemplateArgs);
155 if (Else.isInvalid())
156 return SemaRef.StmtError();
157
158 return SemaRef.ActOnIfStmt(S->getIfLoc(), move(Cond), move(Then),
159 S->getElseLoc(), move(Else));
160}
161
Douglas Gregor4a2e2042009-05-15 21:45:53 +0000162Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *S) {
163 // Instantiate the condition
164 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
165 if (Cond.isInvalid())
166 return SemaRef.StmtError();
167
168 // Instantiate the body
169 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
170 if (Body.isInvalid())
171 return SemaRef.StmtError();
172
173 return SemaRef.ActOnWhileStmt(S->getWhileLoc(), move(Cond), move(Body));
174}
175
Douglas Gregor9f3ca2a2009-05-15 21:56:04 +0000176Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) {
177 // Instantiate the condition
178 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
179 if (Cond.isInvalid())
180 return SemaRef.StmtError();
181
182 // Instantiate the body
183 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
184 if (Body.isInvalid())
185 return SemaRef.StmtError();
186
187 return SemaRef.ActOnDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(),
188 move(Cond));
189}
190
Douglas Gregor5831c6a2009-05-15 22:12:32 +0000191Sema::OwningStmtResult TemplateStmtInstantiator::VisitForStmt(ForStmt *S) {
192 // Instantiate the initialization statement
193 OwningStmtResult Init = SemaRef.InstantiateStmt(S->getInit(), TemplateArgs);
194 if (Init.isInvalid())
195 return SemaRef.StmtError();
196
197 // Instantiate the condition
198 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
199 if (Cond.isInvalid())
200 return SemaRef.StmtError();
201
202 // Instantiate the increment
203 OwningExprResult Inc = SemaRef.InstantiateExpr(S->getInc(), TemplateArgs);
204 if (Inc.isInvalid())
205 return SemaRef.StmtError();
206
207 // Instantiate the body
208 OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
209 if (Body.isInvalid())
210 return SemaRef.StmtError();
211
212 return SemaRef.ActOnForStmt(S->getForLoc(), S->getLParenLoc(),
213 move(Init), move(Cond), move(Inc),
214 S->getRParenLoc(), move(Body));
215}
216
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000217Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) {
218 Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs);
219 if (Result.isInvalid())
220 return SemaRef.StmtError();
221
222 return SemaRef.Owned(Result.takeAs<Stmt>());
223}
224
225Sema::OwningStmtResult
226Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
Douglas Gregor50557a72009-05-15 20:47:12 +0000227 if (!S)
228 return Owned((Stmt *)0);
229
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000230 TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
231 return Instantiator.Visit(S);
232}