TemplateBase.cpp revision e559ca1672ecef59345a928af0a6809b09282d2c
1//===--- TemplateBase.cpp - Common template AST class 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 common classes used throughout C++ template 11// representations. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/AST/TemplateBase.h" 16#include "clang/AST/ASTContext.h" 17#include "clang/AST/DeclBase.h" 18#include "clang/AST/DeclTemplate.h" 19#include "clang/AST/Expr.h" 20#include "clang/AST/ExprCXX.h" 21#include "clang/AST/Type.h" 22#include "clang/AST/TypeLoc.h" 23#include "clang/Basic/Diagnostic.h" 24#include "llvm/ADT/FoldingSet.h" 25#include <algorithm> 26#include <cctype> 27 28using namespace clang; 29 30/// \brief Print a template integral argument value. 31/// 32/// \param TemplArg the TemplateArgument instance to print. 33/// 34/// \param Out the raw_ostream instance to use for printing. 35static void printIntegral(const TemplateArgument &TemplArg, 36 llvm::raw_ostream &Out) { 37 const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); 38 const llvm::APSInt *Val = TemplArg.getAsIntegral(); 39 40 if (T->isBooleanType()) { 41 Out << (Val->getBoolValue() ? "true" : "false"); 42 } else if (T->isCharType()) { 43 const unsigned char Ch = Val->getZExtValue(); 44 const std::string Str(1, Ch); 45 Out << ((Ch == '\'') ? "'\\" : "'"); 46 Out.write_escaped(Str, /*UseHexEscapes=*/ true); 47 Out << "'"; 48 } else { 49 Out << Val->toString(10); 50 } 51} 52 53//===----------------------------------------------------------------------===// 54// TemplateArgument Implementation 55//===----------------------------------------------------------------------===// 56 57TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context, 58 const TemplateArgument *Args, 59 unsigned NumArgs) { 60 if (NumArgs == 0) 61 return TemplateArgument(0, 0); 62 63 TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs]; 64 std::copy(Args, Args + NumArgs, Storage); 65 return TemplateArgument(Storage, NumArgs); 66} 67 68bool TemplateArgument::isDependent() const { 69 switch (getKind()) { 70 case Null: 71 assert(false && "Should not have a NULL template argument"); 72 return false; 73 74 case Type: 75 return getAsType()->isDependentType(); 76 77 case Template: 78 return getAsTemplate().isDependent(); 79 80 case TemplateExpansion: 81 return true; 82 83 case Declaration: 84 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) 85 return DC->isDependentContext(); 86 return getAsDecl()->getDeclContext()->isDependentContext(); 87 88 case Integral: 89 // Never dependent 90 return false; 91 92 case Expression: 93 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent()); 94 95 case Pack: 96 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) { 97 if (P->isDependent()) 98 return true; 99 } 100 101 return false; 102 } 103 104 return false; 105} 106 107bool TemplateArgument::isPackExpansion() const { 108 switch (getKind()) { 109 case Null: 110 case Declaration: 111 case Integral: 112 case Pack: 113 case Template: 114 return false; 115 116 case TemplateExpansion: 117 return true; 118 119 case Type: 120 return isa<PackExpansionType>(getAsType()); 121 122 case Expression: 123 return isa<PackExpansionExpr>(getAsExpr()); 124 } 125 126 return false; 127} 128 129bool TemplateArgument::containsUnexpandedParameterPack() const { 130 switch (getKind()) { 131 case Null: 132 case Declaration: 133 case Integral: 134 case TemplateExpansion: 135 break; 136 137 case Type: 138 if (getAsType()->containsUnexpandedParameterPack()) 139 return true; 140 break; 141 142 case Template: 143 if (getAsTemplate().containsUnexpandedParameterPack()) 144 return true; 145 break; 146 147 case Expression: 148 if (getAsExpr()->containsUnexpandedParameterPack()) 149 return true; 150 break; 151 152 case Pack: 153 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) 154 if (P->containsUnexpandedParameterPack()) 155 return true; 156 157 break; 158 } 159 160 return false; 161} 162 163llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { 164 assert(Kind == TemplateExpansion); 165 if (TemplateArg.NumExpansions) 166 return TemplateArg.NumExpansions - 1; 167 168 return llvm::Optional<unsigned>(); 169} 170 171void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 172 const ASTContext &Context) const { 173 ID.AddInteger(Kind); 174 switch (Kind) { 175 case Null: 176 break; 177 178 case Type: 179 getAsType().Profile(ID); 180 break; 181 182 case Declaration: 183 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); 184 break; 185 186 case Template: 187 case TemplateExpansion: { 188 TemplateName Template = getAsTemplateOrTemplatePattern(); 189 if (TemplateTemplateParmDecl *TTP 190 = dyn_cast_or_null<TemplateTemplateParmDecl>( 191 Template.getAsTemplateDecl())) { 192 ID.AddBoolean(true); 193 ID.AddInteger(TTP->getDepth()); 194 ID.AddInteger(TTP->getPosition()); 195 ID.AddBoolean(TTP->isParameterPack()); 196 } else { 197 ID.AddBoolean(false); 198 ID.AddPointer(Context.getCanonicalTemplateName(Template) 199 .getAsVoidPointer()); 200 } 201 break; 202 } 203 204 case Integral: 205 getAsIntegral()->Profile(ID); 206 getIntegralType().Profile(ID); 207 break; 208 209 case Expression: 210 getAsExpr()->Profile(ID, Context, true); 211 break; 212 213 case Pack: 214 ID.AddInteger(Args.NumArgs); 215 for (unsigned I = 0; I != Args.NumArgs; ++I) 216 Args.Args[I].Profile(ID, Context); 217 } 218} 219 220bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 221 if (getKind() != Other.getKind()) return false; 222 223 switch (getKind()) { 224 case Null: 225 case Type: 226 case Declaration: 227 case Expression: 228 case Template: 229 case TemplateExpansion: 230 return TypeOrValue == Other.TypeOrValue; 231 232 case Integral: 233 return getIntegralType() == Other.getIntegralType() && 234 *getAsIntegral() == *Other.getAsIntegral(); 235 236 case Pack: 237 if (Args.NumArgs != Other.Args.NumArgs) return false; 238 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 239 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 240 return false; 241 return true; 242 } 243 244 // Suppress warnings. 245 return false; 246} 247 248TemplateArgument TemplateArgument::getPackExpansionPattern() const { 249 assert(isPackExpansion()); 250 251 switch (getKind()) { 252 case Type: 253 return getAsType()->getAs<PackExpansionType>()->getPattern(); 254 255 case Expression: 256 return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 257 258 case TemplateExpansion: 259 return TemplateArgument(getAsTemplateOrTemplatePattern()); 260 261 case Declaration: 262 case Integral: 263 case Pack: 264 case Null: 265 case Template: 266 return TemplateArgument(); 267 } 268 269 return TemplateArgument(); 270} 271 272void TemplateArgument::print(const PrintingPolicy &Policy, 273 llvm::raw_ostream &Out) const { 274 switch (getKind()) { 275 case Null: 276 Out << "<no value>"; 277 break; 278 279 case Type: { 280 PrintingPolicy SubPolicy(Policy); 281 SubPolicy.SuppressStrongLifetime = true; 282 std::string TypeStr; 283 getAsType().getAsStringInternal(TypeStr, SubPolicy); 284 Out << TypeStr; 285 break; 286 } 287 288 case Declaration: { 289 bool Unnamed = true; 290 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) { 291 if (ND->getDeclName()) { 292 Unnamed = false; 293 Out << ND->getNameAsString(); 294 } 295 } 296 297 if (Unnamed) { 298 Out << "<anonymous>"; 299 } 300 break; 301 } 302 303 case Template: 304 getAsTemplate().print(Out, Policy); 305 break; 306 307 case TemplateExpansion: 308 getAsTemplateOrTemplatePattern().print(Out, Policy); 309 Out << "..."; 310 break; 311 312 case Integral: { 313 printIntegral(*this, Out); 314 break; 315 } 316 317 case Expression: 318 getAsExpr()->printPretty(Out, 0, Policy); 319 break; 320 321 case Pack: 322 Out << "<"; 323 bool First = true; 324 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end(); 325 P != PEnd; ++P) { 326 if (First) 327 First = false; 328 else 329 Out << ", "; 330 331 P->print(Policy, Out); 332 } 333 Out << ">"; 334 break; 335 } 336} 337 338//===----------------------------------------------------------------------===// 339// TemplateArgumentLoc Implementation 340//===----------------------------------------------------------------------===// 341 342TemplateArgumentLocInfo::TemplateArgumentLocInfo() { 343 memset((void*)this, 0, sizeof(TemplateArgumentLocInfo)); 344} 345 346SourceRange TemplateArgumentLoc::getSourceRange() const { 347 switch (Argument.getKind()) { 348 case TemplateArgument::Expression: 349 return getSourceExpression()->getSourceRange(); 350 351 case TemplateArgument::Declaration: 352 return getSourceDeclExpression()->getSourceRange(); 353 354 case TemplateArgument::Type: 355 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 356 return TSI->getTypeLoc().getSourceRange(); 357 else 358 return SourceRange(); 359 360 case TemplateArgument::Template: 361 if (getTemplateQualifierLoc()) 362 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 363 getTemplateNameLoc()); 364 return SourceRange(getTemplateNameLoc()); 365 366 case TemplateArgument::TemplateExpansion: 367 if (getTemplateQualifierLoc()) 368 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 369 getTemplateEllipsisLoc()); 370 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 371 372 case TemplateArgument::Integral: 373 case TemplateArgument::Pack: 374 case TemplateArgument::Null: 375 return SourceRange(); 376 } 377 378 // Silence bonus gcc warning. 379 return SourceRange(); 380} 381 382TemplateArgumentLoc 383TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, 384 llvm::Optional<unsigned> &NumExpansions, 385 ASTContext &Context) const { 386 assert(Argument.isPackExpansion()); 387 388 switch (Argument.getKind()) { 389 case TemplateArgument::Type: { 390 // FIXME: We shouldn't ever have to worry about missing 391 // type-source info! 392 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo(); 393 if (!ExpansionTSInfo) 394 ExpansionTSInfo = Context.getTrivialTypeSourceInfo( 395 getArgument().getAsType(), 396 Ellipsis); 397 PackExpansionTypeLoc Expansion 398 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); 399 Ellipsis = Expansion.getEllipsisLoc(); 400 401 TypeLoc Pattern = Expansion.getPatternLoc(); 402 NumExpansions = Expansion.getTypePtr()->getNumExpansions(); 403 404 // FIXME: This is horrible. We know where the source location data is for 405 // the pattern, and we have the pattern's type, but we are forced to copy 406 // them into an ASTContext because TypeSourceInfo bundles them together 407 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. 408 TypeSourceInfo *PatternTSInfo 409 = Context.CreateTypeSourceInfo(Pattern.getType(), 410 Pattern.getFullDataSize()); 411 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 412 Pattern.getOpaqueData(), Pattern.getFullDataSize()); 413 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), 414 PatternTSInfo); 415 } 416 417 case TemplateArgument::Expression: { 418 PackExpansionExpr *Expansion 419 = cast<PackExpansionExpr>(Argument.getAsExpr()); 420 Expr *Pattern = Expansion->getPattern(); 421 Ellipsis = Expansion->getEllipsisLoc(); 422 NumExpansions = Expansion->getNumExpansions(); 423 return TemplateArgumentLoc(Pattern, Pattern); 424 } 425 426 case TemplateArgument::TemplateExpansion: 427 Ellipsis = getTemplateEllipsisLoc(); 428 NumExpansions = Argument.getNumTemplateExpansions(); 429 return TemplateArgumentLoc(Argument.getPackExpansionPattern(), 430 getTemplateQualifierLoc(), 431 getTemplateNameLoc()); 432 433 case TemplateArgument::Declaration: 434 case TemplateArgument::Template: 435 case TemplateArgument::Integral: 436 case TemplateArgument::Pack: 437 case TemplateArgument::Null: 438 return TemplateArgumentLoc(); 439 } 440 441 return TemplateArgumentLoc(); 442} 443 444const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 445 const TemplateArgument &Arg) { 446 switch (Arg.getKind()) { 447 case TemplateArgument::Null: 448 // This is bad, but not as bad as crashing because of argument 449 // count mismatches. 450 return DB << "(null template argument)"; 451 452 case TemplateArgument::Type: 453 return DB << Arg.getAsType(); 454 455 case TemplateArgument::Declaration: 456 return DB << Arg.getAsDecl(); 457 458 case TemplateArgument::Integral: 459 return DB << Arg.getAsIntegral()->toString(10); 460 461 case TemplateArgument::Template: 462 return DB << Arg.getAsTemplate(); 463 464 case TemplateArgument::TemplateExpansion: 465 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 466 467 case TemplateArgument::Expression: { 468 // This shouldn't actually ever happen, so it's okay that we're 469 // regurgitating an expression here. 470 // FIXME: We're guessing at LangOptions! 471 llvm::SmallString<32> Str; 472 llvm::raw_svector_ostream OS(Str); 473 LangOptions LangOpts; 474 LangOpts.CPlusPlus = true; 475 PrintingPolicy Policy(LangOpts); 476 Arg.getAsExpr()->printPretty(OS, 0, Policy); 477 return DB << OS.str(); 478 } 479 480 case TemplateArgument::Pack: { 481 // FIXME: We're guessing at LangOptions! 482 llvm::SmallString<32> Str; 483 llvm::raw_svector_ostream OS(Str); 484 LangOptions LangOpts; 485 LangOpts.CPlusPlus = true; 486 PrintingPolicy Policy(LangOpts); 487 Arg.print(Policy, OS); 488 return DB << OS.str(); 489 } 490 } 491 492 return DB; 493} 494