DeclTemplate.cpp revision 194179
1//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===// 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// 10// This file implements the C++ related Decl classes for templates. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/AST/DeclCXX.h" 15#include "clang/AST/DeclTemplate.h" 16#include "clang/AST/Expr.h" 17#include "clang/AST/ASTContext.h" 18#include "clang/Basic/IdentifierTable.h" 19#include "llvm/ADT/STLExtras.h" 20using namespace clang; 21 22//===----------------------------------------------------------------------===// 23// TemplateParameterList Implementation 24//===----------------------------------------------------------------------===// 25 26TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, 27 SourceLocation LAngleLoc, 28 Decl **Params, unsigned NumParams, 29 SourceLocation RAngleLoc) 30 : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), 31 NumParams(NumParams) { 32 for (unsigned Idx = 0; Idx < NumParams; ++Idx) 33 begin()[Idx] = Params[Idx]; 34} 35 36TemplateParameterList * 37TemplateParameterList::Create(ASTContext &C, SourceLocation TemplateLoc, 38 SourceLocation LAngleLoc, Decl **Params, 39 unsigned NumParams, SourceLocation RAngleLoc) { 40 unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams; 41 unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment; 42 void *Mem = C.Allocate(Size, Align); 43 return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params, 44 NumParams, RAngleLoc); 45} 46 47unsigned TemplateParameterList::getMinRequiredArguments() const { 48 unsigned NumRequiredArgs = size(); 49 iterator Param = const_cast<TemplateParameterList *>(this)->end(), 50 ParamBegin = const_cast<TemplateParameterList *>(this)->begin(); 51 while (Param != ParamBegin) { 52 --Param; 53 54 if (!(*Param)->isTemplateParameterPack() && 55 !(isa<TemplateTypeParmDecl>(*Param) && 56 cast<TemplateTypeParmDecl>(*Param)->hasDefaultArgument()) && 57 !(isa<NonTypeTemplateParmDecl>(*Param) && 58 cast<NonTypeTemplateParmDecl>(*Param)->hasDefaultArgument()) && 59 !(isa<TemplateTemplateParmDecl>(*Param) && 60 cast<TemplateTemplateParmDecl>(*Param)->hasDefaultArgument())) 61 break; 62 63 --NumRequiredArgs; 64 } 65 66 return NumRequiredArgs; 67} 68 69//===----------------------------------------------------------------------===// 70// TemplateDecl Implementation 71//===----------------------------------------------------------------------===// 72 73TemplateDecl::~TemplateDecl() { 74} 75 76//===----------------------------------------------------------------------===// 77// FunctionTemplateDecl Implementation 78//===----------------------------------------------------------------------===// 79 80FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, 81 DeclContext *DC, 82 SourceLocation L, 83 DeclarationName Name, 84 TemplateParameterList *Params, 85 NamedDecl *Decl) { 86 return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); 87} 88 89//===----------------------------------------------------------------------===// 90// ClassTemplateDecl Implementation 91//===----------------------------------------------------------------------===// 92 93ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, 94 DeclContext *DC, 95 SourceLocation L, 96 DeclarationName Name, 97 TemplateParameterList *Params, 98 NamedDecl *Decl, 99 ClassTemplateDecl *PrevDecl) { 100 Common *CommonPtr; 101 if (PrevDecl) 102 CommonPtr = PrevDecl->CommonPtr; 103 else 104 CommonPtr = new (C) Common; 105 106 return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl, 107 CommonPtr); 108} 109 110ClassTemplateDecl::~ClassTemplateDecl() { 111 assert(CommonPtr == 0 && "ClassTemplateDecl must be explicitly destroyed"); 112} 113 114void ClassTemplateDecl::Destroy(ASTContext& C) { 115 if (!PreviousDeclaration) { 116 CommonPtr->~Common(); 117 C.Deallocate((void*)CommonPtr); 118 } 119 CommonPtr = 0; 120 121 this->~ClassTemplateDecl(); 122 C.Deallocate((void*)this); 123} 124 125QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { 126 if (!CommonPtr->InjectedClassNameType.isNull()) 127 return CommonPtr->InjectedClassNameType; 128 129 // FIXME: n2800 14.6.1p1 should say how the template arguments 130 // corresponding to template parameter packs should be pack 131 // expansions. We already say that in 14.6.2.1p2, so it would be 132 // better to fix that redundancy. 133 134 TemplateParameterList *Params = getTemplateParameters(); 135 136 llvm::SmallVector<TemplateArgument, 16> TemplateArgs; 137 llvm::SmallVector<TemplateArgument, 16> CanonTemplateArgs; 138 TemplateArgs.reserve(Params->size()); 139 CanonTemplateArgs.reserve(Params->size()); 140 141 for (TemplateParameterList::iterator 142 Param = Params->begin(), ParamEnd = Params->end(); 143 Param != ParamEnd; ++Param) { 144 if (isa<TemplateTypeParmDecl>(*Param)) { 145 QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param)); 146 TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(), 147 ParamType)); 148 CanonTemplateArgs.push_back( 149 TemplateArgument((*Param)->getLocation(), 150 Context.getCanonicalType(ParamType))); 151 } else if (NonTypeTemplateParmDecl *NTTP = 152 dyn_cast<NonTypeTemplateParmDecl>(*Param)) { 153 // FIXME: Build canonical expression, too! 154 Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(), 155 NTTP->getLocation(), 156 NTTP->getType()->isDependentType(), 157 /*Value-dependent=*/true); 158 TemplateArgs.push_back(TemplateArgument(E)); 159 CanonTemplateArgs.push_back(TemplateArgument(E)); 160 } else { 161 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); 162 TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP)); 163 CanonTemplateArgs.push_back(TemplateArgument(TTP->getLocation(), 164 Context.getCanonicalDecl(TTP))); 165 } 166 } 167 168 // FIXME: I should really move the "build-the-canonical-type" logic 169 // into ASTContext::getTemplateSpecializationType. 170 TemplateName Name = TemplateName(this); 171 QualType CanonType = Context.getTemplateSpecializationType( 172 Context.getCanonicalTemplateName(Name), 173 &CanonTemplateArgs[0], 174 CanonTemplateArgs.size()); 175 176 CommonPtr->InjectedClassNameType 177 = Context.getTemplateSpecializationType(Name, 178 &TemplateArgs[0], 179 TemplateArgs.size(), 180 CanonType); 181 return CommonPtr->InjectedClassNameType; 182} 183 184//===----------------------------------------------------------------------===// 185// TemplateTypeParm Allocation/Deallocation Method Implementations 186//===----------------------------------------------------------------------===// 187 188TemplateTypeParmDecl * 189TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, 190 SourceLocation L, unsigned D, unsigned P, 191 IdentifierInfo *Id, bool Typename, 192 bool ParameterPack) { 193 QualType Type = C.getTemplateTypeParmType(D, P, Id); 194 return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack); 195} 196 197//===----------------------------------------------------------------------===// 198// NonTypeTemplateParmDecl Method Implementations 199//===----------------------------------------------------------------------===// 200 201NonTypeTemplateParmDecl * 202NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, 203 SourceLocation L, unsigned D, unsigned P, 204 IdentifierInfo *Id, QualType T, 205 SourceLocation TypeSpecStartLoc) { 206 return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, 207 TypeSpecStartLoc); 208} 209 210SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { 211 return DefaultArgument? DefaultArgument->getSourceRange().getBegin() 212 : SourceLocation(); 213} 214 215//===----------------------------------------------------------------------===// 216// TemplateTemplateParmDecl Method Implementations 217//===----------------------------------------------------------------------===// 218 219TemplateTemplateParmDecl * 220TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, 221 SourceLocation L, unsigned D, unsigned P, 222 IdentifierInfo *Id, 223 TemplateParameterList *Params) { 224 return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params); 225} 226 227SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const { 228 return DefaultArgument? DefaultArgument->getSourceRange().getBegin() 229 : SourceLocation(); 230} 231 232//===----------------------------------------------------------------------===// 233// TemplateArgument Implementation 234//===----------------------------------------------------------------------===// 235 236TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) { 237 TypeOrValue = reinterpret_cast<uintptr_t>(E); 238 StartLoc = E->getSourceRange().getBegin(); 239} 240 241//===----------------------------------------------------------------------===// 242// TemplateArgumentListBuilder Implementation 243//===----------------------------------------------------------------------===// 244void TemplateArgumentListBuilder::push_back(const TemplateArgument& Arg) { 245 switch (Arg.getKind()) { 246 default: break; 247 case TemplateArgument::Type: 248 assert(Arg.getAsType()->isCanonical() && "Type must be canonical!"); 249 break; 250 } 251 252 if (!isAddingFromParameterPack()) { 253 // Add begin and end indicies. 254 Indices.push_back(Args.size()); 255 Indices.push_back(Args.size()); 256 } 257 258 Args.push_back(Arg); 259} 260 261void TemplateArgumentListBuilder::BeginParameterPack() { 262 assert(!isAddingFromParameterPack() && "Already adding to parameter pack!"); 263 264 Indices.push_back(Args.size()); 265} 266 267void TemplateArgumentListBuilder::EndParameterPack() { 268 assert(isAddingFromParameterPack() && "Not adding to parameter pack!"); 269 270 Indices.push_back(Args.size()); 271} 272 273//===----------------------------------------------------------------------===// 274// TemplateArgumentList Implementation 275//===----------------------------------------------------------------------===// 276TemplateArgumentList::TemplateArgumentList(ASTContext &Context, 277 TemplateArgumentListBuilder &Builder, 278 bool CopyArgs, bool FlattenArgs) 279 : NumArguments(Builder.flatSize()) { 280 if (!CopyArgs) { 281 Arguments.setPointer(Builder.getFlatArgumentList()); 282 Arguments.setInt(1); 283 return; 284 } 285 286 287 unsigned Size = sizeof(TemplateArgument) * Builder.flatSize(); 288 unsigned Align = llvm::AlignOf<TemplateArgument>::Alignment; 289 void *Mem = Context.Allocate(Size, Align); 290 Arguments.setPointer((TemplateArgument *)Mem); 291 Arguments.setInt(0); 292 293 TemplateArgument *Args = (TemplateArgument *)Mem; 294 for (unsigned I = 0; I != NumArguments; ++I) 295 new (Args + I) TemplateArgument(Builder.getFlatArgumentList()[I]); 296} 297 298TemplateArgumentList::~TemplateArgumentList() { 299 // FIXME: Deallocate template arguments 300} 301 302//===----------------------------------------------------------------------===// 303// ClassTemplateSpecializationDecl Implementation 304//===----------------------------------------------------------------------===// 305ClassTemplateSpecializationDecl:: 306ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, 307 DeclContext *DC, SourceLocation L, 308 ClassTemplateDecl *SpecializedTemplate, 309 TemplateArgumentListBuilder &Builder) 310 : CXXRecordDecl(DK, 311 SpecializedTemplate->getTemplatedDecl()->getTagKind(), 312 DC, L, 313 // FIXME: Should we use DeclarationName for the name of 314 // class template specializations? 315 SpecializedTemplate->getIdentifier()), 316 SpecializedTemplate(SpecializedTemplate), 317 TemplateArgs(Context, Builder, /*CopyArgs=*/true, /*FlattenArgs=*/true), 318 SpecializationKind(TSK_Undeclared) { 319} 320 321ClassTemplateSpecializationDecl * 322ClassTemplateSpecializationDecl::Create(ASTContext &Context, 323 DeclContext *DC, SourceLocation L, 324 ClassTemplateDecl *SpecializedTemplate, 325 TemplateArgumentListBuilder &Builder, 326 ClassTemplateSpecializationDecl *PrevDecl) { 327 ClassTemplateSpecializationDecl *Result 328 = new (Context)ClassTemplateSpecializationDecl(Context, 329 ClassTemplateSpecialization, 330 DC, L, 331 SpecializedTemplate, 332 Builder); 333 Context.getTypeDeclType(Result, PrevDecl); 334 return Result; 335} 336 337//===----------------------------------------------------------------------===// 338// ClassTemplatePartialSpecializationDecl Implementation 339//===----------------------------------------------------------------------===// 340ClassTemplatePartialSpecializationDecl * 341ClassTemplatePartialSpecializationDecl:: 342Create(ASTContext &Context, DeclContext *DC, SourceLocation L, 343 TemplateParameterList *Params, 344 ClassTemplateDecl *SpecializedTemplate, 345 TemplateArgumentListBuilder &Builder, 346 ClassTemplatePartialSpecializationDecl *PrevDecl) { 347 ClassTemplatePartialSpecializationDecl *Result 348 = new (Context)ClassTemplatePartialSpecializationDecl(Context, 349 DC, L, Params, 350 SpecializedTemplate, 351 Builder); 352 Result->setSpecializationKind(TSK_ExplicitSpecialization); 353 Context.getTypeDeclType(Result, PrevDecl); 354 return Result; 355} 356