TemplateBase.cpp revision 221345
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 std::string TypeStr; 281 getAsType().getAsStringInternal(TypeStr, Policy); 282 Out << TypeStr; 283 break; 284 } 285 286 case Declaration: { 287 bool Unnamed = true; 288 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) { 289 if (ND->getDeclName()) { 290 Unnamed = false; 291 Out << ND->getNameAsString(); 292 } 293 } 294 295 if (Unnamed) { 296 Out << "<anonymous>"; 297 } 298 break; 299 } 300 301 case Template: 302 getAsTemplate().print(Out, Policy); 303 break; 304 305 case TemplateExpansion: 306 getAsTemplateOrTemplatePattern().print(Out, Policy); 307 Out << "..."; 308 break; 309 310 case Integral: { 311 printIntegral(*this, Out); 312 break; 313 } 314 315 case Expression: 316 getAsExpr()->printPretty(Out, 0, Policy); 317 break; 318 319 case Pack: 320 Out << "<"; 321 bool First = true; 322 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end(); 323 P != PEnd; ++P) { 324 if (First) 325 First = false; 326 else 327 Out << ", "; 328 329 P->print(Policy, Out); 330 } 331 Out << ">"; 332 break; 333 } 334} 335 336//===----------------------------------------------------------------------===// 337// TemplateArgumentLoc Implementation 338//===----------------------------------------------------------------------===// 339 340TemplateArgumentLocInfo::TemplateArgumentLocInfo() { 341 memset((void*)this, 0, sizeof(TemplateArgumentLocInfo)); 342} 343 344SourceRange TemplateArgumentLoc::getSourceRange() const { 345 switch (Argument.getKind()) { 346 case TemplateArgument::Expression: 347 return getSourceExpression()->getSourceRange(); 348 349 case TemplateArgument::Declaration: 350 return getSourceDeclExpression()->getSourceRange(); 351 352 case TemplateArgument::Type: 353 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 354 return TSI->getTypeLoc().getSourceRange(); 355 else 356 return SourceRange(); 357 358 case TemplateArgument::Template: 359 if (getTemplateQualifierLoc()) 360 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 361 getTemplateNameLoc()); 362 return SourceRange(getTemplateNameLoc()); 363 364 case TemplateArgument::TemplateExpansion: 365 if (getTemplateQualifierLoc()) 366 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 367 getTemplateEllipsisLoc()); 368 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 369 370 case TemplateArgument::Integral: 371 case TemplateArgument::Pack: 372 case TemplateArgument::Null: 373 return SourceRange(); 374 } 375 376 // Silence bonus gcc warning. 377 return SourceRange(); 378} 379 380TemplateArgumentLoc 381TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, 382 llvm::Optional<unsigned> &NumExpansions, 383 ASTContext &Context) const { 384 assert(Argument.isPackExpansion()); 385 386 switch (Argument.getKind()) { 387 case TemplateArgument::Type: { 388 // FIXME: We shouldn't ever have to worry about missing 389 // type-source info! 390 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo(); 391 if (!ExpansionTSInfo) 392 ExpansionTSInfo = Context.getTrivialTypeSourceInfo( 393 getArgument().getAsType(), 394 Ellipsis); 395 PackExpansionTypeLoc Expansion 396 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); 397 Ellipsis = Expansion.getEllipsisLoc(); 398 399 TypeLoc Pattern = Expansion.getPatternLoc(); 400 NumExpansions = Expansion.getTypePtr()->getNumExpansions(); 401 402 // FIXME: This is horrible. We know where the source location data is for 403 // the pattern, and we have the pattern's type, but we are forced to copy 404 // them into an ASTContext because TypeSourceInfo bundles them together 405 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. 406 TypeSourceInfo *PatternTSInfo 407 = Context.CreateTypeSourceInfo(Pattern.getType(), 408 Pattern.getFullDataSize()); 409 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 410 Pattern.getOpaqueData(), Pattern.getFullDataSize()); 411 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), 412 PatternTSInfo); 413 } 414 415 case TemplateArgument::Expression: { 416 PackExpansionExpr *Expansion 417 = cast<PackExpansionExpr>(Argument.getAsExpr()); 418 Expr *Pattern = Expansion->getPattern(); 419 Ellipsis = Expansion->getEllipsisLoc(); 420 NumExpansions = Expansion->getNumExpansions(); 421 return TemplateArgumentLoc(Pattern, Pattern); 422 } 423 424 case TemplateArgument::TemplateExpansion: 425 Ellipsis = getTemplateEllipsisLoc(); 426 NumExpansions = Argument.getNumTemplateExpansions(); 427 return TemplateArgumentLoc(Argument.getPackExpansionPattern(), 428 getTemplateQualifierLoc(), 429 getTemplateNameLoc()); 430 431 case TemplateArgument::Declaration: 432 case TemplateArgument::Template: 433 case TemplateArgument::Integral: 434 case TemplateArgument::Pack: 435 case TemplateArgument::Null: 436 return TemplateArgumentLoc(); 437 } 438 439 return TemplateArgumentLoc(); 440} 441 442const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 443 const TemplateArgument &Arg) { 444 switch (Arg.getKind()) { 445 case TemplateArgument::Null: 446 // This is bad, but not as bad as crashing because of argument 447 // count mismatches. 448 return DB << "(null template argument)"; 449 450 case TemplateArgument::Type: 451 return DB << Arg.getAsType(); 452 453 case TemplateArgument::Declaration: 454 return DB << Arg.getAsDecl(); 455 456 case TemplateArgument::Integral: 457 return DB << Arg.getAsIntegral()->toString(10); 458 459 case TemplateArgument::Template: 460 return DB << Arg.getAsTemplate(); 461 462 case TemplateArgument::TemplateExpansion: 463 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 464 465 case TemplateArgument::Expression: { 466 // This shouldn't actually ever happen, so it's okay that we're 467 // regurgitating an expression here. 468 // FIXME: We're guessing at LangOptions! 469 llvm::SmallString<32> Str; 470 llvm::raw_svector_ostream OS(Str); 471 LangOptions LangOpts; 472 LangOpts.CPlusPlus = true; 473 PrintingPolicy Policy(LangOpts); 474 Arg.getAsExpr()->printPretty(OS, 0, Policy); 475 return DB << OS.str(); 476 } 477 478 case TemplateArgument::Pack: { 479 // FIXME: We're guessing at LangOptions! 480 llvm::SmallString<32> Str; 481 llvm::raw_svector_ostream OS(Str); 482 LangOptions LangOpts; 483 LangOpts.CPlusPlus = true; 484 PrintingPolicy Policy(LangOpts); 485 Arg.print(Policy, OS); 486 return DB << OS.str(); 487 } 488 } 489 490 return DB; 491} 492