DeclTemplate.cpp revision 198398
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 NamedDecl **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, NamedDecl **Params, 39 unsigned NumParams, SourceLocation RAngleLoc) { 40 unsigned Size = sizeof(TemplateParameterList) 41 + sizeof(NamedDecl *) * NumParams; 42 unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment; 43 void *Mem = C.Allocate(Size, Align); 44 return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params, 45 NumParams, RAngleLoc); 46} 47 48unsigned TemplateParameterList::getMinRequiredArguments() const { 49 unsigned NumRequiredArgs = size(); 50 iterator Param = const_cast<TemplateParameterList *>(this)->end(), 51 ParamBegin = const_cast<TemplateParameterList *>(this)->begin(); 52 while (Param != ParamBegin) { 53 --Param; 54 55 if (!(*Param)->isTemplateParameterPack() && 56 !(isa<TemplateTypeParmDecl>(*Param) && 57 cast<TemplateTypeParmDecl>(*Param)->hasDefaultArgument()) && 58 !(isa<NonTypeTemplateParmDecl>(*Param) && 59 cast<NonTypeTemplateParmDecl>(*Param)->hasDefaultArgument()) && 60 !(isa<TemplateTemplateParmDecl>(*Param) && 61 cast<TemplateTemplateParmDecl>(*Param)->hasDefaultArgument())) 62 break; 63 64 --NumRequiredArgs; 65 } 66 67 return NumRequiredArgs; 68} 69 70//===----------------------------------------------------------------------===// 71// TemplateDecl Implementation 72//===----------------------------------------------------------------------===// 73 74TemplateDecl::~TemplateDecl() { 75} 76 77//===----------------------------------------------------------------------===// 78// FunctionTemplateDecl Implementation 79//===----------------------------------------------------------------------===// 80 81FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, 82 DeclContext *DC, 83 SourceLocation L, 84 DeclarationName Name, 85 TemplateParameterList *Params, 86 NamedDecl *Decl) { 87 return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); 88} 89 90void FunctionTemplateDecl::Destroy(ASTContext &C) { 91 if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) { 92 for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator 93 Spec = CommonPtr->Specializations.begin(), 94 SpecEnd = CommonPtr->Specializations.end(); 95 Spec != SpecEnd; ++Spec) 96 C.Deallocate(&*Spec); 97 } 98 99 Decl::Destroy(C); 100} 101 102FunctionTemplateDecl *FunctionTemplateDecl::getCanonicalDecl() { 103 FunctionTemplateDecl *FunTmpl = this; 104 while (FunTmpl->getPreviousDeclaration()) 105 FunTmpl = FunTmpl->getPreviousDeclaration(); 106 return FunTmpl; 107} 108 109FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() { 110 // Find the first declaration of this function template. 111 FunctionTemplateDecl *First = this; 112 while (First->getPreviousDeclaration()) 113 First = First->getPreviousDeclaration(); 114 115 if (First->CommonOrPrev.isNull()) { 116 // FIXME: Allocate with the ASTContext 117 First->CommonOrPrev = new Common; 118 } 119 return First->CommonOrPrev.get<Common*>(); 120} 121 122//===----------------------------------------------------------------------===// 123// ClassTemplateDecl Implementation 124//===----------------------------------------------------------------------===// 125 126ClassTemplateDecl *ClassTemplateDecl::getCanonicalDecl() { 127 ClassTemplateDecl *Template = this; 128 while (Template->getPreviousDeclaration()) 129 Template = Template->getPreviousDeclaration(); 130 return Template; 131} 132 133ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, 134 DeclContext *DC, 135 SourceLocation L, 136 DeclarationName Name, 137 TemplateParameterList *Params, 138 NamedDecl *Decl, 139 ClassTemplateDecl *PrevDecl) { 140 Common *CommonPtr; 141 if (PrevDecl) 142 CommonPtr = PrevDecl->CommonPtr; 143 else 144 CommonPtr = new (C) Common; 145 146 return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl, 147 CommonPtr); 148} 149 150ClassTemplateDecl::~ClassTemplateDecl() { 151 assert(CommonPtr == 0 && "ClassTemplateDecl must be explicitly destroyed"); 152} 153 154void ClassTemplateDecl::Destroy(ASTContext& C) { 155 if (!PreviousDeclaration) { 156 CommonPtr->~Common(); 157 C.Deallocate((void*)CommonPtr); 158 } 159 CommonPtr = 0; 160 161 this->~ClassTemplateDecl(); 162 C.Deallocate((void*)this); 163} 164 165ClassTemplatePartialSpecializationDecl * 166ClassTemplateDecl::findPartialSpecialization(QualType T) { 167 ASTContext &Context = getASTContext(); 168 typedef llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator 169 partial_spec_iterator; 170 for (partial_spec_iterator P = getPartialSpecializations().begin(), 171 PEnd = getPartialSpecializations().end(); 172 P != PEnd; ++P) { 173 if (Context.hasSameType(Context.getTypeDeclType(&*P), T)) 174 return &*P; 175 } 176 177 return 0; 178} 179 180QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { 181 if (!CommonPtr->InjectedClassNameType.isNull()) 182 return CommonPtr->InjectedClassNameType; 183 184 // FIXME: n2800 14.6.1p1 should say how the template arguments 185 // corresponding to template parameter packs should be pack 186 // expansions. We already say that in 14.6.2.1p2, so it would be 187 // better to fix that redundancy. 188 189 TemplateParameterList *Params = getTemplateParameters(); 190 llvm::SmallVector<TemplateArgument, 16> TemplateArgs; 191 TemplateArgs.reserve(Params->size()); 192 for (TemplateParameterList::iterator Param = Params->begin(), 193 ParamEnd = Params->end(); 194 Param != ParamEnd; ++Param) { 195 if (isa<TemplateTypeParmDecl>(*Param)) { 196 QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param)); 197 TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(), 198 ParamType)); 199 } else if (NonTypeTemplateParmDecl *NTTP = 200 dyn_cast<NonTypeTemplateParmDecl>(*Param)) { 201 Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(), 202 NTTP->getLocation(), 203 NTTP->getType()->isDependentType(), 204 /*Value-dependent=*/true); 205 TemplateArgs.push_back(TemplateArgument(E)); 206 } else { 207 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); 208 TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP)); 209 } 210 } 211 212 CommonPtr->InjectedClassNameType 213 = Context.getTemplateSpecializationType(TemplateName(this), 214 &TemplateArgs[0], 215 TemplateArgs.size()); 216 return CommonPtr->InjectedClassNameType; 217} 218 219//===----------------------------------------------------------------------===// 220// TemplateTypeParm Allocation/Deallocation Method Implementations 221//===----------------------------------------------------------------------===// 222 223TemplateTypeParmDecl * 224TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, 225 SourceLocation L, unsigned D, unsigned P, 226 IdentifierInfo *Id, bool Typename, 227 bool ParameterPack) { 228 QualType Type = C.getTemplateTypeParmType(D, P, ParameterPack, Id); 229 return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack); 230} 231 232//===----------------------------------------------------------------------===// 233// NonTypeTemplateParmDecl Method Implementations 234//===----------------------------------------------------------------------===// 235 236NonTypeTemplateParmDecl * 237NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, 238 SourceLocation L, unsigned D, unsigned P, 239 IdentifierInfo *Id, QualType T, 240 DeclaratorInfo *DInfo) { 241 return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, DInfo); 242} 243 244SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { 245 return DefaultArgument? DefaultArgument->getSourceRange().getBegin() 246 : SourceLocation(); 247} 248 249//===----------------------------------------------------------------------===// 250// TemplateTemplateParmDecl Method Implementations 251//===----------------------------------------------------------------------===// 252 253TemplateTemplateParmDecl * 254TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, 255 SourceLocation L, unsigned D, unsigned P, 256 IdentifierInfo *Id, 257 TemplateParameterList *Params) { 258 return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params); 259} 260 261SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const { 262 return DefaultArgument? DefaultArgument->getSourceRange().getBegin() 263 : SourceLocation(); 264} 265 266//===----------------------------------------------------------------------===// 267// TemplateArgument Implementation 268//===----------------------------------------------------------------------===// 269 270TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) { 271 TypeOrValue = reinterpret_cast<uintptr_t>(E); 272 StartLoc = E->getSourceRange().getBegin(); 273} 274 275/// \brief Construct a template argument pack. 276void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs, 277 bool CopyArgs) { 278 assert(isNull() && "Must call setArgumentPack on a null argument"); 279 280 Kind = Pack; 281 Args.NumArgs = NumArgs; 282 Args.CopyArgs = CopyArgs; 283 if (!Args.CopyArgs) { 284 Args.Args = args; 285 return; 286 } 287 288 // FIXME: Allocate in ASTContext 289 Args.Args = new TemplateArgument[NumArgs]; 290 for (unsigned I = 0; I != Args.NumArgs; ++I) 291 Args.Args[I] = args[I]; 292} 293 294//===----------------------------------------------------------------------===// 295// TemplateArgumentListBuilder Implementation 296//===----------------------------------------------------------------------===// 297 298void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) { 299 switch (Arg.getKind()) { 300 default: break; 301 case TemplateArgument::Type: 302 assert(Arg.getAsType().isCanonical() && "Type must be canonical!"); 303 break; 304 } 305 306 assert(NumFlatArgs < MaxFlatArgs && "Argument list builder is full!"); 307 assert(!StructuredArgs && 308 "Can't append arguments when an argument pack has been added!"); 309 310 if (!FlatArgs) 311 FlatArgs = new TemplateArgument[MaxFlatArgs]; 312 313 FlatArgs[NumFlatArgs++] = Arg; 314} 315 316void TemplateArgumentListBuilder::BeginPack() { 317 assert(!AddingToPack && "Already adding to pack!"); 318 assert(!StructuredArgs && "Argument list already contains a pack!"); 319 320 AddingToPack = true; 321 PackBeginIndex = NumFlatArgs; 322} 323 324void TemplateArgumentListBuilder::EndPack() { 325 assert(AddingToPack && "Not adding to pack!"); 326 assert(!StructuredArgs && "Argument list already contains a pack!"); 327 328 AddingToPack = false; 329 330 StructuredArgs = new TemplateArgument[MaxStructuredArgs]; 331 332 // First copy the flat entries over to the list (if any) 333 for (unsigned I = 0; I != PackBeginIndex; ++I) { 334 NumStructuredArgs++; 335 StructuredArgs[I] = FlatArgs[I]; 336 } 337 338 // Next, set the pack. 339 TemplateArgument *PackArgs = 0; 340 unsigned NumPackArgs = NumFlatArgs - PackBeginIndex; 341 if (NumPackArgs) 342 PackArgs = &FlatArgs[PackBeginIndex]; 343 344 StructuredArgs[NumStructuredArgs++].setArgumentPack(PackArgs, NumPackArgs, 345 /*CopyArgs=*/false); 346} 347 348void TemplateArgumentListBuilder::ReleaseArgs() { 349 FlatArgs = 0; 350 NumFlatArgs = 0; 351 MaxFlatArgs = 0; 352 StructuredArgs = 0; 353 NumStructuredArgs = 0; 354 MaxStructuredArgs = 0; 355} 356 357//===----------------------------------------------------------------------===// 358// TemplateArgumentList Implementation 359//===----------------------------------------------------------------------===// 360TemplateArgumentList::TemplateArgumentList(ASTContext &Context, 361 TemplateArgumentListBuilder &Builder, 362 bool TakeArgs) 363 : FlatArguments(Builder.getFlatArguments(), TakeArgs), 364 NumFlatArguments(Builder.flatSize()), 365 StructuredArguments(Builder.getStructuredArguments(), TakeArgs), 366 NumStructuredArguments(Builder.structuredSize()) { 367 368 if (!TakeArgs) 369 return; 370 371 if (Builder.getStructuredArguments() == Builder.getFlatArguments()) 372 StructuredArguments.setInt(0); 373 Builder.ReleaseArgs(); 374} 375 376TemplateArgumentList::TemplateArgumentList(const TemplateArgumentList &Other) 377 : FlatArguments(Other.FlatArguments.getPointer(), 1), 378 NumFlatArguments(Other.flat_size()), 379 StructuredArguments(Other.StructuredArguments.getPointer(), 1), 380 NumStructuredArguments(Other.NumStructuredArguments) { } 381 382TemplateArgumentList::~TemplateArgumentList() { 383 // FIXME: Deallocate template arguments 384} 385 386//===----------------------------------------------------------------------===// 387// ClassTemplateSpecializationDecl Implementation 388//===----------------------------------------------------------------------===// 389ClassTemplateSpecializationDecl:: 390ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, 391 DeclContext *DC, SourceLocation L, 392 ClassTemplateDecl *SpecializedTemplate, 393 TemplateArgumentListBuilder &Builder, 394 ClassTemplateSpecializationDecl *PrevDecl) 395 : CXXRecordDecl(DK, 396 SpecializedTemplate->getTemplatedDecl()->getTagKind(), 397 DC, L, 398 // FIXME: Should we use DeclarationName for the name of 399 // class template specializations? 400 SpecializedTemplate->getIdentifier(), 401 PrevDecl), 402 SpecializedTemplate(SpecializedTemplate), 403 TemplateArgs(Context, Builder, /*TakeArgs=*/true), 404 SpecializationKind(TSK_Undeclared) { 405} 406 407ClassTemplateSpecializationDecl * 408ClassTemplateSpecializationDecl::Create(ASTContext &Context, 409 DeclContext *DC, SourceLocation L, 410 ClassTemplateDecl *SpecializedTemplate, 411 TemplateArgumentListBuilder &Builder, 412 ClassTemplateSpecializationDecl *PrevDecl) { 413 ClassTemplateSpecializationDecl *Result 414 = new (Context)ClassTemplateSpecializationDecl(Context, 415 ClassTemplateSpecialization, 416 DC, L, 417 SpecializedTemplate, 418 Builder, 419 PrevDecl); 420 Context.getTypeDeclType(Result, PrevDecl); 421 return Result; 422} 423 424void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) { 425 if (SpecializedPartialSpecialization *PartialSpec 426 = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) 427 C.Deallocate(PartialSpec); 428 429 CXXRecordDecl::Destroy(C); 430} 431 432void 433ClassTemplateSpecializationDecl::getNameForDiagnostic(std::string &S, 434 const PrintingPolicy &Policy, 435 bool Qualified) const { 436 NamedDecl::getNameForDiagnostic(S, Policy, Qualified); 437 438 const TemplateArgumentList &TemplateArgs = getTemplateArgs(); 439 S += TemplateSpecializationType::PrintTemplateArgumentList( 440 TemplateArgs.getFlatArgumentList(), 441 TemplateArgs.flat_size(), 442 Policy); 443} 444 445ClassTemplateDecl * 446ClassTemplateSpecializationDecl::getSpecializedTemplate() const { 447 if (SpecializedPartialSpecialization *PartialSpec 448 = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) 449 return PartialSpec->PartialSpecialization->getSpecializedTemplate(); 450 return SpecializedTemplate.get<ClassTemplateDecl*>(); 451} 452 453//===----------------------------------------------------------------------===// 454// ClassTemplatePartialSpecializationDecl Implementation 455//===----------------------------------------------------------------------===// 456ClassTemplatePartialSpecializationDecl * 457ClassTemplatePartialSpecializationDecl:: 458Create(ASTContext &Context, DeclContext *DC, SourceLocation L, 459 TemplateParameterList *Params, 460 ClassTemplateDecl *SpecializedTemplate, 461 TemplateArgumentListBuilder &Builder, 462 ClassTemplatePartialSpecializationDecl *PrevDecl) { 463 ClassTemplatePartialSpecializationDecl *Result 464 = new (Context)ClassTemplatePartialSpecializationDecl(Context, 465 DC, L, Params, 466 SpecializedTemplate, 467 Builder, PrevDecl); 468 Result->setSpecializationKind(TSK_ExplicitSpecialization); 469 Context.getTypeDeclType(Result, PrevDecl); 470 return Result; 471} 472 473//===----------------------------------------------------------------------===// 474// FriendTemplateDecl Implementation 475//===----------------------------------------------------------------------===// 476 477FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context, 478 DeclContext *DC, 479 SourceLocation L, 480 unsigned NParams, 481 TemplateParameterList **Params, 482 FriendUnion Friend, 483 SourceLocation FLoc) { 484 FriendTemplateDecl *Result 485 = new (Context) FriendTemplateDecl(DC, L, NParams, Params, Friend, FLoc); 486 return Result; 487} 488