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