clang API Documentation
00001 //===--- TemplateBase.cpp - Common template AST class implementation ------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements common classes used throughout C++ template 00011 // representations. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "clang/AST/TemplateBase.h" 00016 #include "clang/AST/ASTContext.h" 00017 #include "clang/AST/DeclBase.h" 00018 #include "clang/AST/DeclTemplate.h" 00019 #include "clang/AST/Expr.h" 00020 #include "clang/AST/ExprCXX.h" 00021 #include "clang/AST/Type.h" 00022 #include "clang/AST/TypeLoc.h" 00023 #include "clang/Basic/Diagnostic.h" 00024 #include "llvm/ADT/FoldingSet.h" 00025 #include "llvm/ADT/SmallString.h" 00026 #include "llvm/Support/raw_ostream.h" 00027 #include <algorithm> 00028 00029 using namespace clang; 00030 00031 /// \brief Print a template integral argument value. 00032 /// 00033 /// \param TemplArg the TemplateArgument instance to print. 00034 /// 00035 /// \param Out the raw_ostream instance to use for printing. 00036 static void printIntegral(const TemplateArgument &TemplArg, 00037 raw_ostream &Out) { 00038 const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); 00039 const llvm::APSInt &Val = TemplArg.getAsIntegral(); 00040 00041 if (T->isBooleanType()) { 00042 Out << (Val.getBoolValue() ? "true" : "false"); 00043 } else if (T->isCharType()) { 00044 const char Ch = Val.getZExtValue(); 00045 Out << ((Ch == '\'') ? "'\\" : "'"); 00046 Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true); 00047 Out << "'"; 00048 } else { 00049 Out << Val; 00050 } 00051 } 00052 00053 //===----------------------------------------------------------------------===// 00054 // TemplateArgument Implementation 00055 //===----------------------------------------------------------------------===// 00056 00057 TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, 00058 QualType Type) { 00059 Integer.Kind = Integral; 00060 // Copy the APSInt value into our decomposed form. 00061 Integer.BitWidth = Value.getBitWidth(); 00062 Integer.IsUnsigned = Value.isUnsigned(); 00063 // If the value is large, we have to get additional memory from the ASTContext 00064 unsigned NumWords = Value.getNumWords(); 00065 if (NumWords > 1) { 00066 void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t)); 00067 std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t)); 00068 Integer.pVal = static_cast<uint64_t *>(Mem); 00069 } else { 00070 Integer.VAL = Value.getZExtValue(); 00071 } 00072 00073 Integer.Type = Type.getAsOpaquePtr(); 00074 } 00075 00076 TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context, 00077 const TemplateArgument *Args, 00078 unsigned NumArgs) { 00079 if (NumArgs == 0) 00080 return getEmptyPack(); 00081 00082 TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs]; 00083 std::copy(Args, Args + NumArgs, Storage); 00084 return TemplateArgument(Storage, NumArgs); 00085 } 00086 00087 bool TemplateArgument::isDependent() const { 00088 switch (getKind()) { 00089 case Null: 00090 llvm_unreachable("Should not have a NULL template argument"); 00091 00092 case Type: 00093 return getAsType()->isDependentType() || 00094 isa<PackExpansionType>(getAsType()); 00095 00096 case Template: 00097 return getAsTemplate().isDependent(); 00098 00099 case TemplateExpansion: 00100 return true; 00101 00102 case Declaration: 00103 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) 00104 return DC->isDependentContext(); 00105 return getAsDecl()->getDeclContext()->isDependentContext(); 00106 00107 case NullPtr: 00108 return false; 00109 00110 case Integral: 00111 // Never dependent 00112 return false; 00113 00114 case Expression: 00115 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() || 00116 isa<PackExpansionExpr>(getAsExpr())); 00117 00118 case Pack: 00119 for (const auto &P : pack_elements()) 00120 if (P.isDependent()) 00121 return true; 00122 return false; 00123 } 00124 00125 llvm_unreachable("Invalid TemplateArgument Kind!"); 00126 } 00127 00128 bool TemplateArgument::isInstantiationDependent() const { 00129 switch (getKind()) { 00130 case Null: 00131 llvm_unreachable("Should not have a NULL template argument"); 00132 00133 case Type: 00134 return getAsType()->isInstantiationDependentType(); 00135 00136 case Template: 00137 return getAsTemplate().isInstantiationDependent(); 00138 00139 case TemplateExpansion: 00140 return true; 00141 00142 case Declaration: 00143 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) 00144 return DC->isDependentContext(); 00145 return getAsDecl()->getDeclContext()->isDependentContext(); 00146 00147 case NullPtr: 00148 return false; 00149 00150 case Integral: 00151 // Never dependent 00152 return false; 00153 00154 case Expression: 00155 return getAsExpr()->isInstantiationDependent(); 00156 00157 case Pack: 00158 for (const auto &P : pack_elements()) 00159 if (P.isInstantiationDependent()) 00160 return true; 00161 return false; 00162 } 00163 00164 llvm_unreachable("Invalid TemplateArgument Kind!"); 00165 } 00166 00167 bool TemplateArgument::isPackExpansion() const { 00168 switch (getKind()) { 00169 case Null: 00170 case Declaration: 00171 case Integral: 00172 case Pack: 00173 case Template: 00174 case NullPtr: 00175 return false; 00176 00177 case TemplateExpansion: 00178 return true; 00179 00180 case Type: 00181 return isa<PackExpansionType>(getAsType()); 00182 00183 case Expression: 00184 return isa<PackExpansionExpr>(getAsExpr()); 00185 } 00186 00187 llvm_unreachable("Invalid TemplateArgument Kind!"); 00188 } 00189 00190 bool TemplateArgument::containsUnexpandedParameterPack() const { 00191 switch (getKind()) { 00192 case Null: 00193 case Declaration: 00194 case Integral: 00195 case TemplateExpansion: 00196 case NullPtr: 00197 break; 00198 00199 case Type: 00200 if (getAsType()->containsUnexpandedParameterPack()) 00201 return true; 00202 break; 00203 00204 case Template: 00205 if (getAsTemplate().containsUnexpandedParameterPack()) 00206 return true; 00207 break; 00208 00209 case Expression: 00210 if (getAsExpr()->containsUnexpandedParameterPack()) 00211 return true; 00212 break; 00213 00214 case Pack: 00215 for (const auto &P : pack_elements()) 00216 if (P.containsUnexpandedParameterPack()) 00217 return true; 00218 00219 break; 00220 } 00221 00222 return false; 00223 } 00224 00225 Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { 00226 assert(getKind() == TemplateExpansion); 00227 if (TemplateArg.NumExpansions) 00228 return TemplateArg.NumExpansions - 1; 00229 00230 return None; 00231 } 00232 00233 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 00234 const ASTContext &Context) const { 00235 ID.AddInteger(getKind()); 00236 switch (getKind()) { 00237 case Null: 00238 break; 00239 00240 case Type: 00241 getAsType().Profile(ID); 00242 break; 00243 00244 case NullPtr: 00245 getNullPtrType().Profile(ID); 00246 break; 00247 00248 case Declaration: 00249 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr); 00250 break; 00251 00252 case Template: 00253 case TemplateExpansion: { 00254 TemplateName Template = getAsTemplateOrTemplatePattern(); 00255 if (TemplateTemplateParmDecl *TTP 00256 = dyn_cast_or_null<TemplateTemplateParmDecl>( 00257 Template.getAsTemplateDecl())) { 00258 ID.AddBoolean(true); 00259 ID.AddInteger(TTP->getDepth()); 00260 ID.AddInteger(TTP->getPosition()); 00261 ID.AddBoolean(TTP->isParameterPack()); 00262 } else { 00263 ID.AddBoolean(false); 00264 ID.AddPointer(Context.getCanonicalTemplateName(Template) 00265 .getAsVoidPointer()); 00266 } 00267 break; 00268 } 00269 00270 case Integral: 00271 getAsIntegral().Profile(ID); 00272 getIntegralType().Profile(ID); 00273 break; 00274 00275 case Expression: 00276 getAsExpr()->Profile(ID, Context, true); 00277 break; 00278 00279 case Pack: 00280 ID.AddInteger(Args.NumArgs); 00281 for (unsigned I = 0; I != Args.NumArgs; ++I) 00282 Args.Args[I].Profile(ID, Context); 00283 } 00284 } 00285 00286 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 00287 if (getKind() != Other.getKind()) return false; 00288 00289 switch (getKind()) { 00290 case Null: 00291 case Type: 00292 case Expression: 00293 case Template: 00294 case TemplateExpansion: 00295 case NullPtr: 00296 return TypeOrValue.V == Other.TypeOrValue.V; 00297 00298 case Declaration: 00299 return getAsDecl() == Other.getAsDecl(); 00300 00301 case Integral: 00302 return getIntegralType() == Other.getIntegralType() && 00303 getAsIntegral() == Other.getAsIntegral(); 00304 00305 case Pack: 00306 if (Args.NumArgs != Other.Args.NumArgs) return false; 00307 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 00308 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 00309 return false; 00310 return true; 00311 } 00312 00313 llvm_unreachable("Invalid TemplateArgument Kind!"); 00314 } 00315 00316 TemplateArgument TemplateArgument::getPackExpansionPattern() const { 00317 assert(isPackExpansion()); 00318 00319 switch (getKind()) { 00320 case Type: 00321 return getAsType()->getAs<PackExpansionType>()->getPattern(); 00322 00323 case Expression: 00324 return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 00325 00326 case TemplateExpansion: 00327 return TemplateArgument(getAsTemplateOrTemplatePattern()); 00328 00329 case Declaration: 00330 case Integral: 00331 case Pack: 00332 case Null: 00333 case Template: 00334 case NullPtr: 00335 return TemplateArgument(); 00336 } 00337 00338 llvm_unreachable("Invalid TemplateArgument Kind!"); 00339 } 00340 00341 void TemplateArgument::print(const PrintingPolicy &Policy, 00342 raw_ostream &Out) const { 00343 switch (getKind()) { 00344 case Null: 00345 Out << "(no value)"; 00346 break; 00347 00348 case Type: { 00349 PrintingPolicy SubPolicy(Policy); 00350 SubPolicy.SuppressStrongLifetime = true; 00351 getAsType().print(Out, SubPolicy); 00352 break; 00353 } 00354 00355 case Declaration: { 00356 NamedDecl *ND = cast<NamedDecl>(getAsDecl()); 00357 Out << '&'; 00358 if (ND->getDeclName()) { 00359 // FIXME: distinguish between pointer and reference args? 00360 ND->printQualifiedName(Out); 00361 } else { 00362 Out << "(anonymous)"; 00363 } 00364 break; 00365 } 00366 00367 case NullPtr: 00368 Out << "nullptr"; 00369 break; 00370 00371 case Template: 00372 getAsTemplate().print(Out, Policy); 00373 break; 00374 00375 case TemplateExpansion: 00376 getAsTemplateOrTemplatePattern().print(Out, Policy); 00377 Out << "..."; 00378 break; 00379 00380 case Integral: { 00381 printIntegral(*this, Out); 00382 break; 00383 } 00384 00385 case Expression: 00386 getAsExpr()->printPretty(Out, nullptr, Policy); 00387 break; 00388 00389 case Pack: 00390 Out << "<"; 00391 bool First = true; 00392 for (const auto &P : pack_elements()) { 00393 if (First) 00394 First = false; 00395 else 00396 Out << ", "; 00397 00398 P.print(Policy, Out); 00399 } 00400 Out << ">"; 00401 break; 00402 } 00403 } 00404 00405 //===----------------------------------------------------------------------===// 00406 // TemplateArgumentLoc Implementation 00407 //===----------------------------------------------------------------------===// 00408 00409 TemplateArgumentLocInfo::TemplateArgumentLocInfo() { 00410 memset((void*)this, 0, sizeof(TemplateArgumentLocInfo)); 00411 } 00412 00413 SourceRange TemplateArgumentLoc::getSourceRange() const { 00414 switch (Argument.getKind()) { 00415 case TemplateArgument::Expression: 00416 return getSourceExpression()->getSourceRange(); 00417 00418 case TemplateArgument::Declaration: 00419 return getSourceDeclExpression()->getSourceRange(); 00420 00421 case TemplateArgument::NullPtr: 00422 return getSourceNullPtrExpression()->getSourceRange(); 00423 00424 case TemplateArgument::Type: 00425 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 00426 return TSI->getTypeLoc().getSourceRange(); 00427 else 00428 return SourceRange(); 00429 00430 case TemplateArgument::Template: 00431 if (getTemplateQualifierLoc()) 00432 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 00433 getTemplateNameLoc()); 00434 return SourceRange(getTemplateNameLoc()); 00435 00436 case TemplateArgument::TemplateExpansion: 00437 if (getTemplateQualifierLoc()) 00438 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 00439 getTemplateEllipsisLoc()); 00440 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 00441 00442 case TemplateArgument::Integral: 00443 return getSourceIntegralExpression()->getSourceRange(); 00444 00445 case TemplateArgument::Pack: 00446 case TemplateArgument::Null: 00447 return SourceRange(); 00448 } 00449 00450 llvm_unreachable("Invalid TemplateArgument Kind!"); 00451 } 00452 00453 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 00454 const TemplateArgument &Arg) { 00455 switch (Arg.getKind()) { 00456 case TemplateArgument::Null: 00457 // This is bad, but not as bad as crashing because of argument 00458 // count mismatches. 00459 return DB << "(null template argument)"; 00460 00461 case TemplateArgument::Type: 00462 return DB << Arg.getAsType(); 00463 00464 case TemplateArgument::Declaration: 00465 return DB << Arg.getAsDecl(); 00466 00467 case TemplateArgument::NullPtr: 00468 return DB << "nullptr"; 00469 00470 case TemplateArgument::Integral: 00471 return DB << Arg.getAsIntegral().toString(10); 00472 00473 case TemplateArgument::Template: 00474 return DB << Arg.getAsTemplate(); 00475 00476 case TemplateArgument::TemplateExpansion: 00477 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 00478 00479 case TemplateArgument::Expression: { 00480 // This shouldn't actually ever happen, so it's okay that we're 00481 // regurgitating an expression here. 00482 // FIXME: We're guessing at LangOptions! 00483 SmallString<32> Str; 00484 llvm::raw_svector_ostream OS(Str); 00485 LangOptions LangOpts; 00486 LangOpts.CPlusPlus = true; 00487 PrintingPolicy Policy(LangOpts); 00488 Arg.getAsExpr()->printPretty(OS, nullptr, Policy); 00489 return DB << OS.str(); 00490 } 00491 00492 case TemplateArgument::Pack: { 00493 // FIXME: We're guessing at LangOptions! 00494 SmallString<32> Str; 00495 llvm::raw_svector_ostream OS(Str); 00496 LangOptions LangOpts; 00497 LangOpts.CPlusPlus = true; 00498 PrintingPolicy Policy(LangOpts); 00499 Arg.print(Policy, OS); 00500 return DB << OS.str(); 00501 } 00502 } 00503 00504 llvm_unreachable("Invalid TemplateArgument Kind!"); 00505 } 00506 00507 const ASTTemplateArgumentListInfo * 00508 ASTTemplateArgumentListInfo::Create(ASTContext &C, 00509 const TemplateArgumentListInfo &List) { 00510 assert(llvm::alignOf<ASTTemplateArgumentListInfo>() >= 00511 llvm::alignOf<TemplateArgumentLoc>()); 00512 std::size_t size = ASTTemplateArgumentListInfo::sizeFor(List.size()); 00513 void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>()); 00514 ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo(); 00515 TAI->initializeFrom(List); 00516 return TAI; 00517 } 00518 00519 void ASTTemplateArgumentListInfo::initializeFrom( 00520 const TemplateArgumentListInfo &Info) { 00521 LAngleLoc = Info.getLAngleLoc(); 00522 RAngleLoc = Info.getRAngleLoc(); 00523 NumTemplateArgs = Info.size(); 00524 00525 TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); 00526 for (unsigned i = 0; i != NumTemplateArgs; ++i) 00527 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); 00528 } 00529 00530 void ASTTemplateArgumentListInfo::initializeFrom( 00531 const TemplateArgumentListInfo &Info, 00532 bool &Dependent, 00533 bool &InstantiationDependent, 00534 bool &ContainsUnexpandedParameterPack) { 00535 LAngleLoc = Info.getLAngleLoc(); 00536 RAngleLoc = Info.getRAngleLoc(); 00537 NumTemplateArgs = Info.size(); 00538 00539 TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); 00540 for (unsigned i = 0; i != NumTemplateArgs; ++i) { 00541 Dependent = Dependent || Info[i].getArgument().isDependent(); 00542 InstantiationDependent = InstantiationDependent || 00543 Info[i].getArgument().isInstantiationDependent(); 00544 ContainsUnexpandedParameterPack 00545 = ContainsUnexpandedParameterPack || 00546 Info[i].getArgument().containsUnexpandedParameterPack(); 00547 00548 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); 00549 } 00550 } 00551 00552 void ASTTemplateArgumentListInfo::copyInto( 00553 TemplateArgumentListInfo &Info) const { 00554 Info.setLAngleLoc(LAngleLoc); 00555 Info.setRAngleLoc(RAngleLoc); 00556 for (unsigned I = 0; I != NumTemplateArgs; ++I) 00557 Info.addArgument(getTemplateArgs()[I]); 00558 } 00559 00560 std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) { 00561 return sizeof(ASTTemplateArgumentListInfo) + 00562 sizeof(TemplateArgumentLoc) * NumTemplateArgs; 00563 } 00564 00565 void 00566 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc, 00567 const TemplateArgumentListInfo &Info) { 00568 Base::initializeFrom(Info); 00569 setTemplateKeywordLoc(TemplateKWLoc); 00570 } 00571 00572 void 00573 ASTTemplateKWAndArgsInfo 00574 ::initializeFrom(SourceLocation TemplateKWLoc, 00575 const TemplateArgumentListInfo &Info, 00576 bool &Dependent, 00577 bool &InstantiationDependent, 00578 bool &ContainsUnexpandedParameterPack) { 00579 Base::initializeFrom(Info, Dependent, InstantiationDependent, 00580 ContainsUnexpandedParameterPack); 00581 setTemplateKeywordLoc(TemplateKWLoc); 00582 } 00583 00584 void 00585 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { 00586 // No explicit template arguments, but template keyword loc is valid. 00587 assert(TemplateKWLoc.isValid()); 00588 LAngleLoc = SourceLocation(); 00589 RAngleLoc = SourceLocation(); 00590 NumTemplateArgs = 0; 00591 setTemplateKeywordLoc(TemplateKWLoc); 00592 } 00593 00594 std::size_t 00595 ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) { 00596 // Add space for the template keyword location. 00597 // FIXME: There's room for this in the padding before the template args in 00598 // 64-bit builds. 00599 return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation); 00600 }