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