blob: 906ea258222de2a8d5c4de78254ffcadc37853e6 [file] [log] [blame]
Douglas Gregor8dbc2692009-03-17 21:15:40 +00001//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl 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 declarations.
10//
11//===----------------------------------------------------------------------===/
12#include "Sema.h"
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/DeclTemplate.h"
15#include "clang/AST/DeclVisitor.h"
16#include "clang/AST/Expr.h"
17#include "llvm/Support/Compiler.h"
18
19using namespace clang;
20
21namespace {
22 class VISIBILITY_HIDDEN TemplateDeclInstantiator
23 : public DeclVisitor<TemplateDeclInstantiator, Decl *>
24 {
25 Sema &SemaRef;
26 DeclContext *Owner;
27 const TemplateArgument *TemplateArgs;
28 unsigned NumTemplateArgs;
29
30 public:
31 typedef Sema::OwningExprResult OwningExprResult;
32
33 TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
34 const TemplateArgument *TemplateArgs,
35 unsigned NumTemplateArgs)
36 : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs),
37 NumTemplateArgs(NumTemplateArgs) { }
38
39 // FIXME: Once we get closer to completion, replace these
40 // manually-written declarations with automatically-generated ones
41 // from clang/AST/DeclNodes.def.
42 Decl *VisitTypedefDecl(TypedefDecl *D);
43 Decl *VisitFieldDecl(FieldDecl *D);
44 Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
45 Decl *VisitEnumDecl(EnumDecl *D);
46
47 // Base case. FIXME: Remove once we can instantiate everything.
48 Decl *VisitDecl(Decl *) {
49 return 0;
50 }
51 };
52}
53
54Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
55 bool Invalid = false;
56 QualType T = D->getUnderlyingType();
57 if (T->isDependentType()) {
58 T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
59 D->getLocation(),
60 D->getDeclName());
61 if (T.isNull()) {
62 Invalid = true;
63 T = SemaRef.Context.IntTy;
64 }
65 }
66
67 // Create the new typedef
68 TypedefDecl *Typedef
69 = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(),
70 D->getIdentifier(), T);
71 if (Invalid)
72 Typedef->setInvalidDecl();
73
74 Owner->addDecl(Typedef);
75 return Typedef;
76}
77
78Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
79 bool Invalid = false;
80 QualType T = D->getType();
81 if (T->isDependentType()) {
82 T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
83 D->getLocation(),
84 D->getDeclName());
85 if (!T.isNull() && T->isFunctionType()) {
86 // C++ [temp.arg.type]p3:
87 // If a declaration acquires a function type through a type
88 // dependent on a template-parameter and this causes a
89 // declaration that does not use the syntactic form of a
90 // function declarator to have function type, the program is
91 // ill-formed.
92 SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
93 << T;
94 T = QualType();
95 Invalid = true;
96 }
97 }
98
99 Expr *BitWidth = D->getBitWidth();
100 if (Invalid)
101 BitWidth = 0;
102 else if (BitWidth) {
103 OwningExprResult InstantiatedBitWidth
104 = SemaRef.InstantiateExpr(BitWidth, TemplateArgs, NumTemplateArgs);
105 if (InstantiatedBitWidth.isInvalid()) {
106 Invalid = true;
107 BitWidth = 0;
108 } else
109 BitWidth = (Expr *)InstantiatedBitWidth.release();
110 }
111
112 FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), T,
113 cast<RecordDecl>(Owner),
114 D->getLocation(),
115 D->isMutable(),
116 BitWidth,
117 D->getAccess(),
118 0);
119 if (Field) {
120 if (Invalid)
121 Field->setInvalidDecl();
122
123 Owner->addDecl(Field);
124 }
125
126 return Field;
127}
128
129Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
130 Expr *AssertExpr = D->getAssertExpr();
131
132 OwningExprResult InstantiatedAssertExpr
133 = SemaRef.InstantiateExpr(AssertExpr, TemplateArgs, NumTemplateArgs);
134 if (InstantiatedAssertExpr.isInvalid())
135 return 0;
136
137 OwningExprResult Message = SemaRef.Clone(D->getMessage());
138 Decl *StaticAssert
139 = (Decl *)SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
140 move(InstantiatedAssertExpr),
141 move(Message));
142 return StaticAssert;
143}
144
145Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
146 EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner,
147 D->getLocation(), D->getIdentifier(),
148 /*PrevDecl=*/0);
149 Owner->addDecl(Enum);
150 Enum->startDefinition();
151
152 llvm::SmallVector<Sema::DeclTy *, 16> Enumerators;
153
154 EnumConstantDecl *LastEnumConst = 0;
155 for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(),
156 ECEnd = D->enumerator_end();
157 EC != ECEnd; ++EC) {
158 // The specified value for the enumerator.
159 OwningExprResult Value = SemaRef.Owned((Expr *)0);
160 if (Expr *UninstValue = EC->getInitExpr())
161 Value = SemaRef.InstantiateExpr(UninstValue,
162 TemplateArgs, NumTemplateArgs);
163
164 // Drop the initial value and continue.
165 bool isInvalid = false;
166 if (Value.isInvalid()) {
167 Value = SemaRef.Owned((Expr *)0);
168 isInvalid = true;
169 }
170
171 EnumConstantDecl *EnumConst
172 = SemaRef.CheckEnumConstant(Enum, LastEnumConst,
173 EC->getLocation(), EC->getIdentifier(),
174 move(Value));
175
176 if (isInvalid) {
177 if (EnumConst)
178 EnumConst->setInvalidDecl();
179 Enum->setInvalidDecl();
180 }
181
182 if (EnumConst) {
183 Enum->addDecl(EnumConst);
184 Enumerators.push_back(EnumConst);
185 LastEnumConst = EnumConst;
186 }
187 }
188
189 SemaRef.ActOnEnumBody(Enum->getLocation(), Enum,
190 &Enumerators[0], Enumerators.size());
191
192 return Enum;
193}
194
195Decl *Sema::InstantiateDecl(Decl *D, DeclContext *Owner,
196 const TemplateArgument *TemplateArgs,
197 unsigned NumTemplateArgs) {
198 TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs,
199 NumTemplateArgs);
200 return Instantiator.Visit(D);
201}
202