blob: 8bdb42b58f6767ea78c62f598a40670b645a914b [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 Gregorb70ccad2009-05-15 18:22:25 +000043 OwningStmtResult VisitExpr(Expr *E);
44 OwningStmtResult VisitLabelStmt(LabelStmt *S);
45 OwningStmtResult VisitGotoStmt(GotoStmt *S);
46 OwningStmtResult VisitReturnStmt(ReturnStmt *S);
47
48 // Base case. I'm supposed to ignore this.
49 OwningStmtResult VisitStmt(Stmt *S) {
50 S->dump();
51 assert(false && "Cannot instantiate this kind of statement");
52 return SemaRef.StmtError();
53 }
54 };
55}
56
57Sema::OwningStmtResult TemplateStmtInstantiator::VisitDeclStmt(DeclStmt *S) {
58 llvm::SmallVector<Decl *, 8> Decls;
59 for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
60 D != DEnd; ++D) {
61 Decl *Instantiated = SemaRef.InstantiateDecl(*D, SemaRef.CurContext,
62 TemplateArgs);
63 if (!Instantiated)
64 return SemaRef.StmtError();
65
66 Decls.push_back(Instantiated);
67 SemaRef.CurrentInstantiationScope->InstantiatedLocal(cast<VarDecl>(*D),
68 cast<VarDecl>(Instantiated));
69 }
70
71 return SemaRef.Owned(new (SemaRef.Context) DeclStmt(
72 DeclGroupRef::Create(SemaRef.Context,
73 &Decls[0],
74 Decls.size()),
75 S->getStartLoc(),
76 S->getEndLoc()));
77}
78
79Sema::OwningStmtResult TemplateStmtInstantiator::VisitNullStmt(NullStmt *S) {
80 return SemaRef.Owned(S->Clone(SemaRef.Context));
81}
82
83Sema::OwningStmtResult TemplateStmtInstantiator::VisitLabelStmt(LabelStmt *S) {
84 OwningStmtResult SubStmt = Visit(S->getSubStmt());
85
86 if (SubStmt.isInvalid())
87 return SemaRef.StmtError();
88
89 // FIXME: Pass the real colon loc in.
90 return SemaRef.ActOnLabelStmt(S->getIdentLoc(), S->getID(), SourceLocation(),
91 move(SubStmt));
92}
93
94Sema::OwningStmtResult TemplateStmtInstantiator::VisitGotoStmt(GotoStmt *S) {
95 return SemaRef.ActOnGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
96 S->getLabel()->getID());
97}
98
99Sema::OwningStmtResult
100TemplateStmtInstantiator::VisitReturnStmt(ReturnStmt *S) {
Anders Carlssona52aac42009-05-15 20:10:48 +0000101 Sema::OwningExprResult Result =
102 SemaRef.InstantiateExpr(S->getRetValue(), TemplateArgs);
103 if (Result.isInvalid())
104 return SemaRef.StmtError();
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000105
106 return SemaRef.ActOnReturnStmt(S->getReturnLoc(), move(Result));
107}
108
109Sema::OwningStmtResult
110TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) {
111 // FIXME: We need an *easy* RAII way to delete these statements if
112 // something goes wrong.
113 llvm::SmallVector<Stmt *, 16> Statements;
114
115 for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
116 B != BEnd; ++B) {
117 OwningStmtResult Result = Visit(*B);
118 if (Result.isInvalid()) {
119 // FIXME: This should be handled by an RAII destructor.
120 for (unsigned I = 0, N = Statements.size(); I != N; ++I)
121 Statements[I]->Destroy(SemaRef.Context);
122 return SemaRef.StmtError();
123 }
124
125 Statements.push_back(Result.takeAs<Stmt>());
126 }
127
128 return SemaRef.Owned(
129 new (SemaRef.Context) CompoundStmt(SemaRef.Context,
130 &Statements[0],
131 Statements.size(),
132 S->getLBracLoc(),
133 S->getRBracLoc()));
134}
135
Douglas Gregord06f6ca2009-05-15 18:53:42 +0000136Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) {
137 // Instantiate the condition
138 OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
139 if (Cond.isInvalid())
140 return SemaRef.StmtError();
141
142 // Instantiate the "then" branch.
143 OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs);
144 if (Then.isInvalid())
145 return SemaRef.StmtError();
146
147 // Instantiate the "else" branch.
148 OwningStmtResult Else = SemaRef.InstantiateStmt(S->getElse(), TemplateArgs);
149 if (Else.isInvalid())
150 return SemaRef.StmtError();
151
152 return SemaRef.ActOnIfStmt(S->getIfLoc(), move(Cond), move(Then),
153 S->getElseLoc(), move(Else));
154}
155
Douglas Gregorb70ccad2009-05-15 18:22:25 +0000156Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) {
157 Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs);
158 if (Result.isInvalid())
159 return SemaRef.StmtError();
160
161 return SemaRef.Owned(Result.takeAs<Stmt>());
162}
163
164Sema::OwningStmtResult
165Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
166 TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
167 return Instantiator.Visit(S);
168}