blob: f2651ef65cf47f035bdf59b12d0f3d2b9b5c6e59 [file] [log] [blame]
Douglas Gregorc4633352010-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 Gregor7536dd52010-12-20 02:24:11 +000013#include "clang/Sema/ParsedTemplate.h"
Douglas Gregorc4633352010-12-15 17:38:57 +000014#include "clang/Sema/SemaInternal.h"
Douglas Gregor8491ffe2010-12-20 22:05:00 +000015#include "clang/Sema/Template.h"
Douglas Gregorc4633352010-12-15 17:38:57 +000016#include "clang/AST/Expr.h"
Douglas Gregor9ef75892010-12-15 19:43:21 +000017#include "clang/AST/RecursiveASTVisitor.h"
Douglas Gregorc4633352010-12-15 17:38:57 +000018#include "clang/AST/TypeLoc.h"
19
20using namespace clang;
21
Douglas Gregor9ef75892010-12-15 19:43:21 +000022//----------------------------------------------------------------------------
23// Visitor that collects unexpanded parameter packs
24//----------------------------------------------------------------------------
25
Douglas Gregor9ef75892010-12-15 19:43:21 +000026namespace {
27 /// \brief A class that collects unexpanded parameter packs.
28 class CollectUnexpandedParameterPacksVisitor :
29 public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
30 {
31 typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
32 inherited;
33
34 llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
35
36 public:
37 explicit CollectUnexpandedParameterPacksVisitor(
38 llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
39 : Unexpanded(Unexpanded) { }
40
Douglas Gregora40bc722010-12-20 23:07:20 +000041 bool shouldWalkTypesOfTypeLocs() const { return false; }
42
Douglas Gregor9ef75892010-12-15 19:43:21 +000043 //------------------------------------------------------------------------
44 // Recording occurrences of (unexpanded) parameter packs.
45 //------------------------------------------------------------------------
46
47 /// \brief Record occurrences of template type parameter packs.
48 bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
49 if (TL.getTypePtr()->isParameterPack())
50 Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc()));
51 return true;
52 }
53
54 /// \brief Record occurrences of template type parameter packs
55 /// when we don't have proper source-location information for
56 /// them.
57 ///
58 /// Ideally, this routine would never be used.
59 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
60 if (T->isParameterPack())
61 Unexpanded.push_back(std::make_pair(T, SourceLocation()));
62
63 return true;
64 }
65
66 // FIXME: Record occurrences of non-type and template template
67 // parameter packs.
68
69 // FIXME: Once we have pack expansions in the AST, block their
70 // traversal.
71
72 //------------------------------------------------------------------------
73 // Pruning the search for unexpanded parameter packs.
74 //------------------------------------------------------------------------
75
76 /// \brief Suppress traversal into statements and expressions that
77 /// do not contain unexpanded parameter packs.
78 bool TraverseStmt(Stmt *S) {
79 if (Expr *E = dyn_cast_or_null<Expr>(S))
80 if (E->containsUnexpandedParameterPack())
81 return inherited::TraverseStmt(E);
82
83 return true;
84 }
85
86 /// \brief Suppress traversal into types that do not contain
87 /// unexpanded parameter packs.
88 bool TraverseType(QualType T) {
89 if (!T.isNull() && T->containsUnexpandedParameterPack())
90 return inherited::TraverseType(T);
91
92 return true;
93 }
94
95 /// \brief Suppress traversel into types with location information
96 /// that do not contain unexpanded parameter packs.
97 bool TraverseTypeLoc(TypeLoc TL) {
98 if (!TL.getType().isNull() && TL.
99 getType()->containsUnexpandedParameterPack())
100 return inherited::TraverseTypeLoc(TL);
101
102 return true;
103 }
104
Douglas Gregorcff163e2010-12-15 21:57:59 +0000105 /// \brief Suppress traversal of non-parameter declarations, since
106 /// they cannot contain unexpanded parameter packs.
107 bool TraverseDecl(Decl *D) {
108 if (D && isa<ParmVarDecl>(D))
109 return inherited::TraverseDecl(D);
110
111 return true;
112 }
Douglas Gregor9ef75892010-12-15 19:43:21 +0000113 };
114}
115
116/// \brief Diagnose all of the unexpanded parameter packs in the given
117/// vector.
118static void
119DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc,
120 Sema::UnexpandedParameterPackContext UPPC,
121 const llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
122 llvm::SmallVector<SourceLocation, 4> Locations;
123 llvm::SmallVector<IdentifierInfo *, 4> Names;
124 llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
125
126 for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
127 IdentifierInfo *Name = 0;
128 if (const TemplateTypeParmType *TTP
129 = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
130 Name = TTP->getName();
131 else
132 Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
133
134 if (Name && NamesKnown.insert(Name))
135 Names.push_back(Name);
136
137 if (Unexpanded[I].second.isValid())
138 Locations.push_back(Unexpanded[I].second);
139 }
140
141 DiagnosticBuilder DB
142 = Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0)
143 << (int)UPPC
144 : Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1)
145 << (int)UPPC << Names[0]
146 : Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2)
147 << (int)UPPC << Names[0] << Names[1]
148 : S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
149 << (int)UPPC << Names[0] << Names[1];
150
151 for (unsigned I = 0, N = Locations.size(); I != N; ++I)
152 DB << SourceRange(Locations[I]);
153}
154
Douglas Gregorc4633352010-12-15 17:38:57 +0000155bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
156 TypeSourceInfo *T,
157 UnexpandedParameterPackContext UPPC) {
158 // C++0x [temp.variadic]p5:
159 // An appearance of a name of a parameter pack that is not expanded is
160 // ill-formed.
161 if (!T->getType()->containsUnexpandedParameterPack())
162 return false;
163
Douglas Gregor9ef75892010-12-15 19:43:21 +0000164 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
165 CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
166 T->getTypeLoc());
167 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
168 DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
Douglas Gregorc4633352010-12-15 17:38:57 +0000169 return true;
170}
171
172bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
Douglas Gregor56c04582010-12-16 00:46:58 +0000173 UnexpandedParameterPackContext UPPC) {
Douglas Gregorc4633352010-12-15 17:38:57 +0000174 // C++0x [temp.variadic]p5:
175 // An appearance of a name of a parameter pack that is not expanded is
176 // ill-formed.
177 if (!E->containsUnexpandedParameterPack())
178 return false;
179
Douglas Gregor9ef75892010-12-15 19:43:21 +0000180 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
181 CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
182 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
183 DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded);
Douglas Gregorc4633352010-12-15 17:38:57 +0000184 return true;
185}
Douglas Gregor56c04582010-12-16 00:46:58 +0000186
187bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
188 UnexpandedParameterPackContext UPPC) {
189 // C++0x [temp.variadic]p5:
190 // An appearance of a name of a parameter pack that is not expanded is
191 // ill-formed.
192 if (!SS.getScopeRep() ||
193 !SS.getScopeRep()->containsUnexpandedParameterPack())
194 return false;
195
196 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
197 CollectUnexpandedParameterPacksVisitor(Unexpanded)
198 .TraverseNestedNameSpecifier(SS.getScopeRep());
199 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
200 DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(),
201 UPPC, Unexpanded);
202 return true;
203}
204
205bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
206 UnexpandedParameterPackContext UPPC) {
207 // C++0x [temp.variadic]p5:
208 // An appearance of a name of a parameter pack that is not expanded is
209 // ill-formed.
210 switch (NameInfo.getName().getNameKind()) {
211 case DeclarationName::Identifier:
212 case DeclarationName::ObjCZeroArgSelector:
213 case DeclarationName::ObjCOneArgSelector:
214 case DeclarationName::ObjCMultiArgSelector:
215 case DeclarationName::CXXOperatorName:
216 case DeclarationName::CXXLiteralOperatorName:
217 case DeclarationName::CXXUsingDirective:
218 return false;
219
220 case DeclarationName::CXXConstructorName:
221 case DeclarationName::CXXDestructorName:
222 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor099ffe82010-12-16 17:19:19 +0000223 // FIXME: We shouldn't need this null check!
Douglas Gregor0762bfd2010-12-16 01:40:04 +0000224 if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
225 return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC);
226
227 if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack())
Douglas Gregor56c04582010-12-16 00:46:58 +0000228 return false;
Douglas Gregor0762bfd2010-12-16 01:40:04 +0000229
Douglas Gregor56c04582010-12-16 00:46:58 +0000230 break;
231 }
232
233 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
234 CollectUnexpandedParameterPacksVisitor(Unexpanded)
Douglas Gregor0762bfd2010-12-16 01:40:04 +0000235 .TraverseType(NameInfo.getName().getCXXNameType());
Douglas Gregor56c04582010-12-16 00:46:58 +0000236 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
237 DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
238 return true;
239}
Douglas Gregor6f526752010-12-16 08:48:57 +0000240
241bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
242 TemplateName Template,
243 UnexpandedParameterPackContext UPPC) {
244
245 if (Template.isNull() || !Template.containsUnexpandedParameterPack())
246 return false;
247
248 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
249 CollectUnexpandedParameterPacksVisitor(Unexpanded)
250 .TraverseTemplateName(Template);
251 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
252 DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
253 return true;
254}
255
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000256void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
257 llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
258 CollectUnexpandedParameterPacksVisitor(Unexpanded)
259 .TraverseTemplateArgumentLoc(Arg);
260}
261
Douglas Gregorb99268b2010-12-21 00:52:54 +0000262void Sema::collectUnexpandedParameterPacks(QualType T,
263 llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
264 CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);
265}
266
Douglas Gregor7536dd52010-12-20 02:24:11 +0000267ParsedTemplateArgument
268Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
269 SourceLocation EllipsisLoc) {
270 if (Arg.isInvalid())
271 return Arg;
272
273 switch (Arg.getKind()) {
274 case ParsedTemplateArgument::Type: {
275 TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc);
276 if (Result.isInvalid())
277 return ParsedTemplateArgument();
278
279 return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
280 Arg.getLocation());
281 }
282
283 case ParsedTemplateArgument::NonType:
284 Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
285 << 0;
286 return ParsedTemplateArgument();
287
288 case ParsedTemplateArgument::Template:
289 Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
290 << 1;
291 return ParsedTemplateArgument();
292 }
293 llvm_unreachable("Unhandled template argument kind?");
294 return ParsedTemplateArgument();
295}
296
297TypeResult Sema::ActOnPackExpansion(ParsedType Type,
298 SourceLocation EllipsisLoc) {
299 TypeSourceInfo *TSInfo;
300 GetTypeFromParser(Type, &TSInfo);
301 if (!TSInfo)
302 return true;
303
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000304 TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc);
305 if (!TSResult)
306 return true;
307
308 return CreateParsedType(TSResult->getType(), TSResult);
309}
310
311TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
312 SourceLocation EllipsisLoc) {
Douglas Gregor7536dd52010-12-20 02:24:11 +0000313 // C++0x [temp.variadic]p5:
314 // The pattern of a pack expansion shall name one or more
315 // parameter packs that are not expanded by a nested pack
316 // expansion.
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000317 if (!Pattern->getType()->containsUnexpandedParameterPack()) {
Douglas Gregor7536dd52010-12-20 02:24:11 +0000318 Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000319 << Pattern->getTypeLoc().getSourceRange();
320 return 0;
Douglas Gregor7536dd52010-12-20 02:24:11 +0000321 }
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000322
Douglas Gregor7536dd52010-12-20 02:24:11 +0000323 // Create the pack expansion type and source-location information.
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000324 QualType Result = Context.getPackExpansionType(Pattern->getType());
Douglas Gregor7536dd52010-12-20 02:24:11 +0000325 TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
326 PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
327 TL.setEllipsisLoc(EllipsisLoc);
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000328
Douglas Gregor7536dd52010-12-20 02:24:11 +0000329 // Copy over the source-location information from the type.
330 memcpy(TL.getNextTypeLoc().getOpaqueData(),
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000331 Pattern->getTypeLoc().getOpaqueData(),
332 Pattern->getTypeLoc().getFullDataSize());
333 return TSResult;
Douglas Gregor7536dd52010-12-20 02:24:11 +0000334}
Douglas Gregorb99268b2010-12-21 00:52:54 +0000335
336
337bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
338 SourceRange PatternRange,
339 const UnexpandedParameterPack *Unexpanded,
340 unsigned NumUnexpanded,
341 const MultiLevelTemplateArgumentList &TemplateArgs,
342 bool &ShouldExpand,
343 unsigned &NumExpansions) {
344 ShouldExpand = true;
345 std::pair<IdentifierInfo *, SourceLocation> FirstPack;
346 bool HaveFirstPack = false;
347
348 for (unsigned I = 0; I != NumUnexpanded; ++I) {
349 // Compute the depth and index for this parameter pack.
350 unsigned Depth;
351 unsigned Index;
352 IdentifierInfo *Name;
353
354 if (const TemplateTypeParmType *TTP
355 = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
356 Depth = TTP->getDepth();
357 Index = TTP->getIndex();
358 Name = TTP->getName();
359 } else {
360 NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
361 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) {
362 Depth = TTP->getDepth();
363 Index = TTP->getIndex();
364 } else if (NonTypeTemplateParmDecl *NTTP
365 = dyn_cast<NonTypeTemplateParmDecl>(ND)) {
366 Depth = NTTP->getDepth();
367 Index = NTTP->getIndex();
368 } else {
369 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
370 Depth = TTP->getDepth();
371 Index = TTP->getIndex();
372 }
373 // FIXME: Variadic templates function parameter packs?
374 Name = ND->getIdentifier();
375 }
376
377 // If we don't have a template argument at this depth/index, then we
378 // cannot expand the pack expansion. Make a note of this, but we still
379 // want to check that any parameter packs we *do* have arguments for.
380 if (!TemplateArgs.hasTemplateArgument(Depth, Index)) {
381 ShouldExpand = false;
382 continue;
383 }
384
385 // Determine the size of the argument pack.
386 unsigned NewPackSize = TemplateArgs(Depth, Index).pack_size();
387 if (!HaveFirstPack) {
388 // The is the first pack we've seen for which we have an argument.
389 // Record it.
390 NumExpansions = NewPackSize;
391 FirstPack.first = Name;
392 FirstPack.second = Unexpanded[I].second;
393 HaveFirstPack = true;
394 continue;
395 }
396
397 if (NewPackSize != NumExpansions) {
398 // C++0x [temp.variadic]p5:
399 // All of the parameter packs expanded by a pack expansion shall have
400 // the same number of arguments specified.
401 Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
402 << FirstPack.first << Name << NumExpansions << NewPackSize
403 << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
404 return true;
405 }
406 }
407
408 return false;
409}