SemaTemplateVariadic.cpp revision 8491ffe86c50241b47c6d7ef8cd9ee00f5e675da
1//===------- 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"
13#include "clang/Sema/ParsedTemplate.h"
14#include "clang/Sema/SemaInternal.h"
15#include "clang/Sema/Template.h"
16#include "clang/AST/Expr.h"
17#include "clang/AST/RecursiveASTVisitor.h"
18#include "clang/AST/TypeLoc.h"
19
20using namespace clang;
21
22//----------------------------------------------------------------------------
23// Visitor that collects unexpanded parameter packs
24//----------------------------------------------------------------------------
25
26namespace {
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
103    /// \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    }
111  };
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
153bool 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
162  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);
167  return true;
168}
169
170bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
171                                        UnexpandedParameterPackContext UPPC) {
172  // 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
178  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);
182  return true;
183}
184
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:
221    // FIXME: We shouldn't need this null check!
222    if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
223      return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC);
224
225    if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack())
226      return false;
227
228    break;
229  }
230
231  llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
232  CollectUnexpandedParameterPacksVisitor(Unexpanded)
233    .TraverseType(NameInfo.getName().getCXXNameType());
234  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
235  DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
236  return true;
237}
238
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
254void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
255                   llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
256  CollectUnexpandedParameterPacksVisitor(Unexpanded)
257    .TraverseTemplateArgumentLoc(Arg);
258}
259
260ParsedTemplateArgument
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
297  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) {
306  // 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.
310  if (!Pattern->getType()->containsUnexpandedParameterPack()) {
311    Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
312      << Pattern->getTypeLoc().getSourceRange();
313    return 0;
314  }
315
316  // Create the pack expansion type and source-location information.
317  QualType Result = Context.getPackExpansionType(Pattern->getType());
318  TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
319  PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
320  TL.setEllipsisLoc(EllipsisLoc);
321
322  // Copy over the source-location information from the type.
323  memcpy(TL.getNextTypeLoc().getOpaqueData(),
324         Pattern->getTypeLoc().getOpaqueData(),
325         Pattern->getTypeLoc().getFullDataSize());
326  return TSResult;
327}
328