blob: e71c2334ca555f3827565bfbba699a37cc55369f [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
41 //------------------------------------------------------------------------
42 // Recording occurrences of (unexpanded) parameter packs.
43 //------------------------------------------------------------------------
44
45 /// \brief Record occurrences of template type parameter packs.
46 bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
47 if (TL.getTypePtr()->isParameterPack())
48 Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc()));
49 return true;
50 }
51
52 /// \brief Record occurrences of template type parameter packs
53 /// when we don't have proper source-location information for
54 /// them.
55 ///
56 /// Ideally, this routine would never be used.
57 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
58 if (T->isParameterPack())
59 Unexpanded.push_back(std::make_pair(T, SourceLocation()));
60
61 return true;
62 }
63
64 // FIXME: Record occurrences of non-type and template template
65 // parameter packs.
66
67 // FIXME: Once we have pack expansions in the AST, block their
68 // traversal.
69
70 //------------------------------------------------------------------------
71 // Pruning the search for unexpanded parameter packs.
72 //------------------------------------------------------------------------
73
74 /// \brief Suppress traversal into statements and expressions that
75 /// do not contain unexpanded parameter packs.
76 bool TraverseStmt(Stmt *S) {
77 if (Expr *E = dyn_cast_or_null<Expr>(S))
78 if (E->containsUnexpandedParameterPack())
79 return inherited::TraverseStmt(E);
80
81 return true;
82 }
83
84 /// \brief Suppress traversal into types that do not contain
85 /// unexpanded parameter packs.
86 bool TraverseType(QualType T) {
87 if (!T.isNull() && T->containsUnexpandedParameterPack())
88 return inherited::TraverseType(T);
89
90 return true;
91 }
92
93 /// \brief Suppress traversel into types with location information
94 /// that do not contain unexpanded parameter packs.
95 bool TraverseTypeLoc(TypeLoc TL) {
96 if (!TL.getType().isNull() && TL.
97 getType()->containsUnexpandedParameterPack())
98 return inherited::TraverseTypeLoc(TL);
99
100 return true;
101 }
102
Douglas Gregorcff163e2010-12-15 21:57:59 +0000103 /// \brief Suppress traversal of non-parameter declarations, since
104 /// they cannot contain unexpanded parameter packs.
105 bool TraverseDecl(Decl *D) {
106 if (D && isa<ParmVarDecl>(D))
107 return inherited::TraverseDecl(D);
108
109 return true;
110 }
Douglas Gregor9ef75892010-12-15 19:43:21 +0000111 };
112}
113
114/// \brief Diagnose all of the unexpanded parameter packs in the given
115/// vector.
116static void
117DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc,
118 Sema::UnexpandedParameterPackContext UPPC,
119 const llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
120 llvm::SmallVector<SourceLocation, 4> Locations;
121 llvm::SmallVector<IdentifierInfo *, 4> Names;
122 llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
123
124 for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
125 IdentifierInfo *Name = 0;
126 if (const TemplateTypeParmType *TTP
127 = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
128 Name = TTP->getName();
129 else
130 Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
131
132 if (Name && NamesKnown.insert(Name))
133 Names.push_back(Name);
134
135 if (Unexpanded[I].second.isValid())
136 Locations.push_back(Unexpanded[I].second);
137 }
138
139 DiagnosticBuilder DB
140 = Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0)
141 << (int)UPPC
142 : Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1)
143 << (int)UPPC << Names[0]
144 : Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2)
145 << (int)UPPC << Names[0] << Names[1]
146 : S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
147 << (int)UPPC << Names[0] << Names[1];
148
149 for (unsigned I = 0, N = Locations.size(); I != N; ++I)
150 DB << SourceRange(Locations[I]);
151}
152
Douglas Gregorc4633352010-12-15 17:38:57 +0000153bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
154 TypeSourceInfo *T,
155 UnexpandedParameterPackContext UPPC) {
156 // C++0x [temp.variadic]p5:
157 // An appearance of a name of a parameter pack that is not expanded is
158 // ill-formed.
159 if (!T->getType()->containsUnexpandedParameterPack())
160 return false;
161
Douglas Gregor9ef75892010-12-15 19:43:21 +0000162 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
163 CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
164 T->getTypeLoc());
165 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
166 DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
Douglas Gregorc4633352010-12-15 17:38:57 +0000167 return true;
168}
169
170bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
Douglas Gregor56c04582010-12-16 00:46:58 +0000171 UnexpandedParameterPackContext UPPC) {
Douglas Gregorc4633352010-12-15 17:38:57 +0000172 // C++0x [temp.variadic]p5:
173 // An appearance of a name of a parameter pack that is not expanded is
174 // ill-formed.
175 if (!E->containsUnexpandedParameterPack())
176 return false;
177
Douglas Gregor9ef75892010-12-15 19:43:21 +0000178 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
179 CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
180 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
181 DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded);
Douglas Gregorc4633352010-12-15 17:38:57 +0000182 return true;
183}
Douglas Gregor56c04582010-12-16 00:46:58 +0000184
185bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
186 UnexpandedParameterPackContext UPPC) {
187 // C++0x [temp.variadic]p5:
188 // An appearance of a name of a parameter pack that is not expanded is
189 // ill-formed.
190 if (!SS.getScopeRep() ||
191 !SS.getScopeRep()->containsUnexpandedParameterPack())
192 return false;
193
194 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
195 CollectUnexpandedParameterPacksVisitor(Unexpanded)
196 .TraverseNestedNameSpecifier(SS.getScopeRep());
197 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
198 DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(),
199 UPPC, Unexpanded);
200 return true;
201}
202
203bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
204 UnexpandedParameterPackContext UPPC) {
205 // C++0x [temp.variadic]p5:
206 // An appearance of a name of a parameter pack that is not expanded is
207 // ill-formed.
208 switch (NameInfo.getName().getNameKind()) {
209 case DeclarationName::Identifier:
210 case DeclarationName::ObjCZeroArgSelector:
211 case DeclarationName::ObjCOneArgSelector:
212 case DeclarationName::ObjCMultiArgSelector:
213 case DeclarationName::CXXOperatorName:
214 case DeclarationName::CXXLiteralOperatorName:
215 case DeclarationName::CXXUsingDirective:
216 return false;
217
218 case DeclarationName::CXXConstructorName:
219 case DeclarationName::CXXDestructorName:
220 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor099ffe82010-12-16 17:19:19 +0000221 // FIXME: We shouldn't need this null check!
Douglas Gregor0762bfd2010-12-16 01:40:04 +0000222 if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
223 return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC);
224
225 if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack())
Douglas Gregor56c04582010-12-16 00:46:58 +0000226 return false;
Douglas Gregor0762bfd2010-12-16 01:40:04 +0000227
Douglas Gregor56c04582010-12-16 00:46:58 +0000228 break;
229 }
230
231 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
232 CollectUnexpandedParameterPacksVisitor(Unexpanded)
Douglas Gregor0762bfd2010-12-16 01:40:04 +0000233 .TraverseType(NameInfo.getName().getCXXNameType());
Douglas Gregor56c04582010-12-16 00:46:58 +0000234 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
235 DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
236 return true;
237}
Douglas Gregor6f526752010-12-16 08:48:57 +0000238
239bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
240 TemplateName Template,
241 UnexpandedParameterPackContext UPPC) {
242
243 if (Template.isNull() || !Template.containsUnexpandedParameterPack())
244 return false;
245
246 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
247 CollectUnexpandedParameterPacksVisitor(Unexpanded)
248 .TraverseTemplateName(Template);
249 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
250 DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
251 return true;
252}
253
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000254void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
255 llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
256 CollectUnexpandedParameterPacksVisitor(Unexpanded)
257 .TraverseTemplateArgumentLoc(Arg);
258}
259
Douglas Gregor7536dd52010-12-20 02:24:11 +0000260ParsedTemplateArgument
261Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
262 SourceLocation EllipsisLoc) {
263 if (Arg.isInvalid())
264 return Arg;
265
266 switch (Arg.getKind()) {
267 case ParsedTemplateArgument::Type: {
268 TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc);
269 if (Result.isInvalid())
270 return ParsedTemplateArgument();
271
272 return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
273 Arg.getLocation());
274 }
275
276 case ParsedTemplateArgument::NonType:
277 Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
278 << 0;
279 return ParsedTemplateArgument();
280
281 case ParsedTemplateArgument::Template:
282 Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
283 << 1;
284 return ParsedTemplateArgument();
285 }
286 llvm_unreachable("Unhandled template argument kind?");
287 return ParsedTemplateArgument();
288}
289
290TypeResult Sema::ActOnPackExpansion(ParsedType Type,
291 SourceLocation EllipsisLoc) {
292 TypeSourceInfo *TSInfo;
293 GetTypeFromParser(Type, &TSInfo);
294 if (!TSInfo)
295 return true;
296
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000297 TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc);
298 if (!TSResult)
299 return true;
300
301 return CreateParsedType(TSResult->getType(), TSResult);
302}
303
304TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
305 SourceLocation EllipsisLoc) {
Douglas Gregor7536dd52010-12-20 02:24:11 +0000306 // C++0x [temp.variadic]p5:
307 // The pattern of a pack expansion shall name one or more
308 // parameter packs that are not expanded by a nested pack
309 // expansion.
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000310 if (!Pattern->getType()->containsUnexpandedParameterPack()) {
Douglas Gregor7536dd52010-12-20 02:24:11 +0000311 Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000312 << Pattern->getTypeLoc().getSourceRange();
313 return 0;
Douglas Gregor7536dd52010-12-20 02:24:11 +0000314 }
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000315
Douglas Gregor7536dd52010-12-20 02:24:11 +0000316 // Create the pack expansion type and source-location information.
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000317 QualType Result = Context.getPackExpansionType(Pattern->getType());
Douglas Gregor7536dd52010-12-20 02:24:11 +0000318 TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
319 PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
320 TL.setEllipsisLoc(EllipsisLoc);
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000321
Douglas Gregor7536dd52010-12-20 02:24:11 +0000322 // Copy over the source-location information from the type.
323 memcpy(TL.getNextTypeLoc().getOpaqueData(),
Douglas Gregor8491ffe2010-12-20 22:05:00 +0000324 Pattern->getTypeLoc().getOpaqueData(),
325 Pattern->getTypeLoc().getFullDataSize());
326 return TSResult;
Douglas Gregor7536dd52010-12-20 02:24:11 +0000327}