blob: 321f38397d5d5d55dd68cdec9246331f3cdf700c [file] [log] [blame]
Douglas Gregorb55fdf82010-12-15 17:38:57 +00001//===------- SemaTemplateVariadic.cpp - C++ Variadic Templates ------------===/
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 semantic analysis for C++0x variadic templates.
10//===----------------------------------------------------------------------===/
11
12#include "clang/Sema/Sema.h"
Douglas Gregord2fa7662010-12-20 02:24:11 +000013#include "clang/Sema/ParsedTemplate.h"
Douglas Gregorb55fdf82010-12-15 17:38:57 +000014#include "clang/Sema/SemaInternal.h"
15#include "clang/AST/Expr.h"
Douglas Gregor1da294a2010-12-15 19:43:21 +000016#include "clang/AST/RecursiveASTVisitor.h"
Douglas Gregorb55fdf82010-12-15 17:38:57 +000017#include "clang/AST/TypeLoc.h"
18
19using namespace clang;
20
Douglas Gregor1da294a2010-12-15 19:43:21 +000021//----------------------------------------------------------------------------
22// Visitor that collects unexpanded parameter packs
23//----------------------------------------------------------------------------
24
25// FIXME: No way to easily map from TemplateTypeParmTypes to
26// TemplateTypeParmDecls, so we have this horrible PointerUnion.
27typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,
28 SourceLocation> UnexpandedParameterPack;
29
30namespace {
31 /// \brief A class that collects unexpanded parameter packs.
32 class CollectUnexpandedParameterPacksVisitor :
33 public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
34 {
35 typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
36 inherited;
37
38 llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
39
40 public:
41 explicit CollectUnexpandedParameterPacksVisitor(
42 llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
43 : Unexpanded(Unexpanded) { }
44
45 //------------------------------------------------------------------------
46 // Recording occurrences of (unexpanded) parameter packs.
47 //------------------------------------------------------------------------
48
49 /// \brief Record occurrences of template type parameter packs.
50 bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
51 if (TL.getTypePtr()->isParameterPack())
52 Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc()));
53 return true;
54 }
55
56 /// \brief Record occurrences of template type parameter packs
57 /// when we don't have proper source-location information for
58 /// them.
59 ///
60 /// Ideally, this routine would never be used.
61 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
62 if (T->isParameterPack())
63 Unexpanded.push_back(std::make_pair(T, SourceLocation()));
64
65 return true;
66 }
67
68 // FIXME: Record occurrences of non-type and template template
69 // parameter packs.
70
71 // FIXME: Once we have pack expansions in the AST, block their
72 // traversal.
73
74 //------------------------------------------------------------------------
75 // Pruning the search for unexpanded parameter packs.
76 //------------------------------------------------------------------------
77
78 /// \brief Suppress traversal into statements and expressions that
79 /// do not contain unexpanded parameter packs.
80 bool TraverseStmt(Stmt *S) {
81 if (Expr *E = dyn_cast_or_null<Expr>(S))
82 if (E->containsUnexpandedParameterPack())
83 return inherited::TraverseStmt(E);
84
85 return true;
86 }
87
88 /// \brief Suppress traversal into types that do not contain
89 /// unexpanded parameter packs.
90 bool TraverseType(QualType T) {
91 if (!T.isNull() && T->containsUnexpandedParameterPack())
92 return inherited::TraverseType(T);
93
94 return true;
95 }
96
97 /// \brief Suppress traversel into types with location information
98 /// that do not contain unexpanded parameter packs.
99 bool TraverseTypeLoc(TypeLoc TL) {
100 if (!TL.getType().isNull() && TL.
101 getType()->containsUnexpandedParameterPack())
102 return inherited::TraverseTypeLoc(TL);
103
104 return true;
105 }
106
Douglas Gregora8461bb2010-12-15 21:57:59 +0000107 /// \brief Suppress traversal of non-parameter declarations, since
108 /// they cannot contain unexpanded parameter packs.
109 bool TraverseDecl(Decl *D) {
110 if (D && isa<ParmVarDecl>(D))
111 return inherited::TraverseDecl(D);
112
113 return true;
114 }
Douglas Gregor1da294a2010-12-15 19:43:21 +0000115 };
116}
117
118/// \brief Diagnose all of the unexpanded parameter packs in the given
119/// vector.
120static void
121DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc,
122 Sema::UnexpandedParameterPackContext UPPC,
123 const llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
124 llvm::SmallVector<SourceLocation, 4> Locations;
125 llvm::SmallVector<IdentifierInfo *, 4> Names;
126 llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
127
128 for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
129 IdentifierInfo *Name = 0;
130 if (const TemplateTypeParmType *TTP
131 = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
132 Name = TTP->getName();
133 else
134 Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
135
136 if (Name && NamesKnown.insert(Name))
137 Names.push_back(Name);
138
139 if (Unexpanded[I].second.isValid())
140 Locations.push_back(Unexpanded[I].second);
141 }
142
143 DiagnosticBuilder DB
144 = Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0)
145 << (int)UPPC
146 : Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1)
147 << (int)UPPC << Names[0]
148 : Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2)
149 << (int)UPPC << Names[0] << Names[1]
150 : S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
151 << (int)UPPC << Names[0] << Names[1];
152
153 for (unsigned I = 0, N = Locations.size(); I != N; ++I)
154 DB << SourceRange(Locations[I]);
155}
156
Douglas Gregorb55fdf82010-12-15 17:38:57 +0000157bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
158 TypeSourceInfo *T,
159 UnexpandedParameterPackContext UPPC) {
160 // C++0x [temp.variadic]p5:
161 // An appearance of a name of a parameter pack that is not expanded is
162 // ill-formed.
163 if (!T->getType()->containsUnexpandedParameterPack())
164 return false;
165
Douglas Gregor1da294a2010-12-15 19:43:21 +0000166 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
167 CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
168 T->getTypeLoc());
169 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
170 DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
Douglas Gregorb55fdf82010-12-15 17:38:57 +0000171 return true;
172}
173
174bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
Douglas Gregorc4356532010-12-16 00:46:58 +0000175 UnexpandedParameterPackContext UPPC) {
Douglas Gregorb55fdf82010-12-15 17:38:57 +0000176 // C++0x [temp.variadic]p5:
177 // An appearance of a name of a parameter pack that is not expanded is
178 // ill-formed.
179 if (!E->containsUnexpandedParameterPack())
180 return false;
181
Douglas Gregor1da294a2010-12-15 19:43:21 +0000182 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
183 CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
184 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
185 DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded);
Douglas Gregorb55fdf82010-12-15 17:38:57 +0000186 return true;
187}
Douglas Gregorc4356532010-12-16 00:46:58 +0000188
189bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
190 UnexpandedParameterPackContext UPPC) {
191 // C++0x [temp.variadic]p5:
192 // An appearance of a name of a parameter pack that is not expanded is
193 // ill-formed.
194 if (!SS.getScopeRep() ||
195 !SS.getScopeRep()->containsUnexpandedParameterPack())
196 return false;
197
198 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
199 CollectUnexpandedParameterPacksVisitor(Unexpanded)
200 .TraverseNestedNameSpecifier(SS.getScopeRep());
201 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
202 DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(),
203 UPPC, Unexpanded);
204 return true;
205}
206
207bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
208 UnexpandedParameterPackContext UPPC) {
209 // C++0x [temp.variadic]p5:
210 // An appearance of a name of a parameter pack that is not expanded is
211 // ill-formed.
212 switch (NameInfo.getName().getNameKind()) {
213 case DeclarationName::Identifier:
214 case DeclarationName::ObjCZeroArgSelector:
215 case DeclarationName::ObjCOneArgSelector:
216 case DeclarationName::ObjCMultiArgSelector:
217 case DeclarationName::CXXOperatorName:
218 case DeclarationName::CXXLiteralOperatorName:
219 case DeclarationName::CXXUsingDirective:
220 return false;
221
222 case DeclarationName::CXXConstructorName:
223 case DeclarationName::CXXDestructorName:
224 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor062ecac2010-12-16 17:19:19 +0000225 // FIXME: We shouldn't need this null check!
Douglas Gregor6ab34af2010-12-16 01:40:04 +0000226 if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
227 return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC);
228
229 if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack())
Douglas Gregorc4356532010-12-16 00:46:58 +0000230 return false;
Douglas Gregor6ab34af2010-12-16 01:40:04 +0000231
Douglas Gregorc4356532010-12-16 00:46:58 +0000232 break;
233 }
234
235 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
236 CollectUnexpandedParameterPacksVisitor(Unexpanded)
Douglas Gregor6ab34af2010-12-16 01:40:04 +0000237 .TraverseType(NameInfo.getName().getCXXNameType());
Douglas Gregorc4356532010-12-16 00:46:58 +0000238 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
239 DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
240 return true;
241}
Douglas Gregor6ff1fbf2010-12-16 08:48:57 +0000242
243bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
244 TemplateName Template,
245 UnexpandedParameterPackContext UPPC) {
246
247 if (Template.isNull() || !Template.containsUnexpandedParameterPack())
248 return false;
249
250 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
251 CollectUnexpandedParameterPacksVisitor(Unexpanded)
252 .TraverseTemplateName(Template);
253 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
254 DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
255 return true;
256}
257
Douglas Gregord2fa7662010-12-20 02:24:11 +0000258ParsedTemplateArgument
259Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
260 SourceLocation EllipsisLoc) {
261 if (Arg.isInvalid())
262 return Arg;
263
264 switch (Arg.getKind()) {
265 case ParsedTemplateArgument::Type: {
266 TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc);
267 if (Result.isInvalid())
268 return ParsedTemplateArgument();
269
270 return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
271 Arg.getLocation());
272 }
273
274 case ParsedTemplateArgument::NonType:
275 Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
276 << 0;
277 return ParsedTemplateArgument();
278
279 case ParsedTemplateArgument::Template:
280 Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
281 << 1;
282 return ParsedTemplateArgument();
283 }
284 llvm_unreachable("Unhandled template argument kind?");
285 return ParsedTemplateArgument();
286}
287
288TypeResult Sema::ActOnPackExpansion(ParsedType Type,
289 SourceLocation EllipsisLoc) {
290 TypeSourceInfo *TSInfo;
291 GetTypeFromParser(Type, &TSInfo);
292 if (!TSInfo)
293 return true;
294
295 // C++0x [temp.variadic]p5:
296 // The pattern of a pack expansion shall name one or more
297 // parameter packs that are not expanded by a nested pack
298 // expansion.
299 if (!TSInfo->getType()->containsUnexpandedParameterPack()) {
300 Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
301 << TSInfo->getTypeLoc().getSourceRange();
302 return true;
303 }
304
305 // Create the pack expansion type and source-location information.
306 QualType Result = Context.getPackExpansionType(TSInfo->getType());
307 TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
308 PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
309 TL.setEllipsisLoc(EllipsisLoc);
310
311 // Copy over the source-location information from the type.
312 memcpy(TL.getNextTypeLoc().getOpaqueData(),
313 TSInfo->getTypeLoc().getOpaqueData(),
314 TSInfo->getTypeLoc().getFullDataSize());
315 return CreateParsedType(Result, TSResult);
316}