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