blob: 057792914b28063f9081ed4510880d3e0d6264e5 [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"
13#include "clang/Sema/SemaInternal.h"
14#include "clang/AST/Expr.h"
Douglas Gregor9ef75892010-12-15 19:43:21 +000015#include "clang/AST/RecursiveASTVisitor.h"
Douglas Gregorc4633352010-12-15 17:38:57 +000016#include "clang/AST/TypeLoc.h"
17
18using namespace clang;
19
Douglas Gregor9ef75892010-12-15 19:43:21 +000020//----------------------------------------------------------------------------
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
Douglas Gregorcff163e2010-12-15 21:57:59 +0000106 /// \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 }
Douglas Gregor9ef75892010-12-15 19:43:21 +0000114 };
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
Douglas Gregorc4633352010-12-15 17:38:57 +0000156bool 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
Douglas Gregor9ef75892010-12-15 19:43:21 +0000165 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);
Douglas Gregorc4633352010-12-15 17:38:57 +0000170 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
Douglas Gregor9ef75892010-12-15 19:43:21 +0000181 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);
Douglas Gregorc4633352010-12-15 17:38:57 +0000185 return true;
186}