SemaTemplateVariadic.cpp revision 7536dd5e6c99584481b7dab68b7e7d8df9c54054
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/AST/Expr.h" 16#include "clang/AST/RecursiveASTVisitor.h" 17#include "clang/AST/TypeLoc.h" 18 19using namespace clang; 20 21//---------------------------------------------------------------------------- 22// Visitor that collects unexpanded parameter packs 23//---------------------------------------------------------------------------- 24 25// FIXME: No way to easily map from TemplateTypeParmTypes to 26// TemplateTypeParmDecls, so we have this horrible PointerUnion. 27typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>, 28 SourceLocation> UnexpandedParameterPack; 29 30namespace { 31 /// \brief A class that collects unexpanded parameter packs. 32 class CollectUnexpandedParameterPacksVisitor : 33 public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> 34 { 35 typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> 36 inherited; 37 38 llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded; 39 40 public: 41 explicit CollectUnexpandedParameterPacksVisitor( 42 llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) 43 : Unexpanded(Unexpanded) { } 44 45 //------------------------------------------------------------------------ 46 // Recording occurrences of (unexpanded) parameter packs. 47 //------------------------------------------------------------------------ 48 49 /// \brief Record occurrences of template type parameter packs. 50 bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { 51 if (TL.getTypePtr()->isParameterPack()) 52 Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc())); 53 return true; 54 } 55 56 /// \brief Record occurrences of template type parameter packs 57 /// when we don't have proper source-location information for 58 /// them. 59 /// 60 /// Ideally, this routine would never be used. 61 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { 62 if (T->isParameterPack()) 63 Unexpanded.push_back(std::make_pair(T, SourceLocation())); 64 65 return true; 66 } 67 68 // FIXME: Record occurrences of non-type and template template 69 // parameter packs. 70 71 // FIXME: Once we have pack expansions in the AST, block their 72 // traversal. 73 74 //------------------------------------------------------------------------ 75 // Pruning the search for unexpanded parameter packs. 76 //------------------------------------------------------------------------ 77 78 /// \brief Suppress traversal into statements and expressions that 79 /// do not contain unexpanded parameter packs. 80 bool TraverseStmt(Stmt *S) { 81 if (Expr *E = dyn_cast_or_null<Expr>(S)) 82 if (E->containsUnexpandedParameterPack()) 83 return inherited::TraverseStmt(E); 84 85 return true; 86 } 87 88 /// \brief Suppress traversal into types that do not contain 89 /// unexpanded parameter packs. 90 bool TraverseType(QualType T) { 91 if (!T.isNull() && T->containsUnexpandedParameterPack()) 92 return inherited::TraverseType(T); 93 94 return true; 95 } 96 97 /// \brief Suppress traversel into types with location information 98 /// that do not contain unexpanded parameter packs. 99 bool TraverseTypeLoc(TypeLoc TL) { 100 if (!TL.getType().isNull() && TL. 101 getType()->containsUnexpandedParameterPack()) 102 return inherited::TraverseTypeLoc(TL); 103 104 return true; 105 } 106 107 /// \brief Suppress traversal of non-parameter declarations, since 108 /// they cannot contain unexpanded parameter packs. 109 bool TraverseDecl(Decl *D) { 110 if (D && isa<ParmVarDecl>(D)) 111 return inherited::TraverseDecl(D); 112 113 return true; 114 } 115 }; 116} 117 118/// \brief Diagnose all of the unexpanded parameter packs in the given 119/// vector. 120static void 121DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc, 122 Sema::UnexpandedParameterPackContext UPPC, 123 const llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { 124 llvm::SmallVector<SourceLocation, 4> Locations; 125 llvm::SmallVector<IdentifierInfo *, 4> Names; 126 llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown; 127 128 for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { 129 IdentifierInfo *Name = 0; 130 if (const TemplateTypeParmType *TTP 131 = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) 132 Name = TTP->getName(); 133 else 134 Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier(); 135 136 if (Name && NamesKnown.insert(Name)) 137 Names.push_back(Name); 138 139 if (Unexpanded[I].second.isValid()) 140 Locations.push_back(Unexpanded[I].second); 141 } 142 143 DiagnosticBuilder DB 144 = Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0) 145 << (int)UPPC 146 : Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1) 147 << (int)UPPC << Names[0] 148 : Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2) 149 << (int)UPPC << Names[0] << Names[1] 150 : S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more) 151 << (int)UPPC << Names[0] << Names[1]; 152 153 for (unsigned I = 0, N = Locations.size(); I != N; ++I) 154 DB << SourceRange(Locations[I]); 155} 156 157bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, 158 TypeSourceInfo *T, 159 UnexpandedParameterPackContext UPPC) { 160 // C++0x [temp.variadic]p5: 161 // An appearance of a name of a parameter pack that is not expanded is 162 // ill-formed. 163 if (!T->getType()->containsUnexpandedParameterPack()) 164 return false; 165 166 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; 167 CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc( 168 T->getTypeLoc()); 169 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); 170 DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded); 171 return true; 172} 173 174bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, 175 UnexpandedParameterPackContext UPPC) { 176 // C++0x [temp.variadic]p5: 177 // An appearance of a name of a parameter pack that is not expanded is 178 // ill-formed. 179 if (!E->containsUnexpandedParameterPack()) 180 return false; 181 182 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; 183 CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E); 184 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); 185 DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded); 186 return true; 187} 188 189bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, 190 UnexpandedParameterPackContext UPPC) { 191 // C++0x [temp.variadic]p5: 192 // An appearance of a name of a parameter pack that is not expanded is 193 // ill-formed. 194 if (!SS.getScopeRep() || 195 !SS.getScopeRep()->containsUnexpandedParameterPack()) 196 return false; 197 198 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; 199 CollectUnexpandedParameterPacksVisitor(Unexpanded) 200 .TraverseNestedNameSpecifier(SS.getScopeRep()); 201 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); 202 DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(), 203 UPPC, Unexpanded); 204 return true; 205} 206 207bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, 208 UnexpandedParameterPackContext UPPC) { 209 // C++0x [temp.variadic]p5: 210 // An appearance of a name of a parameter pack that is not expanded is 211 // ill-formed. 212 switch (NameInfo.getName().getNameKind()) { 213 case DeclarationName::Identifier: 214 case DeclarationName::ObjCZeroArgSelector: 215 case DeclarationName::ObjCOneArgSelector: 216 case DeclarationName::ObjCMultiArgSelector: 217 case DeclarationName::CXXOperatorName: 218 case DeclarationName::CXXLiteralOperatorName: 219 case DeclarationName::CXXUsingDirective: 220 return false; 221 222 case DeclarationName::CXXConstructorName: 223 case DeclarationName::CXXDestructorName: 224 case DeclarationName::CXXConversionFunctionName: 225 // FIXME: We shouldn't need this null check! 226 if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) 227 return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC); 228 229 if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack()) 230 return false; 231 232 break; 233 } 234 235 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; 236 CollectUnexpandedParameterPacksVisitor(Unexpanded) 237 .TraverseType(NameInfo.getName().getCXXNameType()); 238 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); 239 DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded); 240 return true; 241} 242 243bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, 244 TemplateName Template, 245 UnexpandedParameterPackContext UPPC) { 246 247 if (Template.isNull() || !Template.containsUnexpandedParameterPack()) 248 return false; 249 250 llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; 251 CollectUnexpandedParameterPacksVisitor(Unexpanded) 252 .TraverseTemplateName(Template); 253 assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); 254 DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded); 255 return true; 256} 257 258ParsedTemplateArgument 259Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, 260 SourceLocation EllipsisLoc) { 261 if (Arg.isInvalid()) 262 return Arg; 263 264 switch (Arg.getKind()) { 265 case ParsedTemplateArgument::Type: { 266 TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc); 267 if (Result.isInvalid()) 268 return ParsedTemplateArgument(); 269 270 return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), 271 Arg.getLocation()); 272 } 273 274 case ParsedTemplateArgument::NonType: 275 Diag(EllipsisLoc, diag::err_pack_expansion_unsupported) 276 << 0; 277 return ParsedTemplateArgument(); 278 279 case ParsedTemplateArgument::Template: 280 Diag(EllipsisLoc, diag::err_pack_expansion_unsupported) 281 << 1; 282 return ParsedTemplateArgument(); 283 } 284 llvm_unreachable("Unhandled template argument kind?"); 285 return ParsedTemplateArgument(); 286} 287 288TypeResult Sema::ActOnPackExpansion(ParsedType Type, 289 SourceLocation EllipsisLoc) { 290 TypeSourceInfo *TSInfo; 291 GetTypeFromParser(Type, &TSInfo); 292 if (!TSInfo) 293 return true; 294 295 // C++0x [temp.variadic]p5: 296 // The pattern of a pack expansion shall name one or more 297 // parameter packs that are not expanded by a nested pack 298 // expansion. 299 if (!TSInfo->getType()->containsUnexpandedParameterPack()) { 300 Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) 301 << TSInfo->getTypeLoc().getSourceRange(); 302 return true; 303 } 304 305 // Create the pack expansion type and source-location information. 306 QualType Result = Context.getPackExpansionType(TSInfo->getType()); 307 TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result); 308 PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc()); 309 TL.setEllipsisLoc(EllipsisLoc); 310 311 // Copy over the source-location information from the type. 312 memcpy(TL.getNextTypeLoc().getOpaqueData(), 313 TSInfo->getTypeLoc().getOpaqueData(), 314 TSInfo->getTypeLoc().getFullDataSize()); 315 return CreateParsedType(Result, TSResult); 316} 317