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