SemaTemplateVariadic.cpp revision cff163e3cc78277496b30fa40070b46abdc290db
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/SemaInternal.h"
14#include "clang/AST/Expr.h"
15#include "clang/AST/RecursiveASTVisitor.h"
16#include "clang/AST/TypeLoc.h"
17
18using namespace clang;
19
20//----------------------------------------------------------------------------
21// Visitor that collects unexpanded parameter packs
22//----------------------------------------------------------------------------
23
24// FIXME: No way to easily map from TemplateTypeParmTypes to
25// TemplateTypeParmDecls, so we have this horrible PointerUnion.
26typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,
27                  SourceLocation> UnexpandedParameterPack;
28
29namespace {
30  /// \brief A class that collects unexpanded parameter packs.
31  class CollectUnexpandedParameterPacksVisitor :
32    public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
33  {
34    typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
35      inherited;
36
37    llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
38
39  public:
40    explicit CollectUnexpandedParameterPacksVisitor(
41                  llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
42      : Unexpanded(Unexpanded) { }
43
44    //------------------------------------------------------------------------
45    // Recording occurrences of (unexpanded) parameter packs.
46    //------------------------------------------------------------------------
47
48    /// \brief Record occurrences of template type parameter packs.
49    bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
50      if (TL.getTypePtr()->isParameterPack())
51        Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc()));
52      return true;
53    }
54
55    /// \brief Record occurrences of template type parameter packs
56    /// when we don't have proper source-location information for
57    /// them.
58    ///
59    /// Ideally, this routine would never be used.
60    bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
61      if (T->isParameterPack())
62        Unexpanded.push_back(std::make_pair(T, SourceLocation()));
63
64      return true;
65    }
66
67    // FIXME: Record occurrences of non-type and template template
68    // parameter packs.
69
70    // FIXME: Once we have pack expansions in the AST, block their
71    // traversal.
72
73    //------------------------------------------------------------------------
74    // Pruning the search for unexpanded parameter packs.
75    //------------------------------------------------------------------------
76
77    /// \brief Suppress traversal into statements and expressions that
78    /// do not contain unexpanded parameter packs.
79    bool TraverseStmt(Stmt *S) {
80      if (Expr *E = dyn_cast_or_null<Expr>(S))
81        if (E->containsUnexpandedParameterPack())
82          return inherited::TraverseStmt(E);
83
84      return true;
85    }
86
87    /// \brief Suppress traversal into types that do not contain
88    /// unexpanded parameter packs.
89    bool TraverseType(QualType T) {
90      if (!T.isNull() && T->containsUnexpandedParameterPack())
91        return inherited::TraverseType(T);
92
93      return true;
94    }
95
96    /// \brief Suppress traversel into types with location information
97    /// that do not contain unexpanded parameter packs.
98    bool TraverseTypeLoc(TypeLoc TL) {
99      if (!TL.getType().isNull() && TL.
100          getType()->containsUnexpandedParameterPack())
101        return inherited::TraverseTypeLoc(TL);
102
103      return true;
104    }
105
106    /// \brief Suppress traversal of non-parameter declarations, since
107    /// they cannot contain unexpanded parameter packs.
108    bool TraverseDecl(Decl *D) {
109      if (D && isa<ParmVarDecl>(D))
110        return inherited::TraverseDecl(D);
111
112      return true;
113    }
114  };
115}
116
117/// \brief Diagnose all of the unexpanded parameter packs in the given
118/// vector.
119static void
120DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc,
121                                 Sema::UnexpandedParameterPackContext UPPC,
122             const llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
123  llvm::SmallVector<SourceLocation, 4> Locations;
124  llvm::SmallVector<IdentifierInfo *, 4> Names;
125  llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
126
127  for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
128    IdentifierInfo *Name = 0;
129    if (const TemplateTypeParmType *TTP
130          = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
131      Name = TTP->getName();
132    else
133      Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
134
135    if (Name && NamesKnown.insert(Name))
136      Names.push_back(Name);
137
138    if (Unexpanded[I].second.isValid())
139      Locations.push_back(Unexpanded[I].second);
140  }
141
142  DiagnosticBuilder DB
143    = Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0)
144                           << (int)UPPC
145    : Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1)
146                           << (int)UPPC << Names[0]
147    : Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2)
148                           << (int)UPPC << Names[0] << Names[1]
149    : S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
150        << (int)UPPC << Names[0] << Names[1];
151
152  for (unsigned I = 0, N = Locations.size(); I != N; ++I)
153    DB << SourceRange(Locations[I]);
154}
155
156bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
157                                           TypeSourceInfo *T,
158                                         UnexpandedParameterPackContext UPPC) {
159  // C++0x [temp.variadic]p5:
160  //   An appearance of a name of a parameter pack that is not expanded is
161  //   ill-formed.
162  if (!T->getType()->containsUnexpandedParameterPack())
163    return false;
164
165  llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
166  CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
167                                                              T->getTypeLoc());
168  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
169  DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
170  return true;
171}
172
173bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
174                                           UnexpandedParameterPackContext UPPC) {
175  // C++0x [temp.variadic]p5:
176  //   An appearance of a name of a parameter pack that is not expanded is
177  //   ill-formed.
178  if (!E->containsUnexpandedParameterPack())
179    return false;
180
181  llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
182  CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
183  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
184  DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded);
185  return true;
186}
187