DeclTemplate.cpp revision 4e3d355931542dc1a40c35c108f7e0b72876584c
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, ParameterPack, 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/// \brief Construct a template argument pack. 242TemplateArgument::TemplateArgument(SourceLocation Loc, TemplateArgument *args, 243 unsigned NumArgs, bool CopyArgs) 244 : Kind(Pack) { 245 Args.NumArgs = NumArgs; 246 Args.CopyArgs = CopyArgs; 247 if (!Args.CopyArgs) { 248 Args.Args = args; 249 return; 250 } 251 252 Args.Args = new TemplateArgument[NumArgs]; 253 for (unsigned I = 0; I != NumArgs; ++I) 254 Args.Args[I] = args[I]; 255} 256 257//===----------------------------------------------------------------------===// 258// TemplateArgumentListBuilder Implementation 259//===----------------------------------------------------------------------===// 260void TemplateArgumentListBuilder::push_back(const TemplateArgument& Arg) { 261 switch (Arg.getKind()) { 262 default: break; 263 case TemplateArgument::Type: 264 assert(Arg.getAsType()->isCanonical() && "Type must be canonical!"); 265 break; 266 } 267 268 FlatArgs.push_back(Arg); 269 270 if (!isAddingFromParameterPack()) 271 StructuredArgs.push_back(Arg); 272} 273 274void TemplateArgumentListBuilder::BeginParameterPack() { 275 assert(!isAddingFromParameterPack() && "Already adding to parameter pack!"); 276 277 PackBeginIndex = FlatArgs.size(); 278} 279 280void TemplateArgumentListBuilder::EndParameterPack() { 281 assert(isAddingFromParameterPack() && "Not adding to parameter pack!"); 282 283 unsigned NumArgs = FlatArgs.size() - PackBeginIndex; 284 TemplateArgument *Args = NumArgs ? &FlatArgs[PackBeginIndex] : 0; 285 286 StructuredArgs.push_back(TemplateArgument(SourceLocation(), Args, NumArgs, 287 /*CopyArgs=*/false)); 288 289 PackBeginIndex = std::numeric_limits<unsigned>::max(); 290} 291 292//===----------------------------------------------------------------------===// 293// TemplateArgumentList Implementation 294//===----------------------------------------------------------------------===// 295TemplateArgumentList::TemplateArgumentList(ASTContext &Context, 296 TemplateArgumentListBuilder &Builder, 297 bool CopyArgs, bool FlattenArgs) 298 : NumArguments(Builder.flatSize()) { 299 if (!CopyArgs) { 300 Arguments.setPointer(Builder.getFlatArgumentList()); 301 Arguments.setInt(1); 302 return; 303 } 304 305 306 unsigned Size = sizeof(TemplateArgument) * Builder.flatSize(); 307 unsigned Align = llvm::AlignOf<TemplateArgument>::Alignment; 308 void *Mem = Context.Allocate(Size, Align); 309 Arguments.setPointer((TemplateArgument *)Mem); 310 Arguments.setInt(0); 311 312 TemplateArgument *Args = (TemplateArgument *)Mem; 313 for (unsigned I = 0; I != NumArguments; ++I) 314 new (Args + I) TemplateArgument(Builder.getFlatArgumentList()[I]); 315} 316 317TemplateArgumentList::~TemplateArgumentList() { 318 // FIXME: Deallocate template arguments 319} 320 321//===----------------------------------------------------------------------===// 322// ClassTemplateSpecializationDecl Implementation 323//===----------------------------------------------------------------------===// 324ClassTemplateSpecializationDecl:: 325ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, 326 DeclContext *DC, SourceLocation L, 327 ClassTemplateDecl *SpecializedTemplate, 328 TemplateArgumentListBuilder &Builder) 329 : CXXRecordDecl(DK, 330 SpecializedTemplate->getTemplatedDecl()->getTagKind(), 331 DC, L, 332 // FIXME: Should we use DeclarationName for the name of 333 // class template specializations? 334 SpecializedTemplate->getIdentifier()), 335 SpecializedTemplate(SpecializedTemplate), 336 TemplateArgs(Context, Builder, /*CopyArgs=*/true, /*FlattenArgs=*/true), 337 SpecializationKind(TSK_Undeclared) { 338} 339 340ClassTemplateSpecializationDecl * 341ClassTemplateSpecializationDecl::Create(ASTContext &Context, 342 DeclContext *DC, SourceLocation L, 343 ClassTemplateDecl *SpecializedTemplate, 344 TemplateArgumentListBuilder &Builder, 345 ClassTemplateSpecializationDecl *PrevDecl) { 346 ClassTemplateSpecializationDecl *Result 347 = new (Context)ClassTemplateSpecializationDecl(Context, 348 ClassTemplateSpecialization, 349 DC, L, 350 SpecializedTemplate, 351 Builder); 352 Context.getTypeDeclType(Result, PrevDecl); 353 return Result; 354} 355 356//===----------------------------------------------------------------------===// 357// ClassTemplatePartialSpecializationDecl Implementation 358//===----------------------------------------------------------------------===// 359ClassTemplatePartialSpecializationDecl * 360ClassTemplatePartialSpecializationDecl:: 361Create(ASTContext &Context, DeclContext *DC, SourceLocation L, 362 TemplateParameterList *Params, 363 ClassTemplateDecl *SpecializedTemplate, 364 TemplateArgumentListBuilder &Builder, 365 ClassTemplatePartialSpecializationDecl *PrevDecl) { 366 ClassTemplatePartialSpecializationDecl *Result 367 = new (Context)ClassTemplatePartialSpecializationDecl(Context, 368 DC, L, Params, 369 SpecializedTemplate, 370 Builder); 371 Result->setSpecializationKind(TSK_ExplicitSpecialization); 372 Context.getTypeDeclType(Result, PrevDecl); 373 return Result; 374} 375