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